I'm trying to build a simple chat app using node and socket.io. I am following the tutorial listed here: http://socket.io/get-started/chat/
My issues is that the tutorial has some javascript that is placed in a script tag directly in the html. I would like to move this code into it's own js file.
I made a file called chat.js, that is in the same directory as my index.html and index.js. In my html I put the following code in the header (I also tried right before the ending body tag too)
<script type="text/javascript" src="chat.js"></script>
However, when I run node index.js in terminal and go to localhost, I get a 400 for chat.js. I've tried placing "/chat.js" as well as "./chat.js" with no luck. All three files are in the same directory.
Any clues to what I am doing wrong will be appreciated.
My index.js
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
app.get('/', function(req, res){
res.sendFile(__dirname + '/index.html');
});
io.on('connection', function(socket){
socket.on('chat message', function(msg){
io.emit('chat message', msg);
});
});
http.listen(3000, function(){
console.log('listening on *:3000');
});
node.js does not automatically serve any files like other web servers do. If you want it to send chat.js when the browser requests it, you will have to create a route for it in your node.js code so that the web server will send it.
If you use something like the Express framework, this can be done in perhaps one line of code with app.use(express.static(...)).
Notice how in the demo you linked to, there's a specific route for the / path. You need a similar route for /chat.js or you could use app.use(express.static(...)) to configure the automatic serving of a whole directory of files.
In the future, if you show your actual server code, then we could help more specifically with actual code that fits into your server.
Now that you've shown your code, you could add a specific route for /chat.js:
app.get('/chat.js', function(req, res){
res.sendFile(__dirname + '/chat.js');
});
Or, if you move chat.js to be in a public sub-directory under your app code, then you could serve all files in that directory automatically with this:
app.use(express.static('public'));
When Express gets a request for a route that doesn't have a specific handler, it will check the public sub-directory to see if a file matches the request name. If so, it will automatically serve that file.
Related
I'm trying to send different html files to users, with index.html being a bunch of hyperlinks that a user can click on to see that file, but I get an error that says "cannot GET (that file's name)" whenever I click on a hyperlink.
var app = require('express')();
var http = require('http').createServer(app);
app.get('/', function(req, res){
res.sendFile(__dirname + '/index.html');
});
http.listen(3000, function(){
console.log('listening on *:3000');
});
Here's my index.html:
<html>
Pong Game
</html>
You can define a public static file folder like this:
app.use(express.static(__dirname + '/public'));
Everything you have in your public folder will be accessible at the root of your URL (i.e. /pongClient.html)
Basically you have to setup the node server so that it knows where to get the file from and You can setup a static server in this case. The syntax in express can be found here
To serve static files such as images, CSS files, and JavaScript files, use the express.static built-in middleware function in Express.
var app = require('express')();
var http = require('http').createServer(app);
app.use(express.static(__dirname)) //since the index.html and probably pongClient.html are in the current directory based on your code.
http.listen(3000, function(){
console.log('listening on *:3000');
});
Nodejs has nothing to do with hyperlink. But if you want your user to access different page use
app.get('/', function(req, res){
res.send('<p>Pong Game</p>\n');
});
The port number is 80(I am assuming your web server port is 80).Mainly you have to give full URL(accessible ones).
I am currently working on a project which uses socket.io with NodeJS to control something else. This is my code so far:
var express = require('express');
var app = express();
var http = require('http').Server(app);
var io = require('socket.io')(http);
var fs = require('fs');
var contents = fs.readFileSync("data.json");
var remoteLayout = JSON.parse(contents);
app.get('/', function(req, res) {
res.sendFile(__dirname + '/index.html');
});
app.get('/edit', function(req, res) {
res.sendFile(__dirname + '/edit.html');
});
app.use(express.static(__dirname));
io.on('connection', function(socket) {
console.log('a user connected');
socket.on('disconnect', function() {
console.log('user disconnected');
});
});
http.listen(8080, function() {
console.log('listening on *:8080');
});
It is my code shortened to the parts which are relevant.
So my question is, when I run this code in node, and I open the page [myIPAddress]:8080 it opens up index.html like it should and at the top of Chrome, it says [myIPAddress]:8080. Now if I to the bar which shows the page's URL at the top, and change that to [myIPAddress]:8080/handler.js it opens a page with my js script printed out on it. How do I make it so that the person cannot go to that [myIPAddress]:8080/handler.js page?
I'm not sure if it matters, but the folder with the main.js file has also index.html, edit.html, and handler.js.
The problem is this:
app.use(express.static(__dirname));
When you do that, you've exposed all files in the __dirname directory for anyone to see including your server files that are located in that directory. Instead, you should move your static files that you intend for the public to have access to to some other directory and then use:
app.use(express.static(someOtherPath));
This will keep your server files in __dirname private and expose only the files you intend to be public that you have located in someOtherPath.
If handler.js is actually intended for use in your web pages and thus must be made available to the browser, then you cannot prevent anyone from looking at it. If your webpage needs to use it, then the browser must be able to download it and if the browser must be able to download it, then you cannot prevent a person from seeing it. You can do all sorts of things like obscure it to make it less intelligible to a person, but to any determined hacker, the logic will still all be there and you can't hide any Javascript intended to run in a browser.
Logic that you want to protect MUST be only on your server, perhaps usable via Ajax calls. You can't keep code secret that must run in a browser.
I am starting to learn node.js, for now I am just trying to execute my old none node app with node. In this app, I have a html page with a body calling an onload js function. It's working just fine.
Now I have a a node app: app.js, simple as that:
var express = require ('express');
var app = express ();
app.use(express.static(__dirname + '/images'));
app.use(express.static(__dirname + '/CSS'));
app.use(express.static(__dirname + '/font'));
app.use(express.static(__dirname ));
app.use(express.static(__dirname +'/ketcher'));
app.use(express.static(__dirname +'/ChemAlive_JS'));
app.get('/', function(req, res) {
res.sendFile('/home/laetitia/Project/ChemAlive_Interface_Node/ChemAlive_Interface.html');
});
app.listen(8080);
And in the .html I still have:
<body onload="ketcher.init();">
but the function I want to load is not load at all anymore.
Any clue?
Thanks
You have not provided a lot of info in the question but from what you provide I can have few suggestions:
Suggestions
Instead of adding a lot of express.static uses:
app.use(express.static(__dirname + '/images'));
app.use(express.static(__dirname + '/CSS'));
app.use(express.static(__dirname + '/font'));
app.use(express.static(__dirname ));
app.use(express.static(__dirname +'/ketcher'));
app.use(express.static(__dirname +'/ChemAlive_JS'));
put those files (and directories) that you want to be served into one directory, e.g. called static, and use express.static once:
app.use(express.static(__dirname + '/static'));
or better yet, using the path module:
app.use(express.static(path.join(__dirname, 'static')));
you need to require the path module first with:
var path = require('path');
Now, instead of serving the single file for the '/' route with:
app.get('/', function(req, res) {
res.sendFile('/home/laetitia/Project/ChemAlive_Interface_Node/ChemAlive_Interface.html');
});
just put that file into the static directory as index.html so it will be served by the express.static middleware automatically.
Rationale
The way you have it configured currently, is that e.g. everyone can download your Node application - app.js with all of its configuration and even submodules etc.
Also, by using the express.static middleware many times I suspect that you are not sure how the files in those directories will be mapped to URLs.
Having a one place for static files makes it easy to verify whether any script tags have correct paths etc.
My guess
You don't provide enough info to be sure but my guess is that the JavaScript files for the main HTML file are not loaded correctly but you provide not enough info to be sure.
You can open the developer tools console in the browser and reload the page while the console is open and see for errors.
I suspect that the ketcher.init() method is being run but either the method, or the ketcher object is undefined, because some <script> tags failed to be loaded.
Example
The full example after following my suggestions would be much simpler:
var path = require('path');
var express = require ('express');
var app = express();
app.use(express.static(path.join(__dirname, 'static')));
app.listen(8080);
Maybe I would add some output to see what's going on:
var path = require('path');
var express = require ('express');
console.log('starting app.js');
var app = express();
app.use(express.static(path.join(__dirname, 'static')));
app.listen(8080, function () {
console.log('listening on http://localhost:8080/');
});
And now you will have all files that can be served to the browser in one place: in the static directory in this example.
Working app
You can see my example of a working Express application serving static files on GitHub:
https://github.com/rsp/node-express-static-example
In this example the directory for static files is called html but you can call it how you want, as long as it's consistent with how you use the express.static middleware.
You can start from this example project and just put your own files into the directory where express.static is told to look for files to serve.
You can also change the port number to match your needs.
More examples to do the same with and without Express, plus better explanation:
https://github.com/rsp/node-static-http-servers
More hints
The onload callback may not be fired if the page is waiting for some resources to load.
To see if your onload callback is firing you can change it to:
<body onload="alert('onload callback fired');">
Also the ketcher object may be not initialized or it may not have the init() method. After the page is loaded you can open the JavaScript Console and try running the method manually to see if it would work if it was fired:
ketcher.init();
You can also try commands like:
console.dir(ketcher.init);
console.dir(ketcher);
console.log(typeof ketcher.init);
console.log(typeof ketcher);
to see if the ketcher object contains what it should.
Even if the GET localhost:8080/ketcher.js gives a 200 OK status, it can still load some other resources that are not available or, as is very common with code that serve files with res.sendFile() (though unlikely in this case), it can serve HTML instead of JavaScript and result in a cryptic parse error on the < character - see this question for example:
Uncaught (in promise) SyntaxError: Unexpected token < in JSON at position 0 while acess static files in node server
Other related answers:
How to serve an image using nodejs
Failed to load resource from same directory when redirecting Javascript
Sending whole folder content to client with express
Loading partials fails on the server JS
Node JS not serving the static image
I am writing a "todolist" application. In my node.js code I make use of express and give it access to my folder called Client:
var app = express();
app.use(express.static(__dirname + "/Client"));
In my Client folder is the following:
codeJS.js
homepage.html
Todolistpage.html
style.css
logo.jpg
How can I prevent a user to not be able to view my Todolistpage.html file when they type in localhost:3000/Todolistpage.html (without removing Todolistpage.html from my Client folder)?
(Ideally later on I try to only allow users logged in to view it)
It's probably easier if you don't serve the file statically and handle it as part of the view logic. So you would just remove it from the public directory and handle it separately with app.get() or router.get() middleware. Is there a reason why you need to serve it statically?
You could do something like this:
var app = express();
app.get('/Todolistpage.html, function(req, res) {
return res.status(401).end();
});
app.use(express.static(__dirname + '/Client');
This isn't ideal as you'll have to change it anytime the file name changes, and have to do it individually for each file.
You could also have a different directory /secure and some middleware for user auth like:
app.use('/secure', someAuth, express.static(__dirname + '/secure'));
or even...
app.use('/secure', someAuth, express.static(__dirname + '/Client/secure'));
but that seems confusing to me.
Is there a way to hide files that are being served by the Node server? I have tried to reroute certain files and directories, but nothing is working in Express 4.X. I have also tried to send 4XX HTTP responses when certain files are requested, but this only works for directory paths. No matter what I do, if there is a file that is being served by Node, then the user is going to be able to see the source code. Is this just how Express works? Is it meant to be a development framework over a production framework?
Right now I am trying to send bad responses.
full server.js
var path = require('path'),
express = require('express'),
var app = express();
app.use('/', express.static(__dirname));
app.use('/', express.static('dist'));
// not working
app.get('/client/config/app.js', function(req, res) {
res.sendStatus(400);
});
app.listen(3001, function() {
console.log('listening');
});
I am able to send a response if I specify a directory path, but not if I specify a full file path. This works:
app.get('/client/config/', function(req, res) {
res.sendStatus(400);
});
And this doesn't:
app.get('/client/config/app.js', function(req, res) {
res.sendStatus(400);
});
I've also tried routing with app.use. That didn't work either.
The best thing I can do right now to "hide" the source code is to uglify it with Gulp, but I imagine it's easy to unravel it with a JS prettifier.
one line culprit
app.use('/', express.static(__dirname));
That line is saying its ok to pull anything. You could replace it with:
app.use('/', express.static(__dirname + '/public'));
Then put stuff in the public directory you want viewed. For routes you want to have as priority, place them before the other declarations. So you would place:
app.get('/client/config/app.js', function(req, res) {
res.sendStatus(400);
});
above all else. However, seems like you may not need it if you just fix the first problem, then you are good. Also, see HTTP status codes. You would probably want 404 or 403 for that type of file.
http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html