Node.js: is request unique? - node.js

In node.js, when using https-module and createserver. When user makes request to httpsserver, is request unique or can different request has same request (id?). If it is unique, which property should be to use?

The request argument in an http request handler is a Javascript object and every one is unique. They are never reused. That object is documented here.
There is no such thing as a request ID in the node.js http library. If you want to make your own request ID, you can do that yourself by just assigning a symbol as a property of the request object. You can pick any property name to use that does not conflict with existing properties.
Since this is a bit of an unusual request, I'd ask you why you're trying to do this because there may be a better way to solve your problem than trying to make a request ID. If you show your actual code and what you're trying to do, we could probably help you more specifically.
If you were using Express, you could set your own request ID with some middleware like this:
// set request ID
let reqCntr = 0;
app.use((req, res, next) => {
req._localID = reqCntr++;
next();
});
Just place this middleware before any other request handlers that wish to use the id. You can pick any non-conflicting property name. I picked _localID.

Related

Why do we add properties to request object?

I can't understand why do we add properties to request object?
As I know, the request object comes from the front end side and if any information is needed or they have, the frontend side should attach it to the request object and send it to backend side like a cookie or JWT token, etc.
And after we got that information in the backend side we can add/update more properties to the response object, like new JWT token, new session ID, etc.
But I see in backend codes, they also add properties to request object and this is vague to me. I don't know why the backend side should add something to the request? Maybe because of the internal transactions between the different middleware this happens? I mean middleware1 adds something to the request object and sends it to the middleware2 in backend side?
For example I can't understand why do we add something to req.session not res.session? Because as I understand this data should be passed to the frontend side to be added into their next request.
But if there is any other reason for adding properties to req object instead of the res object, please let me know?
Mutating the request object by adding additional properties is the primary method of passing additional data between middlewares within Express. Since the request and response are passed to every middleware, this is the only chain that gives you continuity between middlewares.
(You will also see some passed on the response object as well, but in general it's most common to see it on req).
Note that you need to avoid collisions with Express's properties and methods as well as the underlying connection objects from Node.

router handler returns an array of object but client doesn't get them in json though response with 200 status

I am implementing a express.js project with Typescript.
I have defined a enum and a interface :
export enum ProductType {
FOOD = 'food',
CLOTH = 'cloth',
TOOL = 'tool'
}
export interface MyProduct {
type: ProductType;
info: {
price: number;
date: Date;
};
}
One of my router handler needs to return an array of MyProduct to client. I tried this :
const productArr: MyProduct[] = // call another service returns an array of MyProduct
app.get('/products', (req, res) => {
res.status(200).send({products: productArr});
});
I use Postman tested this endpoint, it responses with status 200 but with a default HTML page instead of the array of objects in JSON.
What do I miss? Is it because express.js can't automatically parse the enum and interface to json object??
P.S. I have set up json parser, so it is not about that, other endpoints work fine with json response:
const app = express();
app.use(express.json());
...
As mentioned in the comments, your code should work. I'll list some steps which can be used to try to find the problem.
Show debug info
Set DEBUG=* in your environment. DEBUG is an environment variable which controls logging for many Node modules. You'll be able to see the flow of a request through Express. If there is too much info, you can limit the output like so: DEBUG=*,-babel,-babel:*,-nodemon,-nodemon:*,-router:layer,-follow-redirects,-send (use a comma-separated list and put a - in front of any module you'd like to exclude)
This should help you trace the life of a request through the various routers and routes. You're now in a position to...
Check for another route that is short-circuiting the request
The fact that you're seeing an HTML page when the Express route is sending an object might indicate that your request is matching a different route. Look for catch-all routes such as non-middleware app.use() or wildcard routes which appear ABOVE your route.
Other suggestions
Don't explicitly set the status
Adding .status(200) is more code and unnecessary.
Use res.json()
Use .json() instead of .send(). If will always add the Content-Type: application/json header, whereas .send() will not when it cannot determine the content type (e.g. .send(null) or .send('hello') will not set the Content Type header to application/json, which may confuse clients).
As there is a lack of full response headers and server environment, assuming you are using AWS service with reverse proxy. So, there might be few possibilities listed here that need to look upon :
If router handler returns an array of object but client doesn't get them in json though response with 200 status then there might be a reverse proxy acting as a backend server, serving default content with status code 200 for unknown routes from the client. So in this scenario, you need to whitelist a new route in your reverse proxy server, assuming you are using AWS Amplify for API rewrite and redirects then you need to whitelist this route in your AWS amplify settings, or else it will serve the default content like it is happening in current scenrio.
If issue still persists then :
Make sure you have proper CORS specification on your server.
Make sure productArr is an array returned by service, because if some service returns this value - it might be an unresolved promise. So, proper test cases will help you out here or for debugging purposes set DEBUG=* in your environment and make sure it should return value as expected.
Check for another route that is short-circuiting the request: The fact that you're seeing an HTML page when the Express route is sending an object might indicate that your request is matching a different route. Look for catch-all routes such as non-middleware app.use() or wildcard routes that appear above your route.

