Here, we would be extending / simplifying our server that we had made in our last post here.
Objectives –
- We had a static URL handler which was invoked when URL pattern had /static/. It made the design very specific and not generic.
- Need to make sure that in case there is no URL pattern handler for a given URL, a file for same name must be looked. If there is no such file, just raise 404 error.
Lets first update our server.js to handle only mappings.
var http = require('http'), url = require('url'); function start(dispatch, handlers) { http.createServer(function(req, res) { var _url = url.parse(req.url).pathname; dispatch(handlers, _url, req, res); }).listen(8888); console.log("Server started !! "); } exports.start = start;
Does looks sweet with simple code. The dispatch method will now take care of all mappings as well as static file readings. Below is the code for dispatch as defined from our controller –
var staticHandler = require('./staticHandler'); function dispatch(handler, pathname, req, res) { console.log("About to dispatch a request for " + pathname); var content = "Hey "+pathname; if (typeof handler[pathname] === 'function') { content += handler[pathname](req); res.writeHead(200, {'Content-Type': 'text/html'}); res.write(content); res.end(); } else { console.log("No request handler found for " + pathname); staticHandler.handleStatic(pathname, res); } }
What we have done here is just checked if there is a URL handler for a given pattern, in case we find it, we invoke it. Else we just pass the request to our static handler.
That’s it. Our server is now capable of handling any request. There is no pressure for you to put your static files in static directory on the server. Your middle ware server will take care of everything.
The updated code can be downloaded from this link.
5 Comments
majestic · August 24, 2012 at 6:41 pm
I truly wanted to send a quick message in order to appreciate you for all of the marvelous techniques you are giving out on this site. My rather long internet lookup has at the end been paid with sensible facts and strategies to talk about with my classmates and friends. I would suppose that many of us visitors are very fortunate to be in a fantastic website with very many brilliant people with very helpful tricks. I feel somewhat blessed to have used your website and look forward to some more awesome times reading here. Thank you once more for a lot of things.
Ravi · August 29, 2012 at 1:44 pm
Hey – Thats a good read, though just a thought why wouldn’t you include Mime types while sending the response ?
Thanks
Supal Dubey · August 31, 2012 at 3:14 am
Hi Ravi –
Modern browsers are smart enough to pick up Mime. I avoided sending MIME type because I did not wanted someone to use wrong mime type.
Mayur Ahir · August 30, 2012 at 12:03 pm
Hey Ravi,
I am getting this
Server started !!
About to dispatch a request for /static/images/lion.jpg
No request handler found for /static/images/lion.jpg
About to read /static/images/lion.jpg
File /var/www/node/static/static/images/lion.jpg
About to read /static/images/lion.jpg
About to dispatch a request for /static/images/
No request handler found for /static/images/
About to read /static/images/
File /var/www/node/static/static/images/
About to read /static/images/
stream.js:81
throw er; // Unhandled stream error in pipe.
^
Error: EISDIR, read
Supal Dubey · August 31, 2012 at 3:12 am
Hi Mayur –
You would need to modify your staticFile Handler to handle directories as well.
path.exists(filename, function(exists) {
if(!exists) {
console.log("not exists: " + filename);
response.writeHead(404, {'Content-Type': 'text/html'});
response.write('404 Not Found\n');
response.end();
return;
}
if(!fs.lstatSync(filename).isDirectory())
{
console.log("About to read "+pageUrl);
var fileStream = fs.createReadStream(filename);
response.writeHead(200);
fileStream.pipe(response);
}
else
{
response.writeHead(302, {'location': 'index.html'});
}
response.end();
I have currently used the lstatSync method which is synchronous as we would need to know if the path is directory before we proceed. You can also use lstat or stat which are Async methods.
Also I have used response headers to forward such directory requests to index.html, you can choose any other options you like.
PS: Do not forget to include response.end();
-Supal