response.writeHead and response.end in NodeJs - node.js

var https = require('https');
var fs = require('fs');
var options = {
key: fs.readFileSync('test/fixtures/keys/agent2-key.pem'),
cert: fs.readFileSync('test/fixtures/keys/agent2-cert.pem')
};
https.createServer(options, function (req, res) {
res.writeHead(200);
res.end("hello world\n");
}).listen(8000);
Can anyone explain me why do we call the writeHead and end
method in createServer method.
What is the main purpose of options object passed in createServer
method.

Those calls to writeHead and end are not being done in the createServermethod, but rather in a callback.
It's a bit easier to see if you split out the callback into a separate function:
function handleRequest(req, res) {
res.writeHead(200);
res.end("hello world\n");
}
https.createServer(options, handleRequest).listen(8000);
So here we define a handleRequest function and then pass that into the createServer call. Now whenever the node.js server we created receives an incoming request, it will invoke our handleRequest method.
This pattern is very common in JavaScript and is core to node.js' asynchronous event handling.

In your code, the writeHead() is called to write the header of the response, that the application will serve to the client. The end() method both sends the content of the response to the client and signals to the server that the response (header and content) has been sent completely. If you are still going to send anything else, you should call write() method of res response object instead.
The options JSON object is a modifier that you may use, to override the default behaviour of the createServer() method. In your code's case:
+ key: Private key to use for SSL (default is null)
+ cert: Public x509 certificate to use (default is null)
You can find more in this section of the Node.js API doc about the response.writeHead() method.
You can find more in this section of the Node.js API doc about the https.createServer() method.

response.writeHead(200) sends a response header to the request. The status code is a 3-digit HTTP status code, like 404.
This method must only be called once on a message and it must be called before response.end() is called.
If you call response.write() or response.end() before calling this, the implicit/mutable headers will be calculated and call this function for you.

As far as i know if you don't put the response.end() at the end then your web page will go on loading thus the response.end() is used to tell the server that the data has been loaded

The res.writeHead method is for returning a status code to the browser, and the browser will throw an error if it is a client-side status code or server-side status code. The res.end method is to make sure the response isn't returned before it might be ready, in case of nested code or otherwise.
The purpose of the options object is to make sure the page has a valid key and certificate before declaring that the page is encrypted under https.

Related

Access HTTP2 headers from a #grpc/grpc-js Handler

I have a #grpc/grpc-js server. It includes a handler for a method that looks like this
server = new grpc.Server()
server.addService(proto.GrpcTester.service, {
myMethod(call, callback) {
callback(null, {hello:"world"})
}
})
Is there a way to access the HTTP2 request headers that were set when this request was made?
The call object passed to the myMethod function in that example code has a metadata property that contains the request headers.

Call Express router manually

Нello! I am looking to call a function which has been passed to an expressRouter.post(...) call.
This expressRouter.post(...) call is occurring in a file which I am unable to modify. The code has already been distributed to many clients and there is no procedure for me to modify their versions of the file. While I have no ability to update this file for remote clients, other developers are able to. I therefore face the issue of this POST endpoint's behaviour changing in the future.
I am also dealing with performance concerns. This POST endpoint expects req.body to be a parsed JSON object, and that JSON object can be excessively large.
My goal is to write a GET endpoint which internally activates this POST endpoint. The GET endpoint will need to call the POST endpoint with a very large JSON value, which has had URL query params inserted into it. The GET's functionality should always mirror the POST's functionality, including if the POST's functionality is updated in the future. For this reason I cannot copy/paste the POST's logic. Note also that the JSON format will never change.
I understand that the issue of calling an expressjs endpoint internally has conventionally been solved by either 1) extracting the router function into an accessible scope, or 2) generating an HTTP request to localhost.
Unfortunately in my case neither of these options are viable:
I can't move the function into an accessible scope as I can't modify the source, nor can I copy-paste the function as the original version may change
Avoiding the HTTP request is a high priority due to performance considerations. The HTTP request will require serializing+deserializing an excessively large JSON body, re-visiting a number of authentication middlewares (which require waiting for further HTTP requests + database queries to complete), etc
Here is my (contrived) POST endpoint:
expressRouter.post('/my/post/endpoint', (req, res) => {
if (!req.body.hasOwnProperty('val'))
return res.status(400).send('Missing "val"');
return res.status(200).send(`Your val: ${req.body.val}`);
});
If I make a POST request to localhost:<port>/my/post/endpoint I get the expected error or response based on whether I included "val" in the JSON body.
Now, I want to have exactly the same functionality available, but via GET, and with "val" supplied in the URL instead of in any JSON body. I have attempted the following:
expressRouter.get('/my/get/endpoint/:val', (req, res) => {
// Make it seem as if "val" occurred inside the JSON body
let fakeReq = {
body: {
val: req.params.val
}
};
// Now call the POST endpoint
// Pass the fake request, and the real response
// This should enable the POST endpoint to write data to the
// response, and it will seem like THIS endpoint wrote to the
// response.
manuallyCallExpressEndpoint(expressRouter, 'POST', '/my/post/endpoint', fakeReq, res);
});
Unfortunately I don't know how to implement manuallyCallExpressEndpoint.
Is there a solution to this problem which excludes both extracting the function into an accessible scope, and generating an HTTP request?
This seems possible, but it may make more sense to modify req and pass it, rather than create a whole new fakeReq object. The thing which enables this looks to be the router.handle(req, res, next) function. I'm not sure this is the smartest way to go about this, but it will certainly avoid the large overhead of a separate http request!
app.get('/my/get/endpoint/:val', (req, res) => {
// Modify `req`, don't create a whole new `fakeReq`
req.body = {
val: req.params.val
};
manuallyCallExpressEndpoint(app, 'POST', '/my/post/endpoint', req, res);
});
let manuallyCallExpressEndpoint = (router, method, url, req, res) => {
req.method = method;
req.url = url;
router.handle(req, res, () => {});
};
How about a simple middleware?
function checkVal(req, res, next) {
const val = req.params.val || req.body.val
if (!val) {
return res.status(400).send('Missing "val"');
}
return res.status(200).send(`Your val: ${val}`);
}
app.get('/my/get/endpoint/:val', checkVal)
app.post('/my/post/endpoint', checkVal)
This code isn't tested but gives you rough idea on how you can have the same code run in both places.
The checkVal function serves as a Express handler, with request, response and next. It checks for params first then the body.

