Is writeHead a non blocking IO command?

I am writing a code to load a page for the client. A piece of the code is:

response.writeHead(301, {"Location": "/login/index.html"});
response.end("");

The question is if I have a slow client called A, does this code block the event loop for other clients? Or it can handle other events while the A is waiting for the page to be loaded?

I read in a book that it's better to use pipe method, like the following code:

var fs = require('fs');
var rs = fs.createReadStream('/login/index.html');
rs.pipe(response);

which one is better to be used?

No, writeHead does not invlove I/O. It does not read or write from network/disk. It simply writes into response (http.ServerResponse object), which resides in the memory. Each response you create/send is a separate object. You can call it only once per response, so writeHead cannot block. The http.ServerResponse implements a Writable Stream interface for synchronization.

To answer your question it cannot block a client loading page, unlike SQL queries which need to be ordered/serialized, writeHead requires trivial synchronization.

The pipe() method that you have read, is certainly better but only with respect to synchronous file reads and for fewer file reads. If you do readFileSync which is synchronous, will force a disk read and will block the execution of rest of node server. So if you use this you cannot execute anything (do something meaningful) while file is being read.

But say you do use it. Then for every request the file will be read from disk asynchronously but still, which becomes unnecessary if the file is not changing. Reading it to memory once then using it for further requests is sensible. It is best to employ caches which perform read only when it changes on disk for static files.

So it is better to use a static file server like one express has. See this.

No, writeHead is not synchronous, it does not block the event loop. I would not advise using pipe in the particular example. I have 2 reasons for that:

  1. /login/index.html, being a static file, can be cached, hence lower network transfer. Useful especially with slow client connections.
  2. Consistency: the login url is always the same. But this is a matter of taste :)

As @spotirca has already pointed out, response.writeHead() isn't cached, but I think it's worth expanding on the other aspect of this question, the use of pipe().

pipe() is actually a red herring here, the issue is whether to redirect to use the existing HTTP response or to start a new cycle. It's important to understand that the two solutions do very different things.

301 Redirect

response.writeHead(301, {"Location": "/login/index.html"});
response.end("");

This responds to the browser with a permanent redirect, i.e. tells that browser that the current URL should always redirect to the specified URL. If you're redirecting a user to the login page based on their session state then this is absolutely wrong, as the browser would be justified in caching the redirect and causing undesirable behaviour.

Streaming

require('fs').createReadStream('/login/index.html').pipe(response);

This would work, but would mean that the login page would be served on whatever the current URL is. You'd also be breaking from standard HTTP behaviour by serving different content on the same URL, so as @spotirca points this would have repercussions around caching.

My suggestion

Use a 302 (Temporary) redirect to /login/ then serve the content from there.

response.writeHead(302, {"Location": "/login/"});
response.end("");

I never include file extentions on URLs because it reduces your ability to change things later, but that aspect of the approach would mean you'd need to have a request handler listening on that URL and serving up the static file. You could use pipe() for this and set a suitable cache headers, but my advice would be to use Express or a similar framework to avoid the bugs associated with custom code.

e.g.

// A framework will do most of this for you
response.writeHead("Expires","Thu, 01 Dec 2994 16:00:00 GMT"); 
require('fs').createReadStream('/login/index.html').pipe(response);