How send javasript with Express? - javascript

I want to return javascript with an Express server, not html document,
I tried
const express = require('express');
const app = express();
app.get('/', (req, res) => {
res.type('.js');
res.send("var danny = new Human();");
});
app.listen(5000, () => {
console.log('Example app listening at http://localhost:5000');
});
but I just get <pre>var danny = new Human();</pre> as html response :/
Thank you for your help :)

You're misinterpreting the result. You are sending JS to the browser. The browser just isn't doing what you expect with it.
If you type the URL of some JS into the address bar of the browser, then it will generate an HTML document to display that script's source code.
Browsers will only execute JS if it is loaded with a <script> element in an HTML document (or via a browser extension).

Edit:
You can use res.sendFile(__dirname + "path/to/file.js")

Related

Use Actions SDK for Google Assistant

I am trying to use Actions SDK in my own Server, the actions that I made are showed in Google Assistant, but it's not working, the assistant just closes without showing any errors. This is my code:
'use strict';
const express = require('express');
const bodyParser = require('body-parser');
var exps = express();
exps.use(bodyParser.json());
const {actionssdk} = require('actions-on-google');
const app = actionssdk({debug: true});
const asyncTask = () => new Promise(
resolve => setTimeout(resolve, 1000)
);
exps.post('/', function(request, response) {
app.intent('actions.intent.MAIN', (conv) => {
return asyncTask()
.then(() => conv.ask('Hi, this is a test!'));
});
});
express().use(bodyParser.json(), app).listen(3000);
Request and Debug tabs
Both Errors and Response are empty.
I think the issue is that you are creating two different express objects. One gets mounted on the '/' path, but isn't setup to listen on any port. The other listens on a port, but doesn't have any paths setup for it to handle.
Changing your listener line to
exps.use(bodyParser.json(), app).listen(3000);
will make it so the express object where you've setup the '/' path will also be the one listening on the port.
It also appears that your webhook is listening at the '/' path, but you've specified the webhook in your actions.json file as using the '/node/' path. (It is a little difficult to read the screen shot - which is why we request you post the text and not a screen shot.) If you either change your webhook to listen to '/node/' or change the actions.json file to use '/', it should work.
Looking at the documentation (https://developers.google.com/actions/assistant/responses) suggests that you are attempting to call conv.ask() incorrectly. I would imagine you'd need something like this:
conv.ask(new SimpleResponse({speech: 'Hi, this is a test!', text: 'Hi, this is a test!'}));

Getting data from/writing data to localhost with Express

I'm trying to create a webapp for a web art class using node (w/ npm) and express. The idea is to have the body of the site be all one color, but anyone can text the site a hexcode/CSS color at a Twilio number and the color of the site will instantly change to that color value.
Essentially how it works is the server receives a POST request from Twilio at http://example.com/message, which contains the body of the text message. It writes it to a temporary file at ~/app/.data/color.tmp, which is accessed by the client with a jQuery .get() call to http://example.com/color, which returns
So here's the problem: I got a version of the app working on glitch.me, so I know that this code can work, but I'm having a lot of trouble getting it to work on my domain. I installed the app and can start it with npm, and it successfully shows me the HTML page, but the Chrome devtools show the script is receiving a 403 when it tries to access /color. Also, new texts to my site aren't changing the color value in /.data/color.tmp. I thought it might be a permissions issue but I checked them and they seem fine.
Here's the server file and the script on the index.html page:
app/server.js
var express = require('express');
var bodyParser = require('body-parser');
var fs = require('fs');
var app = express();
app.use(bodyParser.urlencoded({extended: false}));
var dataPath = '.data/color.tmp';
// set a new color (saves posted color to disk)
app.post("/message", function (request, response) {
var dataStr = JSON.stringify(request.body.Body);
fs.writeFile(dataPath, dataStr);
response.end();
});
// get the saved color (reading from disk)
app.get("/color", function (request, response) {
var dataStr = fs.readFileSync(dataPath).toString();
response.send(JSON.parse(dataStr));
});
app.get("/", function (request, response) {
response.sendFile(__dirname + '/views/index.html');
});
var listener = app.listen(process.env.PORT, function () {
console.log('listening on port ' + listener.address().port);
});
app/views/index.html
<script>
// checks server for color value and sets background
function checkForColorChange() {
$.get('/color', function getColorComplete(data) {
document.body.style.backgroundColor = data;
console.log(data);
})
}
// Poll the server at 2000ms interval
setInterval(checkForColorChange, 2000);
checkForColorChange();
</script>
Anyway, I feel like I must be missing something really obvious if it worked so easily on Glitch and won't on my website, but I've been stuck for a few days and am not making any progress! Any help would be so appreciated. Let me know if anything's unclear too.
(See update below for a working example)
TL;DR - example:
Original answer
There are few problems with your code:
you're not checking for errors
you're using blocking functions
you're implicitly relying on file permissions but you're not checking it
you're using string concatenation instead of path.join to join paths
you're constantly polling for new data instead of waiting for it to change
you're not catching exceptions of functions that can raise exception
you're not waiting for async operations to finish and you don't handle errors
The main problem that you're experiencing right now is most likely with the file permissions. The good news is that you don't need any file access for what you're doing and using files for that is not optimal anyway. All you need is to store the color in a variable if you don't need it it persist between server restarts - and even if you do then I would use a simple database for that.
For example:
// some initial value:
var color = '#ffffff';
app.post("/message", function (request, response) {
var color = request.body.Body;
response.end();
});
// get the saved color (reading from disk)
app.get("/color", function (request, response) {
response.send(color);
});
app.get("/", function (request, response) {
response.sendFile(__dirname + '/views/index.html');
});
var listener = app.listen(process.env.PORT, function () {
console.log('listening on port ' + listener.address().port);
});
This is the first change that I would use - don't rely on the file system, permissions, race conditions etc.
Another problem that you had with your code was using blocking functions inside of request handlers. You should never use any blocking function (those with "Sync" in their name) except the first tick of the event loop.
Another improvement that I would make would be using WebSocket or Socket.io instead of polling for data on regular intervals. This would be quite easy to code. See this answer for examples:
Differences between socket.io and websockets
A plus of doing that would be that all of your students would get the color changed instantly and at the same time instead of in random moments spanning 2 seconds.
Update
I wrote an example of what I was describing above.
The POST endpoint is slightly different - it uses /color route and color=#abcdef instead of /message and Body=... but you can easily change it if you want - see below.
Server code - server.js:
// requires removed for brevity
const app = express();
const server = http.Server(app);
const io = socket(server);
let color = '#ffffff';
app.use(bodyParser.urlencoded({ extended: false }));
app.use('/', express.static(path.join(__dirname, 'html')));
io.on('connection', (s) => {
console.log('Socket.io client connected');
s.emit('color', color);
});
app.post('/color', (req, res) => {
color = req.body.color;
console.log('Changing color to', color);
io.emit('color', color);
res.send({ color });
});
server.listen(3338, () => console.log('Listening on 3338'));
HTML page - index.html:
<!doctype html>
<html lang=en>
<head>
<meta charset=utf-8>
<meta name=viewport content="width=device-width, initial-scale=1">
<title>Node Live Color</title>
<link href="/style.css" rel=stylesheet>
</head>
<body>
<h1>Node Live Color</h1>
<script src="/socket.io/socket.io.js"></script>
<script src="/script.js"></script>
</body>
</html>
Style sheet - style.css:
body {
transition: background-color 2s ease;
background-color: #fff;
}
Client-side JavaScript - script.js:
var s = io();
s.on('color', function (color) {
document.body.style.backgroundColor = color;
});
What is particularly interesting is how simple is the client side code.
For your original endpoint use this in server.js:
app.post('/message', (req, res) => {
color = req.body.Body;
console.log('Changing color to', color);
io.emit('color', color);
res.end();
});
Full example is available on GitHub:
https://github.com/rsp/node-live-color
I tested it locally and on Heroku. You can click this button to deploy it on Heroku and test yourself:
Enjoy.
I think, the problem is in var dataStr = fs.readFileSync(dataPath).toString();. Please change your dataPath as follow:
var dataPath = __dirname + '/data/color.tmp';
And also make sure that file has read/write permission by the .

Chrome and Node.js: sometimes the page doesn't load

I developed a small web application using Node.js. The core part of the server is:
var http = require('http');
var https = require("https");
var privateKey = fs.readFileSync("sslcert/server.key", "utf8");
var certificate = fs.readFileSync("sslcert/server.crt", "utf8");
var credentials = { key: privateKey, cert: certificate};
var httpServer = http.createServer(app);
var httpsServer = https.createServer(credentials, app);
httpServer.listen(80);
httpsServer.listen(443);
...
var app = express();
var routes = require('./routes/index');
app.use(function https(req, res, next){
if (!req.secure) return res.redirect("https://" + req.headers.host + req.url);
next();
});
app.use('/', routes);
...
var router = express.Router();
router.get("/", function (req, res, next) {
res.render("index");
});
It works and also redirect the incoming http connections to the https server.
With Chrome for Android, sometimes (I didn't find any criteria) it doesn't load anything (i.e. no activity is shown on the server logs) or it partially loads a page - no errors though. In both case the browser shows a blank page. Refreshing multiple times ofter leads to a normal loading. In few cases I had to exit and run again Chrome.
With Firefox for Android, it always works.
I'm afraid there are some differences between browsers I'm not aware of.
Where should I look? At the Node.js server code, or in the main "index" view?
Currently I'm testing the server in LAN.
UPDATE
After debugging a bit I found that there are errors in the console when the page is not loaded (it makes sense, indeed!).
Uncaught Error: undefinedModule
at _f (https://192.168.178.53/javascripts/dojo/dojo.js:8:436)
at _16 (https://192.168.178.53/javascripts/dojo/dojo.js:8:7573)
at req (https://192.168.178.53/javascripts/dojo/dojo.js:8:555)
at _9 (https://192.168.178.53/javascripts/dojox/mobile/parser.js:11:42)
at _7.parse (https://192.168.178.53/javascripts/dojox/mobile/parser.js:102:4)
at https://192.168.178.53/:66:12
at _ce (https://192.168.178.53/javascripts/dojo/dojo.js:8:11949)
at _37 (https://192.168.178.53/javascripts/dojo/dojo.js:8:13569)
at https://192.168.178.53/javascripts/dojo/dojo.js:8:13833
at _38 (https://192.168.178.53/javascripts/dojo/dojo.js:8:13659)
and
Uncaught TypeError: Cannot read property 'set' of undefined
at https://192.168.178.53/:315:33
at _ce (https://192.168.178.53/javascripts/dojo/dojo.js:8:11949)
at _37 (https://192.168.178.53/javascripts/dojo/dojo.js:8:13569)
at https://192.168.178.53/javascripts/dojo/dojo.js:8:13833
at _38 (https://192.168.178.53/javascripts/dojo/dojo.js:8:13659)
at _81 (https://192.168.178.53/javascripts/dojo/dojo.js:8:13758)
at _f6 (https://192.168.178.53/javascripts/dojo/dojo.js:8:15537)
at HTMLScriptElement._10b (https://192.168.178.53/javascripts/dojo/dojo.js:8:18464)
The only references to my code are at line 66 and line 315.
Line 66 is just the parser invocation in the head section:
require([
"dojox/mobile/parser",
"dojox/mobile/View",
"dojox/mobile/Button",
"dojox/mobile/TextBox",
"dojox/mobile/RoundRect",
"dojox/mobile/FilteredListMixin",
"dojox/mobile/TextArea",
"dojox/mobile/Switch",
"dojox/mobile/FormLayout",
"dojox/mobile/SimpleDialog",
"dojo/domReady!"
], function (parser) {
parser.parse();
});
while line 315 is included in this short snippet, executed on startup:
var userName = JSON.parse(localStorage.getItem("userName"));
if (userName != undefined && userName.length) {
registry.byId("txtName").set("value", userName); // line 315
}
As far I as understand the console error is saying it "cannot read property (?!) set of undefined". Set is a method anyway.
I guess it doesn't find the txtName widget. It is defined as:
input#txtName.login(type="text" data-dojo-type="dojox/mobile/TextBox" data-dojo-props="selectOnClick:true, placeHolder:'Username'" name="name" required)
and the snippet above as dojo/domReady! as last item of the require array.
It appears weird to me because FireFox doesn't throw such errors.
Do you see any evidence of wrong code here?

Connect to socket-io already defined in index.js using external node script

I am using hapijs in my MEAN stack and implemented socket.io (using this for reference: http://matt-harrison.com/using-hapi-js-with-socket-io/) Everything works fine, no problems there. It works great in my application!
However, there will be script I will be running via command line separately (which will be doing some maintenance on the application) that I was hoping to connect to the same web socket and be able to push to clients messages if data needs to be refreshed.
My index.js taken straight from the example:
var Hapi = require('hapi');
var server = new Hapi.Server();
server.connection({ port: 3000 });
var io = require('socket.io')(server.listener);
io.on('connection', function (socket) {
socket.emit('Hello');
});
server.start();
I tried to create a separate JS file, and do a:
var socket = require('socket.io');
var io = socket.listen(3000);
Then passed io to send a message. This doesn't seem right... I guess I'm wondering if this can even be done. Messing around I've either created a separate web socket or no connection to the client.
Please let me know if I need to provide more information.
Thanks.
T
In your provided code, you're creating 2 servers. [io.listen()][1] listens on a port as a server.
What you need to do instead to pass messages around is to create a socket.io client in your separate script. There's a separate module for this called socket.io-client, which you can require to be a client:
client.js
var io = require('socket.io-client');
var socket = io('http://localhost:3000');
socket.on('beep', function () {
console.log('beep');
socket.emit('boop');
});
server.js
Here's a slightly updated version of your server script too (hapi v9.0.0 has a mandatory callback for server.start()):
var Hapi = require('hapi');
var server = new Hapi.Server();
server.connection({ port: 3000 });
var io = require('socket.io')(server.listener);
io.on('connection', function (socket) {
socket.emit('beep');
socket.on('boop', function () {
console.log('boop');
});
});
server.start(function () {
console.log('Started Server!');
});
If you open up a couple of terminals and run these, you should see messages passed between them and beep and boop logged out:

socket io Websocket Disconnected Node js

I am actually facing an issue here. I am having a login page From there I am going to another page. From there I am getting my socket disconnected.
What i am trying to do is
In my server side app.js
app.post('/login', urlencodedParser, function(req, res) {
req.session.username = req.body.usr;
req.session.password = req.body.pass;
req.session.password = 380;
authenticatAPI.logIn(req, res);
});
From here then to authenticate js(server side)
getUserName = req.body.usr;
getPassword = req.body.pass;
req.session.username = getUserName;
req.session.password = getPassword;
res.send({url:"screen1.html",id:100,usr:getUserName});
From here to client side
var socket = io.connect('http://localhost:8080');
When i reach here Again it goes for app.js and goes inside the io.on("connection") function ,here I am getting an error when i debug using node inspect.
"Remote debugging stopped Websocket closed reattach new target"
What should i do here....?
I'm going to bet that you have node inspect set to break on caught exceptions. Try unchecking "Pause On Caught Exceptions" near the right hand side of the debugger.
Otherwise, you are likely using a 3rd party library that is using socket.io that is throwing this error.

Categories