Reputation: 773
I'm fairly new to web development and have just started on node and express 4.9.0.
Already went through some tutorials and played around with the API. From what I understand, http protocol and request urls are the backbone of a web app. For example, we have to manipulate the url to redirect the user to another page or upload files. POST is for submitting data and GET is for requesting data. Also, response.send()
is for sending server's response back to client. We also must have response.end()
at the end, according to nodejs docs (I assume this is the same for express).
Coming to the express part - here are some examples I tried and do not understand why they're not working:
1. Calling response.send() in two places
Motivation: To find out what exactly does response.send() do, and can I send different parts of information to client in different places.
I expected express to process the first app.get, then follow the next() to our next app.get. Finally, output "Welcome to the homepage!" and "Welcome to the second page!". However, the app crashed with net::ERR_EMPTY_RESPONSE
. Why is that so?
var express = require("express");
var http = require("http");
var app = express();
app.all("*", function(request, response, next) {
response.writeHead(200, { "Content-Type": "text/plain" });
next();
});
app.get("/", function(request, response, next) {
response.send("Welcome to the homepage!");
next();
});
app.get("/", function(request, response) {
response.end("Welcome to the second page!");
});
app.get("*", function(request, response) {
response.end("404!");
});
http.createServer(app).listen(1337);
2. When to use app.get and app.set?
Tried interchanging them and they often have similar behaviours.
For instance, if we remove the erronous response.send()
in the first example, it successfully finds the next app.get
with parameter "/"
. This also works if we replace app.get
with app.set
3. Redirecting
Tried redirecting to another external site, or another page of my site, but got net::ERR_EMPTY_RESPONSE
app.all("*", function(request, response, next) {
response.writeHead(200, { "Content-Type": "text/plain" });
next();
});
app.get("/", function(request, response) {
response.redirect("http://google.com");
//also does not work with response.redirect("/about);
});
app.get("/about", function(request, response) {
response.end("about page");
});
4. Why do we need express routers? Read that there's been a breaking change in routers from express 3.x to 4.x. Using 4.9.0 here.
var router = express.Router([options]);
The synatx and api for routers is almost the same as using plain old var app = express();
The documentation also says Routers behave like middleware themselves and can be ".use()'d" by the app or in other routers.
Isn't the normal express already a middleware in itself, and we can use it to do routing?
Upvotes: 1
Views: 3223
Reputation: 6665
Each http request made to the node.js server expects a single response, after which the connection is ended. If you want to send multiple pieces of information you can open up a websocket connection (http://socket.io/ - makes this very easy). http://maxogden.com/node-streams.html
response.send([status], body)
is an alternative to response.end()
(more information)
From the node.js docs:
response.end([data], [encoding])
This method signals to the server that all of the response headers and body have been sent; that server should consider this message complete. The method, response.end(), MUST be called on each response.
If data is specified, it is equivalent to calling response.write(data, encoding) followed by response.end().
If this wasn't the case, every time a http request is made, the requester doesn't know when to stop listening for a response and disaster ensues.
If you want to send various pieces of information from different places (i.e. from different places within your application), I would recommend collection all the information from said various places and then wrapping up and sending the information in one fell swoop.
Use app.set
when you want to set application wide property and use app.get
when you want to retrieve said property's value.
.e.g app.set('port', config.port);
and then later on app.listen(app.get('port'), function(){ ... });
In my opinion the use of app.get('/', function(req, res){ ... })
is a confusing piece of over-loading.
I believe a better option use something of this format:
app.route('/my-objects')
.get(function(request, response){ /* handle get request (maybe get a list of said objects) */ })
.post(function(request, response){ /* handle post request (maybe create a new object)*/ })
.put(function(request, response){ /* handle put request */ })
.delete(function(request, response){ /* handle delete request */ });
or better still imo (although this is just how I like to structure a project)
app.route('/my-objects')
.get(require('./routes/my-objects/get'))
.put(require('./routes/my-objects/put'))
...
In your example you're always going to have a problem redirecting because you're trying to set the response code twice (which node doesn't allow). Once as 200 (OK), and then once when you attempt to redirect the request which is a 302 response code by default.
This in isolation (i.e. given that the 200 response code isn't set) works:
app.get("/", function(request, response) {
response.redirect('http://google.com');
});
We don't. My take on express routers it that
var router = express.Router([options]);
...
app.use('/calendar', router);
can be used to partition up particular parts of, say, an API and arrange your code in a manner that suits you.
I think the example above (using app.route('/something').get(...)
) will likely serve you well enough for the time being.
Best of luck
Upvotes: 3