At what point are request and response objects populated in express app

I’m always coding backend api’s and I don’t really get how express does its bidding with my code. I know what the request and response objects offer, I just don’t understand how they come to be.
This simplified code for instance:
exports.getBlurts = function() {
return function(req, res) {
// build query…
qry.exec(function(err, results) {
res.json(results);
}
});
}
}
Then I’d call in one of my routes:
app.get('/getblurts/, middleware.requireUser, routes.api.blurtapi.getBlurts());
I get that the function is called upon the route request. It’s very abstract to me though and I don’t understand the when, where, or how as it pertains to the req\res params being injected.
For instance. I use a CMS that modifies the request object by adding a user property, which is then available globally on all requests made whether ajax or otherwise, making it easy at all times to determine if a user is logged in.
Are the req and res objects just pre-cooked by express but allow freedom for them to be modified to your needs? When are they actually 'built'
At its heart express is actually using node's default http-module and passing the express-application as a callback to the http.createServer-function. The request and response objects are populated at that point, i.e. from node itself for every incoming connection. See the nodeJS documentation for more details regarding node's http-module and what req/res are.
You might want to check out express' source code which shows how the express application is passed as a callback to http.createServer.
https://github.com/expressjs/express/blob/master/lib/request.js and https://github.com/expressjs/express/blob/master/lib/response.js show how node's request/response are extended by express specific functions.

Change global variable in express middleware at request level. Block fetch for certain requests

Is it possible to change a global variable (like fetch) at request level in express?
I have this middleware.
app.use((req, res, next) => {
if(req.headers.host.startsWith('mock.')) { // e.g. mock.myapp.com
global.fetch = {};
}
next();
});
My intention is to block the use of fetch in certain requests but allow it in others.
Will this affect subsequent requests?
If it will, how can I apply this change just to the current request.
Well. It's possible to change global variables in middleware, but it's not practical to do what you're trying to do because node.js can easily have multiple requests in flight at the same time. So, you can't really change the global environment for just one request that won't affect the other requests being processed at the same time.
You'd literally have to force Express to serialize all request processing (build some sort of input queue) and only have one request being worked on until completion before you start processing the next request. This, of course, would ruin the scalability of node.js.
The "per request" environment is the req object. That's where middleware typically puts things that apply to this request only.
My intention is to block the use of fetch in certain requests but allow it in others.
Can't really do it that way.
Will this affect subsequent requests?
Yes. You will have permanently changed the global object.
If it will, how can I apply this change just to the current request.
I think we will need to know more about the higher level problem you're actually trying to solve and why. The req object is the typical place to put state that is supposed to apply uniquely to this specific request processing because there is a unique req object for each request and one request knows nothing about any other request's object.

Access custom request headers node express

I am building a web api with Express and have not found information on accessing incoming custom request headers.
I will be expecting, for instance, that an incoming post request have a provider_identifier header. When I receive the request, I need to access that header information to validate their subscription.
Can someone point me in the right direction/provide advice on this?
router.post('myendpoint/', function(req, res){
var providerId = req.????;
});
Answering my own question here... was kindof a DUH moment for me.
Using above example, simply reference the headers collection like so:
var providerId = req.headers.provider_identifier;
One note: Use an underscore rather than a dash. "provider-identifier" doesn't work, but "provider_identifier" does.

Resources