Node Introductory Tutorial (12) Chapter 10: Node's HTTP Module

The original intention of Ryan Dahl 's development of node is to combine Nginxnon-blocking IO functions with a highly encapsulated WEB server. So Node's original intention is to go for a high-performance web server, so: Node's HTTP module is also the core of the core.

The prerequisite knowledge points you need to know about this article:

  • HTTP protocol
  • Web Request Model: Request → Process → Response
  • Node's streams and events

client of http module

To use the HTTP server and client,  require('http')modules are required. The http module provides two functions http.request()and http.get(), which help programs send requests to the server.

We can http.request ()create an http.ClientRequestinstance of the class that sends the request through the method. After the request is created, the request will not be sent immediately. We can also continue to access the request header: setHeader(name, value), getHeader(name) and  removeHeader(name) the API for modification. The actual request headers are sent with the first chunk of data or when called  request.end() .

http.ClientRequest类

  • http.ClientRequestThe class inherits EventEmitterand it defines the following events internally.
event illustrate
abort Fired when the request has been terminated by the client. This event is only fired when abort() is called for the first time.
connect

Fired whenever the server responds to a CONNECT request.

If the event is not listened for, the client that receives the CONNECT method closes the connection.

continue

Fired when the server sends a 100 Continue HTTP response,

Usually because the request contains Expect: 100-continue.

This is the instruction that the client will send the request body.

response

Fired when a response to a request is received.

This event fires only once. If no 'response' event handler is added, the response is discarded entirely.

If the 'response' event handler is added, the response object's data must be consumed,

This can be done by calling response.read(), or by adding a 'data' event handler,

Or call the .resume() method. The 'end' event is fired when the data is consumed.

Memory is consumed before the data has been read, possibly causing a 'process out of memory' error.

socket Fired when a socket is allocated to a request.
timeout

Fired when the underlying socket times out.

This method will only notify idle sockets. The request must be stopped manually.

upgrade

Fired whenever the server responds to an upgrade request.

If this event is not listened for, the client that receives the upgrade header will close the connection.

  • http.ClientRequestThe class also provides some methods for us to process the request and return the response.
method parameter illustrate
request.end([data[, encoding]][, callback]) ①Sent datadata encoding②Encoding ③callback callback function End sending request. If parts of the request body have not been sent, they are flushed to the stream. If the request is chunked, the terminating character '0\r\n\r\n' is sent. If data is specified, it is equivalent to calling request.end(callback) after calling request.write(data, encoding). If callback is specified, it will be called when the request stream ends.
request.flushHeaders() without Flush request headers. For efficiency reasons, Node.js usually caches request headers until request.end() is called or the first chunk of request data is written. Node.js will then package the request headers and data into a single TCP packet.
request.getHeader(name) ①name ②return string Read the request header, note: the parameter name is case sensitive
request.removeHeader(name) name string Removes a header that is already in the headers object.
request.setHeader(name, value) ①name is the key of the header ②value Set a single header value for the headers object. If the header already exists, it will be replaced. Here an array of strings is used to set multiple headers with the same name.
request.setSocketKeepAlive([enable][, initialDelay]) ①enable类型boolean②initialDelay 一旦 socket 被分配给请求且已连接,socket.setKeepAlive() 会被调用。
request.setTimeout(timeout[, callback]) ①timeout请求被认为是超时的毫秒数。②callback 可选的函数,当超时发生时被调用。 等同于绑定到 timeout 事件。一旦socket被分配给请求且已连接,socket.setTimeout() 会被调用。
request.write(chunk[, encoding][, callback]) ①chunk发送的请求数据。②encoding:编码;③callback回调函数 发送请求主体的一个数据块。 通过多次调用该方法,一个请求主体可被发送到一个服务器,在这种情况下,当创建请求时,建议使用 ['Transfer-Encoding', 'chunked'] 请求头。

发送GET请求

// 引入http模块
const http = require('http');

// 创建一个请求 let request = http.request( { protocol: 'http:', // 请求的协议 host: 'aicoder.com', // 请求的host port: 80, // 端口 method: 'GET', // GET请求 timeout: 2000, // 超时时间 path: '/' // 请求路径 }, res => { // 连接成功后,接收到后台服务器返回的响应,回调函数就会被调用一次。 // res => http.IncomingMessage : 是一个Readable Stream res.on('data', data => { console.log(data.toString('utf8')); // 打印返回的数据。 }); } ); // 设置请求头部 request.setHeader('Cache-Control', 'max-age=0'); // 真正的发送请求 request.end(); 

发送get请求的另外一个办法

http模块还提供了http.get(options,callback),用来更简单的处理GET方式的请求,它是http.request()的简化版本,唯一的区别在于http.get自动将请求方法设为GET请求,同时不需要手动调用req.end();

http.get('http://aicoder.com', res => {
  res.on('data', data => {
    console.log(data.toString('utf8'));
  });
});

发送post请求

且看一个发送post请求的例子。

const http = require('http');

let request = http.request(
  {
    protocol: 'http:', host: 'aicoder.com', port: 80, method: 'POST', timeout: 2000, path: '/' }, res => { res.on('data', data => { console.log(data.toString('utf8')); }); } ); // 发送请求的数据。 request.write('id=3&name=aicoder'); request.end(); 

HTTP服务器端

