1. Opening analysis
First of all, everyone should be familiar with the concept of "Http". It is not based on a specific language, but is a general application layer protocol. Different languages have different implementation details, but they are consistent with their principles and the ideas are the same.
As a host running environment, NodeJS uses JavaScript as the host language and also has its own set of standards implemented. In this article, let’s learn about the “Http module” together. But as a premise,
I hope you can read the API provided by the official website first and have a preliminary understanding, which will make it much more convenient. The following is an overview of the API in the Http part:
The code copy is as follows:
HTTP
http.STATUS_CODES
http.createServer([requestListener])
http.createClient([port], [host])
Class: http.Server
Event: 'request'
Event: 'connection'
Event: 'close'
Event: 'checkContinue'
Event: 'connect'
Event: 'upgrade'
Event: 'clientError'
server.listen(port, [hostname], [backlog], [callback])
server.listen(path, [callback])
server.listen(handle, [callback])
server.close([callback])
server.maxHeadersCount
server.setTimeout(msecs, callback)
server.timeout
Class: http.ServerResponse
Event: 'close'
response.writeContinue()
response.writeHead(statusCode, [reasonPhrase], [headers])
response.setTimeout(msecs, callback)
response.statusCode
response.setHeader(name, value)
response.headersSent
response.sendDate
response.getHeader(name)
response.removeHeader(name)
response.write(chunk, [encoding])
response.addTrailers(headers)
response.end([data], [encoding])
http.request(options, callback)
http.get(options, callback)
Class: http.Agent
new Agent([options])
agent.maxSockets
agent.maxFreeSockets
agent.sockets
agent.freeSockets
agent.requests
agent.destroy()
agent.getName(options)
http.globalAgent
Class: http.ClientRequest
Event 'response'
Event: 'socket'
Event: 'connect'
Event: 'upgrade'
Event: 'continue'
request.write(chunk, [encoding])
request.end([data], [encoding])
request.abort()
request.setTimeout(timeout, [callback])
request.setNoDelay([noDelay])
request.setSocketKeepAlive([enable], [initialDelay])
http.IncomingMessage
Event: 'close'
message.httpVersion
message.headers
message.rawHeaders
message.trailers
message.rawTrailers
message.setTimeout(msecs, callback)
message.method
message.url
message.statusCode
message.socket
Let's start with a simple example, create a file called server.js, and write the following code:
The code copy is as follows:
var http = require('http') ;
var server = http.createServer(function(req,res){
res.writeHeader(200,{
'Content-Type' : 'text/plain;charset=utf-8' // Add charset=utf-8
}) ;
res.end("Hello, Big Bear!") ;
}) ;
server.listen(8888);
console.log("http server running on port 8888...") ;
(node server.js) The following is the running result:
2. Detailed analysis examples
Let’s take a look at this small example:
(line 1): Introduce the "http" module that comes with NodeJS through "require" and assign it to the http variable.
(2 lines): Call the function provided by the http module: "createServer". This function returns a new web server object.
The parameter "requestListener" is a function that will automatically be added to the listening queue of the "request" event.
When a request arrives, Event-Loop will put the Listener callback function into the execution queue, and all the code in the node is executed one by one from the execution queue.
These executions are all on the worker thread (Event Loop itself can be considered as being in an independent thread. We generally do not mention this thread, but call node a single-threaded execution environment).
All callbacks are run on a worker thread.
Let's take a look at the callback function "requestListener", which provides two parameters (request, response).
Triggered every time a request is received. Note that each connection may have multiple requests (in keep-alive connections).
"request" is an instance of http.IncomingMessage. "response" is an instance of http.ServerResponse.
An http request object is a readable stream, while an http response object is a writable stream.
An "IncomingMessage" object is created by http.Server or http.ClientRequest.
And pass as the first parameter to the "request" and "response" events respectively.
It can also be used to access the state, header files and data of the response.
It implements the "Stream" interface as well as the following additional events, methods and properties. (Refer to API for details).
(3 lines): "writeHeader", use the "response.writeHead()" function to send an Http status 200 and the content-type of the Http header (content-type).
Reply to the request header. "statusCode" is a three-bit HTTP status code, such as 404. The last parameter, "headers", is the content of the response header.
Take a chestnut:
The code copy is as follows:
var body = 'hello world' ;
response.writeHead(200, {
'Content-Length': body.length,
'Content-Type': 'text/plain'
}) ;
Note: Content-Length is calculated in bytes, not in characters.
The reason for the previous example is that the string "Hello World!" contains only single-byte characters.
If the body contains multibyte-encoded characters, Buffer.byteLength() should be used to determine the number of bytes of the string in the case of multibyte character encoding.
It should be further explained that Node does not check whether the Content-Lenth attribute matches the transmitted body length.
statusCode is a three-bit HTTP status code, for example: "404". What I want to talk about here is "http.STATUS_CODES", all the sets and short descriptions of the standard "Http" response status codes are included.
The following is the source code reference:
The code copy is as follows:
var STATUS_CODES = exports.STATUS_CODES = {
100 : 'Continue',
101 : 'Switching Protocols',
102 : 'Processing', // RFC 2518, obsoleted by RFC 4918
200 : 'OK',
201 : 'Created',
202 : 'Accepted',
203: 'Non-Authoritative Information',
204 : 'No Content',
205 : 'Reset Content',
206 : 'Partial Content',
207 : 'Multi-Status', // RFC 4918
300 : 'Multiple Choices',
301 : 'Moved Permanently',
302 : 'Moved Temporarily',
303 : 'See Other',
304 : 'Not Modified',
305 : 'Use Proxy',
307 : 'Temporary Redirect',
400 : 'Bad Request',
401 : 'Unauthorized',
402 : 'Payment Required',
403 : 'Forbidden',
404 : 'Not Found',
405 : 'Method Not Allowed',
406 : 'Not Acceptable',
407 : 'Proxy Authentication Required',
408 : 'Request Time-out',
409 : 'Conflict',
410 : 'Gone',
411 : 'Length Required',
412 : 'Precondition Failed',
413 : 'Request Entity Too Large',
414 : 'Request-URI Too Large',
415 : 'Unsupported Media Type',
416 : 'Requested Range Not Satisfiable',
417 : 'Expectation Failed',
418 : 'I/'ma teapot', // RFC 2324
422 : 'Unprocessable Entity', // RFC 4918
423 : 'Locked', // RFC 4918
424 : 'Failed Dependency', // RFC 4918
425 : 'Unordered Collection', // RFC 4918
426 : 'Upgrade Required', // RFC 2817
500 : 'Internal Server Error',
501 : 'Not Implemented',
502 : 'Bad Gateway',
503: 'Service Unavailable',
504 : 'Gateway Time-out',
505 : 'HTTP Version not supported',
506 : 'Variant Also Negotiates', // RFC 2295
507 : 'Insufficial Storage', // RFC 4918
509 : 'Bandwidth Limit Exceeded',
510 : 'Not Extended' // RFC 2774
};
Excerpted from the Nodejs source code "http.js" starts with line 143.
In fact, it is not difficult to see from the client response result:
(6 lines): "response.end"------ When all response headers and messages are sent, this method sends the signal to the server. The server will think that the message is completed.
This method must be called after each response is completed. If the parameter "data" is specified, it is equivalent to calling "response.write(data, encoding)" first and then calling "response.end()".
(8 lines): "server.listen(8888)" ----- The server accepts connections with the specified handle and binds to a specific port.
The above is a more detailed analysis process, hoping to help deepen understanding. Although there is not much code, the focus is on understanding some detailed mechanisms so that NodeJS applications can be efficiently developed in the future.
Three, examples
In addition to using the "request" object to access the request header data, the "request" object can also be used as a read-only data stream to access the request body data.
Here is an example of a "POST" request:
The code copy is as follows:
http.createServer(function (request, response) {
var body = [];
console.log(request.method);
console.log(request.headers);
request.on('data', function (chunk) {
body.push(chunk);
}) ;
request.on('end', function () {
body = Buffer.concat(body);
console.log(body.toString());
});
}).listen(8888);
Below is a complete "Http" request data content.
The code copy is as follows:
POST/HTTP/1.1
User-Agent: curl/7.26.0
Host: localhost
Accept: */*
Content-Length: 11
Content-Type: application/x-www-form-urlencoded
Hello World
Four, let's summarize
(1) Understand the concept of "Http".
(2) Proficient in using "Http"-related APIs.
(3) Pay attention to the control of details, such as: the processing details between "POST, GET".
(4), Understanding of "requestListener".
(5), emphasize a concept: an http request object is a readable stream, while an http response object is a writable stream.