Accessing response headers from NodeJS/ExpressJS before a response is sent - node.js

Is there a way to see which response headers will be present on an HTTP response (and possibly set new HTTP headers)? It seems like once res.send() or res.json() is called, ExpressJS takes over, and there is no way to "intercept" the response before it is sent to the client. Note that I've seen this asked and answered for different platforms, its just not clear whether this is possible in NodeJS/ExpressJS.

I ended up asking this on the ExpressJS issues board. The answer from dougwilson:
For both use-cases you listed, you want to alter/inspect the response
headers. https://www.npmjs.org/package/on-headers is what you would
use.
Source: https://github.com/strongloop/express/issues/2327

Related

How to send get request with a body?

I am trying to send a get request to my API to get a list of users. But I need there is an exclude list that the response must exclude. How can I send this exclude list in my GET request?
You can send a body with the request. Query parameters is probably the best way to do it though. The folks at Elastic.co say:
The truth is that RFC 7231—the RFC that deals with HTTP semantics and
content—​does not define what should happen to a GET request with a
body! As a result, some HTTP servers allow it, and some—​especially
caching proxies—​don’t.
The authors of Elasticsearch prefer using GET for a search request
because they feel that it describes the action—​retrieving
information—​better than the POST verb. However, because GET with a
request body is not universally supported, the search API also accepts
POST requests:
You cannot send a request body when making a GET request. However, you can add it as a query parameter. Alternatively, you can make a POST request.

Implementing "side effects" in Express routes?

I'm looking for some advice on how to achieve something the "proper" way in Express.
When routes on my API are hit, I need to send a bunch of "side-effect" data to all clients via a websocket. All the websocket stuff is done and working, my question is mostly conceptual. So, for example, a POST is made to /message, after the route controller has handled the request and sent a response, I need to send some updated data regarding other data models via websocket to all clients.
I could, of course, just send the WS message from the route controller, but that feels haphazard and unstructured. I'm sure there must be a "proper" way to do it! I did wonder about creating a middleware that runs after the route controller that either examines the request and sends the appropriate updates, or takes something passed from the route controller and uses that to determine what to send. Does anyone have any suggestions?
Thanks!

OPTIONS Preflight request executes POST's code - is that standard?

If I understand correctly, a preflight OPTIONS request is sent as a way of asking "what's allowed here?". Then, once the response comes, if allowed, the calling site sends the POST request (or GET but in my case it's a post). I have figured out that, at least with Azure Function Apps, the OPTIONS request is executing the code that I expected only the POST to execute. I believe this to be the case because once I added some null checking (since the OPTIONS request doesn't have a payload in the body) everything worked fine.
I'm wondering if this is standard.
Seems to me that if I had written the API without using Azure Function Apps, I'd have the OPTIONS request sent down a path that would set the appropriate headers and return a 200 response. And the POST request would be sent down a different path that would expect a payload in the body. If that's how it usually works then that means I've just found an idiosyncrasy of the Azure functionality. But if not it means that I have something to learn about the OPTIONS preflight request.
Thanks in advance for your advice.
Denise
As sideshowbarker mentioned, the OPTIONS request is sent automatically by the browser to check if the cross-origin request can be made.
In case of Azure Functions, this will handled by the Azure when running in the cloud.
If your function is being triggered, that would mean that you have "options" as a supported method for your HTTP Trigger
In the HTTPTrigger attribute for C# functions
In functions.json for non-C# functions
If you want to customize the CORS responses and/or running functions in a container, you could always include "options" as supported and respond differently when the incoming HTTP method is OPTIONS.
Also, if you are using Azure API Management with Azure Functions, you could offload CORS handling to it instead or even use Functions Proxies as shown here.
Thanks y'all! Sorry I was unclear. And sorry it took me a while to get back. Things have been a bit crazy on this end.
Yes, the function being called is mine. And now I understand the browser doesn't have much choice as to whether or not it makes the OPTIONS call.
And yes, I could make my Azure function handle an options call differently and thanks for that suggestion too. That's sort of what I ended up doing but basically I did it by handling an empty payload. I didn't follow that best practice originally because I thought any valid request would have a payload. Accordingly, any request that did not have a payload was invalid and should be turned away as a failure of some sort. This was before I knew that the OPTIONS call was actually executing that function.
My remaining question is if I had NOT been using Azure... if I had rolled my own solution and hosted it somewhere, I'd have a class or at least methods that handle calls to this particular API. (This is something I'm new to so bear with me if my terms aren't quite right and please do correct me). So if I'd done my own API, I'd have one method to handle a POST call and a different method to handle an OPTIONS call, wouldn't I? And the method that handles the OPTIONS call would return information about what's legally do-able with this API. And the method that handles a POST call would handle the payload sent with it. And the method that handles the POST wouldn't get executed when an OPTIONS request is sent. At least that's how I figured it would work. And that's my question -- is that how it's done when not letting something like Azure handle some of the infrastructure?
I'm just trying to learn if the OPTIONS request executing a POST's function is a standard practice or if it's some kind of idiosyncrasy to working with Azure functions.
Thanks again for the advice and for helping me understand these questions.