http.Server实现了简单的web服务器,并把请求和响应也做了封装。

http.server对象的事件

http.server是一个基于事件的HTTP服务器,所有的请求都被封装到独立的事件当中,我们只需要对他的事件编写相应的行数就可以实现HTTP服务器的所有功能,它继承自EventEmitter,提供了以下的事件:

  1. request:当客户端请求到来的时候,该事件被触发,提供两个参数request和response,分别是http.ServerRequest和http.ServerResponse表示请求和响应的信息。
  2. connection:当TCP建立连接的时候,该事件被触发,提供了一个参数socket,为net.socket的实例(底层协议对象)
  3. close:当服务器关闭的时候会被触发
  4. 除此之外还有checkContinueupgradeclientError等事件

我们最常用的还是request事件,http也给这个事件提供了一个捷径:http.createServer([requestListener])
下面我们来简单的看一下两个案例:

第一个:使用request事件的:

const http = require('http');

let server = new http.Server(); server.on('request', (req, res) => { console.log(req.url); //设置应答头信息 res.writeHead(200, { 'Content-Type': 'text/html' }); res.write('hello we are family<br>'); res.end('server already end\n'); }); //显示了三次这也证明了TCP的三次握手 server.on('connection', () => { console.log('握手'); }); server.on('close', () => { console.log('server will close'); }); //关闭服务为了触发close事件 server.close(); server.listen(8080); 

第二个:利用http.createServer创建服务器实例代码:

const http = require('http');

http.createServer(function(req,res){ res.writeHead(200,{'Content-Type':'text/plain'}) res.write("hi, from aicoder.com"); res.end(); }).listen(3000); 

http.ServerRequset请求信息

我们都知道HTTP请求分为两部分:请求头和请求体,如果请求的内容少的话就直接在请求头协议完成之后立即读取,请求体可能相对较长一点,需要一定的时间传输。因此提供了三个事件用于控制请求体传输.

1.data:当请求体数据到来时,该事件被触发,该事件一共一个参数chunk,表示接受到的数据。
1.end:当请求体数据传输完成时,该事件被触发,此后将不会再有数据到来。
1.close:用户当前请求结束时,该事件被触发,不同于end,如果用户强制终止了传输,也会触发close

ServerRequest的属性

名称 含义
ccomplete 客户端请求是否已经发送完成
httpVersion HTTP协议版本,通常是1.0或1.1
method HTTP请求方法,如:GET,POST
url 原始的请求路径
headers HTTP请求头
trailers HTTP请求尾(不常见)
connection 当前HTTP连接套接字,为net.Socket的实例
socket connection属性的别名
client client属性的别名
http.createServer(function(req,res){
    console.log(req.httpVersion);
    //console.log(req.socket); console.log(req.headers); console.log(req.method); res.writeHead(404,{'Content-Type':'text/plain'}) res.write("we are is content"); res.end(); }).listen(8080); 

获取GET请求内容

由于GET请求直接被嵌入在路径中,URL完整的请求路径,包括了?后面的部分,因此你可以手动解析后面的内容作为GET的参数,Nodejs的url模块中的parse函数提供了这个功能。

const http = require('http');
const url = require('url'); const util = require('util'); http .createServer((req, res) => { //利用url模块去解析客户端发送过来的URL res.write(util.inspect(url.parse(req.url, true))); res.end(); }) .listen(8080); 

获得POST请求内容

POST请求的内容全部都在请求体中,·http.ServerRequest·并没有一个属性内容为请求体,原因是等待请求体传输可能是一件耗时的工作。譬如上传文件。恶意的POST请求会大大消耗服务器的资源。所以Nodejs是不会解析请求体,当你需要的时候,需要手动来做。

简单的看一下代码:

// 获取post请求数据
const http = require('http');
const util = require('util'); const querystring = require('querystring'); http .createServer((req, res) => { let post = ''; req.on('data', chunk => { post += chunk; }); req.on('end', () => { post = querystring.parse(post); res.end(util.inspect(post)); }); }) .listen(60004); 

http.ServerResponse返回客户端信息

http.ServerResponse这个类实现了(而不是继承自)可写流 接口。继承了EventEmitter。它用来给用户发送响应结果,它是由http.Serverrequest事件发送的,作为第二个参数传递。一般为response或res
主要的三个函数:

  • response.writeHead(statusCode,[headers]):向请求的客户端发送响应头。
    • statusCode是HTTP的状态码,如200为成功,404未找到等。
    • headers是一个类似关联数组的对象,表示响应头的每个属性。
  • response.write(data,[encoding]) 向请求客户端发送相应内容,data是buffer或字符串,encoding为编码
  • response.end([data],[encoding]) 结束响应,告知用户所有发送已经完成,当所有要返回的内容发送完毕,该函数必须被调用一次,如果不调用,客户端永远处于等待状态

总结

真正开发环境,不会用这么底层的API去做web网站或者微服务,一般会选择KOA或者EXPRESS等框架。不过,通过底层的API也可以感受一下NODE原生的开发的快乐。


参考:

1.https://blog.csdn.net/woshinannan741/article/details/51357464
1.http://nodejs.cn/api/http.html#http_http_createserver_requestlistener


老马免费视频教程

返回教程列表首页

github地址:https://github.com/malun666/aicoder_node

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324503352&siteId=291194637