Is Express.js platform-independent? - javascript

I'm just starting out with Express.js. In the official getting started guide, they showed the following basic code:
var express = require('express')
var app = express()
// respond with "hello world" when a GET request is made to the homepage
app.get('/', function (req, res) {
res.send('hello world')
})
The first parameter to app.get() is a forward-slash indicating the root directory. But the slash is a backward-slash in windows systems. Does express deal with these differences automatically, or do we need to write extra code for it? When I was using the http module, I did have to consider and correct for these differences. Thanks for the help!

app.get('/', ...) declares a handler for when an HTTP GET request is made to the URL path /. E.g. http://localhost:8080/. It has nothing to do with file paths on the server’s file system. If you use any functions that do take a file path, you may have to account for the differences between Windows and *NIX, that depends on the function.

Related

What is this express variable is doing?

I recently started learning JS and I am a basic programming background previously but always stuck on OOPs concepts.
So here we are importing I think the express module by writing the required (express). But I don't understand why we are storing this in a variable.
Likewise then storing express() in app variable then using app variable to do some stuff.
I mean how's this is working? What is What in this code block? Please explain in detail.
Thanks in advance.
const express = require('express')
const { createReadStream } = require('fs')
const app = express()
app.get('/' , (req,res) => {
createReadStream('index.html').pipe(res)
})
Line 1: You import the express node module that you installed with npm i express and store it in a constant (const).
Line 2: You import the function or variable createReadStream from the file system module of node.js (fs module) and make it available for use in this file.
Line 3 you assign the express() function from the express module above to a constant called app, so you now have everything express related available to you on the app constant.
Line 4-5: You use the get method from the express() function you have stored in the app constant, and create a route for the base url of your app / (e.g. domain.com/ or localhost:8000/). If you request something from the server you send a GET request. If you send some data use POST or PUT, for example, the express() function in app have these methods for you to use, too (app.post for example).
When Postman or a regular user with a browser hits this part of your domain (route) with a GET request, the arrow function on line 4 (req, res) => kicks in. It takes in the request (req) and the result (res) parameters so you can use those inside of the function if you wish. On the req parameter you have available whatever is in the body the user sends in from a form, for example. In your case your route streams back a html file to the user via http in order to display it in the user's browser.

Why is my Express server responding with 404 for all files except index.html?

I'm learning Node.js with Express to get a little server running for studying. I'm getting response code 404 for all requests to files linked in my index.html file (e.g. the .css, .js, and image files).
The code I used to send index.html:
routes.get('/', (req, res) => {
res.sendFile(path.join(__dirname, "/clientSide/index.html"));
})
If I change the path to the whole folder instead:
routes.get('/', (req, res) => {
res.sendFile(path.join(__dirname, "/clientSide"));
})
I get in my browser the path from my hard drive to the folder, but I still can't view the files that way.
The clientSide folder contains index.html, app.js, style.css, and 2 or 3 images, all in the same folder. I can't view any of them.
I changed the filenames and folder name, and checked for capitalization to no avail.
SOLVED
I was using app.use(express.static(path.join(__dirname, "static/")));
With app = express();
That does not work, but using routes.use instead of app.use, while routes = express.Router();, is what solves that
The end
In your first code snippet, when you write:
routes.get('/', (req, res) => {
res.sendFile(path.join(__dirname, "/clientSide/index.html"));
})
You defined a new middleware function for requests to route /; that's what routes.get('/', ...) does. Assuming your server is running on port 3000, route / maps to http://127.0.0.1:3000/. For exactly that URL, and no other, Express executes your provided function, which replies with the the file clientSide/index.html. Thus, when your browser requests http://127.0.0.1:3000/, Express responds correctly.
But you've said nothing about the other files, such as http://127.0.0.1:3000/style.css, which would be route /style.css. You haven't defined any middleware for that route. So Express, not knowing what to do, by default responds with 404 and an error message. Thus, when your browser tries to load http://127.0.0.1:3000/style.css while fetching the resources referenced in index.html, the stylesheet fails to load.
Your second code snippet doesn't fix anything. It really makes things worse, because res.sendFile() can't send folders (how would that even work?) and that generates errors. You still haven't defined routes other than /, and now all your files are inaccessible.
To actually solve the problem, you could, theoretically, tediously define a route for every file, or more cleverly define one route with a route parameter. But serving a static folder with Express is a solved problem. You can simply offload the work to express.static by replacing all your code with:
routes.use(express.static(path.join(__dirname, "clientSide/")));
To go even further, you don't need Express or Node.js for a static file server. Try nginx. And for simple webpages, you don't need a server at all; just double-click index.html and let your browser open it.

onload js call not working with node

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

How to make a redirect (301) in Node.js / Express?

I have a static site, a simple single page layout that I deploy in Dokku. I need to make a redirect (301) from www to non www and from *.website1.com to website2.com, but I don't know how. I was trying to use express-force-domain in npm but it makes my URL's crazy and having some redirect loops, I was trying other methods that I find on the web but none succeeds.
my server.js is:
var express = require('express')
var app = express();
app.set('port', (process.env.PORT || 80))
app.use(express.static(__dirname + '/public'))
app.get('/', function(request, response) {
response.send('Hello World!')
})
app.listen(app.get('port'), function() {
console.log("Node app is running at localhost:" + app.get('port'))
})
That is the version that works, but without redirects.
res.redirect(301, 'http://yourotherdomain.com' + req.path)
See Express documentation.
To anyone arriving here from Google, while #frederic's answer is still what is recommended by the express docs, the response.send(status, body) style has been deprecated and will generate a warning (I am on express 4.13.4 at time of writing), and more importantly I found that it no longer produced the desired result when redirecting.
As #Markasoftware mentioned, to achieve an automatically followed 301, you need to set the location header to the url you want. The request body can be empty:
response.set('location', 'https://my.redirect.location');
response.status(301).send()
As far as I understand it, to set an HTTP 301 code, you would set the response code to be 301 and then set the Location header to whatever url you want it to redirect to. I don't think this is the preferred way to do www to non-www urls though

Okay to add a route to Node.js Express while listening?

Obviously the typical example of adding routes to express follows something like the following:
var express = require('express');
var app = express();
app.get('/', function(req, res){
res.send('hello world');
});
app.listen(3000);
Clearly, in most cases you know the get route exists before the server begins listening. But what if you want to dynamically create new routes once the server is listening? In other words, I want to do something like the following:
var express = require('express');
var app = express();
app.listen(3000, function () {
app.get('/', function(req, res){
res.send('hello world');
});
});
In practice the callback of the route would obviously be pulled dynamically from some remote source. I've tested the above code and everything appears to function properly, however, I was hoping to get confirmation that there wouldn't be any unintended side-effects of creating routes after app.listen is called before I move forward with this pattern.
Note: To clarify, I don't know what the routes will be when I write the main server.js file that will be creating the express server (hence why I can't create the routes before listen is called). The list of routes (and their respective handlers/callback functions) will be pulled from a database while the server is starting up/running.
According to TJ (author of Express), it’s okay to add routes at runtime.
The main gotcha is going to be that routes are evaluated in the order they were added, so routes added at runtime will have a lower precedence than routes added earlier. This may or may not matter, depending on your API design.

Categories