Reputation: 61
I am using Node.js.
I have a piece of code that works well in returning the expected response and the response is received quickly:
if (req.accepts('json')) {
res.header('Content-Type', 'application/json');
res.send(res.locals.items, 200);
}
In addition to the Status 200, I want to add a message in the header. Therefore, I modified the code above a little bit:
if (req.accepts('json')) {
res.writeHead( 200, 'my_customizd_message', {'Content-Type' : 'application/json'} );
res.send(res.locals.items);
}
then, it complains that "Error : can't set headers after they are sent".
I tried something else:
if (req.accepts('json')) {
res.writeHead( 200, 'my_customizd_message', {'Content-Type' : 'application/json'} );
res.end();
}
There is no error message on the console. But, nothing is returned. The code is running forever. I am hoping someone could help me out. Thank you very much.
Upvotes: 1
Views: 3454
Reputation: 66
Based on what I just read, you can use:
res.setHeader(name, value);
setHeader()
works on two conditions:
writeHead()
(i.e. you can't set the header if its already been sent)res.write()
or res.endif you need to read more, I just extracted this info from the book "professional node.js", chapter 11 page 99
Upvotes: 0
Reputation: 61
now, I added another line:
res.header('warning' : 'my_customized_message');
it works.
Upvotes: 0
Reputation: 145102
It looks like you're using Express. It's important to understand that writeHead
is provided by node's core HTTP library, and Express generally manages headers for you. In other words, you shouldn't be calling writeHead
in an Express application.
Your error in your first attempt comes from the fact that Expess itself calls writeHead
when you call send
(an Express-provided method). Because you already manually wrote headers to the wire, Express's attempt to write headers fails and throws an exception.
Your second attempt returns nothing because you write headers and then immediately end the response without sending any data – there is no error because you don't call an Express method, but of course the client would see nothing.
The problem you have is that Express's response methods (like send
) set various headers (and even the response code in some cases) and then rely on node's implicit header function to actually write the headers. Notice that writeHead
never appears anywhere in Express's source code.
When you (or in this case, Express on your behalf) starts writing data to the response (either write
or end
), node checks to see whether headers were sent. If not, it calls writeHead
for you, which merges any headers passed directly to that function with the headers stored in res._headers
(a private property that you modify by calling res.setHeader
).
There are a couple things that combine to make if very difficult to accomplish a custom HTTP status message:
Express methods (like send
) set headers, write data, and end
the response in one go. Thus, you cannot modify the headers or call writeHead
with a custom status message yourself.
When (the current version of) node's HTTP module writes implicit headers, it always writes the default status message. There is no documented way of customizing it.
So how do you get a custom status message?
You could bypass Express's logic and respond to the request manually (like in your second attempt). However, you miss out on a lot of useful features when you do this. Only do this if you absolutely know what you're doing. (so don't)
The simplest answer is that node's 0.11 branch adds res.statusMessage
, which would allow you to simply set your desired message before calling res.send
. Unfortunately, 0.11 is unstable and shouldn't be used in production. 0.12 (the next stable release that will have this feature) will come out "soon". Of course, this release also comes with several breaking changes (especially on the C++ module side), so you may not be able to use it immediately.
The stopgap answer for node 0.10 is to monkey patch http.ServerResponse.prototype._implicitHeader
. This is a dirty hack that may break things. Proceed at your own risk.
http.ServerResponse.prototype._implicitHeader = function() {
this.writeHead(this.statusCode, this.statusMessage);
};
Do this once when your app starts up. This will allow you to set res.statusMessage = 'My Custom Status';
before calling res.send
, just like in 0.11.
Upvotes: 3
Reputation: 4292
I haven't used it before, but what about this?:
if (req.accepts('json')) {
res.writeHead( 200, {
'Content-Type' : 'application/json',
'my_customizd_message':'blah blah'
});
res.send(res.locals.items);
}
Upvotes: 0