Node post request body gets truncated

when trying to post a WakeUp event with a JSON body to the Alexa events API using nodejs with axios or request-promise, the API always returns an error 500.
I posted to an online endpoint to actually see what gets posted and learned that the post body gets truncated which obviously results in invalid json. I abstracted the problem and tried to run it from a virgin nodejs installation by using repl.it and the result is the same.
Interestingly enough, there seems to be a relation between the length of the header and the body. So when I shorten the auth token in the header, more characters of the body get transferred. If I shorten the long tokens in the body to about 450 to 500 characters (it seems to vary) the whole request gets through. Obviously this is not a solution, because the tokens are needed for authentication.
When I experimented with the axios version used lowering it to 0.10 I once got a result but posting again lead to another 500. If I post often enough some requests get trough complete, even on the current axios version. I also tried using request-promise with the same outcome.
I got the feeling that I made a really stupid mistake but I can't find it and I really couldn't find anything on this topic, so it's driving me crazy. Any help would be greatly appreciated!
This looks like a tricky one.. first of all, I don't think you're making a really stupid mistake. It looks to me like one of the low-level modules doesn't like something in the POST body for some reason (really weird.).. I've played about with this and I'm getting exactly the same behaviour with both Axios and Request.. if I comment out the tokens (correlationToken and bearer token ) everything works fine.
If I test this locally, everything works as it should (e.g. set up express server and log POST body).
Also posting to https://postman-echo.com/post works as expected (with the original post data)..
I've created this here: https://repl.it/repls/YoungPuzzlingMonad
It looks to me like the original request to http://posthere.io is failing because of the request size only. If you try a very basic POST with a large JSON body you get the same result.
I get the same result with superagent too.. this leads me to believe this is something server side...
This was not related to the post request at all. The reason for the error after sending the WakeUp event was the missing configuration parameter containing the MACAdresses in the Alexa.WakeOnLANController interface.
I used the AlexaResponse class to add the capability via createPayloadEndpointCapability which had not been modified to support the "new" WakeOnLANController interface yet.
It's a pity that the discovery was accepted and my WOL-capable device was added to my smart home devices although a required parameter was missing :(
posthere.io cutting off long post bodys cost me quite a few hours... On the upside, I go to know many different ways of issuing a post request in node ;)
Thanks again Terry for investigating!

Sometimes GET returns 304 instead of 200

I am using node.js and mongodb.
I seem to be receiving a 200 sometimes, and a 304 not modified other times.
router.get('/add-to-bag/:id', (req, res, next) => {
req.session.bag.push(req.params.id);
res.redirect('back');
});
});
I can't be sure what stack you're using to create the app. It looks like you're using Express.js to do routing. However, I can tell you why you're getting a 304.
From Wikipedia:
304 Not Modified (RFC 7232)
Indicates that the resource has not been modified since the version specified by the request headers If-Modified-Since or If-None-Match. In such case, there is no need to retransmit the resource since the client still has a previously-downloaded copy.[24]
A 304 means "hey, remember the last answer I sent you? It hasn't changed", and hence your browser would replay the last response it received from cache, without data transmission ever having taken place.
This means that your data is being added. But since it's the exact same data in the bag, instead of giving a 200 with the exact same data again, the server just issues a 304.
BTW: Your API isn't Restful. I'd recommend using POST to create new records instead of issuing a GET to a different URL. I recommend reading up on REST API design. It's pretty straightforward once you get the hang of it.
TL;DR: Use a POST request instead of a GET request.
GET requests should be used for getting things. A GET request should not affect the state of the application (i.e. of the server).
In your case, adding an item to the shopping bag is clearly a modification of the state of the server.
If you're not convinced, check out this answer
A GET is defined in this way in the HTTP protocol. It is supposed to be idempotent and safe.
If you use a POST request, not only will it fix you 304 issue, but it will also prevent some other possible bugs later on. (And it will be more correct.)
Did you try by disabling etag?
app.disable('etag');
Simply adding 'Cache-Control': 'no-cache', to my headers was able to bypass the 304 issue I was having. Seen in this answer here

Resources