How does the function passed to create server Return Object

I have just started with Node.js.While learning to write a simple node.js code that outputs hello world to the browser I used the following code. In this code the listen method is called upon the argument passed on the createServer method.Here are my doubts
1.The Function does not seem to create any Object.
2.How can we call methods on response we haven't defined any.
var http = require("http");
http.createServer(function(request,response))
{
response.writeHead(200,"Content-Type":"text/plain");
response.write("Hello World");
response.end()
}).listen(8888);
First of all, I believe you misplaced the parentheses. The code should be:
var http = require("http");
http.createServer(function (request,response) {
response.writeHead(200,"Content-Type":"text/plain");
response.write("Hello World");
response.end();
}).listen(8888);
Secondly, the function that you write (that accept request and response as arguments) is called a callback function. The createServer function will call this function, passing 2 arguments to it - request and response.
That's why you can use response and request when defining it.

Node.js - Create a proxy, why is request.pipe needed?

Can some one explain this code to create a proxy server. Everything makes sense except the last block. request.pipe(proxy - I don't get that because when proxy is declared it makes a request and pipes its response to the clients response. What am I missing here? Why would we need to pipe the original request to the proxy because the http.request method already makes the request contained in the options var.
var http = require('http');
function onRequest(request, response) {
console.log('serve: ' + request.url);
var options = {
hostname: 'www.google.com',
port: 80,
path: request.url,
method: 'GET'
};
var proxy = http.request(options, function (res) {
res.pipe(response, {
end: true
});
});
request.pipe(proxy, {
end: true
});
}
http.createServer(onRequest).listen(8888);
What am I missing here? [...] the http.request method already makes the request contained in the options var.
http.request() doesn't actually send the request in its entirety immediately:
[...] With http.request() one must always call req.end() to signify that you're done with the request - even if there is no data being written to the request body.
The http.ClientRequest it creates is left open so that body content, such as JSON data, can be written and sent to the responding server:
var req = http.request(options);
req.write(JSON.stringify({
// ...
}));
req.end();
.pipe() is just one option for this, when you have a readable stream, as it will .end() the client request by default.
Although, since GET requests rarely have a body that would need to be piped or written, you can typically use http.get() instead, which calls .end() itself:
Since most requests are GET requests without bodies, Node provides this convenience method. The only difference between this method and http.request() is that it sets the method to GET and calls req.end() automatically.
http.get(options, function (res) {
res.pipe(response, {
end: true
});
});
Short answer: the event loop. I don't want to talk too far out of my ass, and this is where node.js gets both beautiful and complicated, but the request isn't strictly MADE on the line declaring proxy: it's added to the event loop. So when you connect the pipe, everything works as it should, piping from the incoming request > proxy > outgoing response. It's the magic / confusion of asynchronous code!

How does the 'reverse path' in Node.js Connect work?

So I understand that Node.js Connect works like a stack through which it runs, starting from the top and going to the bottom. From the Connect introduction by its author at http://howtonode.org/connect-it it shows an example like
var Connect = require('connect');
module.exports = Connect.createServer(
require('./log-it')(),
require('./serve-js')()
);
The article reads
Every request enters the onion at the outside and traverses layer by
layer till it hits something that handles it and generates a response.
In Connect terms, these are called filters and providers. Once a layer
provides a response, the path happens in reverse.
I'm particulary curious about "Once a layer provides a response, the path happens in reverse". How does that happen? Every middleware gets called again, but in reverse order?
No, they don't get called again in reverse, but each middleware has a chance to monkey-patch the request methods and hijack them. It's not ideal.
// basic logger example
module.exports = function () {
return function logger(req, res, next) {
var writeHead = res.writeHead;
res.writeHead = function (code, headers) {
console.log(req.method, req.url, code);
res.writeHead = writeHead;
return res.writeHead(code, headers);
};
next();
};
};
Now, this code has issues because writeHead isn't the only way to set the status code, so it won't catch all requests. But that is the basic way that middleware can catch events on the way out.

Resources