Nodejs系列-14-http模块

Http概述

http模块主要用于搭建HTTP服务。大体上可以分为两个部分:客户端http请求 与 服务端http响应

客户端http请求

利用http模块向服务器发送http请求:

http.request

http.request(url[, options][, callback])

我们将远端js文件下载到本地

  const http = require("http");
  const fs=require("fs");
  const path=require("path");
  const options = {
    hostname: 's29.9956.cn',
    port: 80,
    path: '/static/common/js/vue.min.js?v=1549865000',
    method: 'GET',
    headers: {
      'Content-Type': 'application/x-www-form-urlencoded',
    }
  };
  let filename = path.resolve('vue.js');
  let writeStream = fs.createWriteStream(filename,{encoding:'utf8'});
  const req = http.request(options, (res) => {
    console.log(`状态码: ${res.statusCode}`);
    console.log(`响应头: ${JSON.stringify(res.headers)}`);
    res.setEncoding('utf8');
    res.on('data', (chunk) => {
      console.log(`数据写入中...`);
      writeStream.write(chunk)
    });
    res.on('end', () => {
      console.log('响应中已无数据');
      writeStream.end();
    });
  });

  req.on('error', (e) => {
    console.error(`请求遇到问题: ${e.message}`);
  });
  req.end(); //使用 http.request() 时,必须始终调用 req.end() 来表示请求的结束,即使没有数据被写入请求主体。

运行结果:

  状态码: 200
  响应头: {"server":"Tengine","content-type":"application/javascript; charset=utf-8","content-length":"85310","connection":"close","vary":"Accept-Encoding","date":"Fri, 16 Aug 2019 11:19:19 GMT","last-modified":"Thu, 27 Jun 2019 02:03:26 GMT","etag":"\"5d1423ee-14d3e\"","accept-ranges":"bytes","ali-swift-global-savetime":"1565954359","via":"cache21.l2cn1807[0,200-0,H], cache22.l2cn1807[0,0], kunlun4.cn698[0,200-0,H], kunlun2.cn698[0,0]","age":"5519659","x-cache":"HIT TCP_MEM_HIT dirn:11:519083382","x-swift-savetime":"Mon, 09 Sep 2019 10:23:15 GMT","x-swift-cachetime":"7776000","timing-allow-origin":"*","eagleid":"3da864a015714740181924794e"}
  数据写入中...
  数据写入中...
  数据写入中...
  响应中已无数据

最终文件被下载到本地

http.get

由于大多数请求都是没有主体的 GET 请求,因此 Node.js 提供了这个便捷的方法。 这个方法与 http.request() 的唯一区别是它将方法设置为 GET 并自动调用 req.end():

http.get(url[, options][, callback])

例子:

const http = require("http");
http.get("http://pv.sohu.com/cityjson?ie=utf-8",(res)=>{
  res.setEncoding('utf8');
  let rawData = '';
  res.on('data', (chunk) => { rawData += chunk; });
  res.on('end', () => {
    console.log(rawData)
  });
}).on('error', (e) => {
  console.error(`出现错误: ${e.message}`);
});

运行结果:

var returnCitySN = {"cip": "115.60.61.16", "cid": "410100", "cname": "河南省郑州市"};

http.ClientRequest

http.ClientRequest是由http.request或者是http.get返回产生的对象,表示一个已经产生而且正在进行中的HTPP请求。

一般会显式地在这个对象上绑定监听函数来监听整个请求的状态,如:req.on("error") 监听异常,req.end()结束发起的http请求

服务端http响应

通过http模块在服务端创建http服务,处理客户端的请求返回对应相应数据

http.Server

通过实例化http.Server即可创建http服务, http.Server是一个基于事件的服务器,它是继承自EventEmitter,http.Server提供的事件如下:

- request:当客户端请求到来时,该事件被触发,提供两个参数req和res,表示请求和响应信息,是最常用的事件
- connection:当TCP连接建立时,该事件被触发,提供一个参数socket,是net.Socket的实例
- close:当服务器关闭时,触发事件(注意不是在用户断开连接时) 
- listen:启动一个服务器来监听连接,listen存在多个可能的参数
    server.listen(handle[, backlog][, callback])
    server.listen(options[, callback])
    server.listen(path[, backlog][, callback]) 用于 IPC 服务器。
    server.listen([port[, host[, backlog]]][, callback]) 用于 TCP 服务器。

例子:

  const http=require("http");
  const server=new http.Server();
  server.listen(8080)
  server.on("request",function(req,res){
      res.writeHead(200,{
          "content-type":"text/plain"
      });
      res.write("hello nodejs");
      res.end();
  });
  server.on("close",()=>{
    console.log("http服务关闭")
  })

  server.on("connection",()=>{
    console.log("TCP连接建立")
  })
  setTimeout(()=>{
    server.close()
  },5000)

打开本机浏览器访问http://localhost:8080/,得到内容:

  hello nodejs

服务端运行结果:

  TCP连接建立
  http服务关闭

http.createServer

我们也可以使用http.createServer方法来创建服务,塔返回了一个http.Server对象

http.createServer([options][, requestlistener])

参数说明:

- options <Object>
  IncomingMessage <http.IncomingMessage> 指定要使用的 IncomingMessage 类。用于扩展原始的 IncomingMessage。默认值: IncomingMessage。
  ServerResponse <http.ServerResponse> 指定要使用的 ServerResponse 类。用于扩展原始 ServerResponse。默认值: ServerResponse。
- requestListener <Function>

我们在本地开启一个http服务,且根据不同地址返回不同的内容,根目录请求返回一个本地文件:

const http = require('http');
const fs = require('fs');

const service=http.createServer( (request, response)=>{
  if (request.url == "/") {
    response.writeHead(200, { "Content-Type": "text/html" });
    fs.createReadStream(`${__dirname}/index.html`).pipe(response);
  }else{
    response.writeHead(404, { "Content-Type": "text/plain" });
    response.end("404 error! File not found.");
  }
  
})
service.listen(8080);
console.log('Server running on port 8080.');

http.ServerResponse

http.ServerResponse是返回给客户端的信息,决定了用户最终看到的内容,一般也由http.Server的request事件发送,并作为第二个参数传递,它有三个重要的成员函数,

  • res.writeHead(statusCode,[heasers]):向请求的客户端发送响应头,该函数在一个请求中最多调用一次,如果不调用,则会自动生成一个响应头
  • res.write(data,[encoding]):想请求的客户端发送相应内容,data是一个buffer或者字符串,如果data是字符串,则需要制定编码方式,默认为utf-8,在res.end调用之前可以多次调用
  • res.end([data],[encoding]):结束响应,告知客户端所有发送已经结束,当所有要返回的内容发送完毕时,该函数必需被调用一次,两个可选参数与res.write()相同。如果不调用这个函数,客户端将用于处于等待状态。

上述例子均有调用。

参考