NodeJS搭建HTTP服务器的实现步骤

在 NodeJS 中用来创建服务的模块是 http 核心模块,本篇就来介绍关于使用 http 模块搭建 HTTP 服务器和客户端的方法,以及模块的基本 API。

HTTP 服务器

1、创建 HTTP 服务器

在 NodeJS 中,创建 HTTP 服务器可以与 net 模块创建 TCP 服务器对比,创建服务器有也两种方式。

方式 1:

const http = require("http"); const server = http.createServer(function(req, res) { // ...... }); server.listen(3000);

方式 2:

const http = require("http"); const server = http.createServer(); server.on("request", function(req, res) { // ...... }); server.listen(3000);

在 createServer 的回调和 request 事件的回调函数中有两个参数,req(请求)、res(响应),基于 socket,这两个对象都是 Duplex 类型的可读可写流。

http 模块是基于 net 模块实现的,所以 net 模块原有的事件在 http 中依然存在。

const http = require("http"); const server = http.createServer(); // net 模块事件 server.on("connection", function(socket) { console.log("连接成功"); }); server.listen(3000);

2、获取请求信息

在请求对象 req 中存在请求的方法、请求的 url(包含参数,即查询字符串)、当前的 HTTP 协议版本和请求头等信息。

const http = require("http"); const server = http.createServer(); server.on("request", function(req, res) { console.log(req.method); // 获取请求方法 console.log(req.url); // 获取请求路径(包含查询字符串) console.log(req.httpVersion); // 获取 HTTP 协议版本 console.log(req.headers); // 获取请求头(对象) // 获取请求体的内容 let arr = []; req.on("data", function(data) { arr.push(data); }); req.on("end", function() { console.log(Buffer.concat(arr).toString()); }); }); server.listen(3000, function() { console.log("server start 3000"); });

通过 req 对应的属性可以拿到请求行和请求首部的信息,请求体内的内容通过流操作来获取,其中 url 中存在多个有用的参数,我们自己处理会很麻烦,可以通过 NodeJS 的核心模块 url 进行解析。

const url = require("url"); let str = "http://user:pass@:8080/src/index.html?a=1&b=2#hash"; // parse 方法帮助我们解析 url 路径 let obj = url.parse(str, true); console.log(obj); // { // protocol: 'http:', // slashes: true, // auth: 'user:pas', // host: 'www.pandashen.com:8080', // port: '8080', // hostname: 'www.pandashen.com', // hash: '#hash', // search: '?a=1&b=2', // query: '{ a: '1', b: '2' }', // pathname: '/src/index.html' // path: '/src/index.html?a=1&b=2', // href: 'http://user:pass@:8080/src/index.html?a=1&b=2#hash' }

在被解析路径返回的对象中有几个属性被经常使用:

host:主机(域名 + 端口号);

hostname:主机名;

query:请求参数(查询字符串或参数对象);

pathname:资源路径(根据不同的路径返回不同的资源)。

我们使用 url 的 parse 方法来帮我们解析请求路径,在真实的服务器中传入的第一个参数为 req.url,第二个参数不传时,query 会被解析成 a=1&b=2 的形式,第二个参数传入 true,query 属性的查询字符串会被解析成对象的形式。

url 模块中,将查询字符串 a=1&b=2 转换为对象 { a: '1', b: '2' } 的实现方式其实是使用正则替换实现的。

模拟查询字符串转换对象的核心逻辑:

let str = "a=1&b=2&c=3"; let obj = {}; str.replace(/([^=&]+)=([^=&]+)/g, function() { obj[arguments[1]] = arguments[2]; }); console.log(obj); // { a: '1', b: '2', c: '3' }

在上面代码的 replace 方法的回调函数中参数集合的第一项为匹配到的字符串,第二项为第一个分组的值,第三项为第二个分组的值,依次类推,倒数第二项为分组匹配的索引,最后一项为原字符串。

3、设置响应信息

我们可以通过 req 来获取请求信息,自然也可以通过 res 来设置响应信息返回给客户端。

const http = require("http"); const server = http.createServer(); server.on("request", function(req, res) { // 设置响应头(过去的用法),不能多次调用,见到要认识 res.writeHead(200, { "Content-Type": "text", a: "hello world" }); // 设置响应头(现在的用法,常用),可以多次调用,每次设置一个响应头 res.setHeader("Content-Type", "text"); // 设置状态码,不设置默认为 200 res.statusCode = 200; // 不发送 Date(日期)响应头 res.sendDate = false; // 返回内容 res.write("hello world"); // 不会关闭连接 res.end("hello world"); // 将内容返回后关闭连接 }); server.listen(3000, function() { console.log("server start 3000"); });

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/97e07c7a0d74a237ff7c2205bc12f7e4.html