http
服务分为客户端和服务端。我们先来说说服务端。
服务端
创建HTTP服务器
http.createServer(fn)
用来创建http
服务器
const http = require("http");
const server = http.createServer((serverReq, serverRes) => {});
当服务器收到客户端的请求后就会进入该方法serverReq
是请求对象,serverRes
是服务器端响应对象。
启动HTTP服务器
server.listen(port,[host],[backlog],[callback]);
用来启动服务器。
- port 监听的端口号
- host 监听的地址
- backlog 指定位于等待队列中的客户端连接数
- callback 回调函数
server.listen(3000, () => {
console.log("服务启动啦")
})
关闭HTTP服务器
server.close()
用来关闭http
服务,并且还可以监听该事件。
const http = require("http");
const server = http.createServer(function (serverReq, serverRes) {
const url = serverReq.url;
serverRes.end("您访问的地址是:" + url);
});
server.on("close", () => {
console.log("服务关闭啦");
});
server.listen(3000, () => {
console.log("服务器端开始监听!");
server.close();
});
监听服务器错误
server.on('error', (e)=>{
console.log(e)
});
设置超时时间
通过server.setTimeout(msecs, callback)
设置超时时间,超时后不可再复用已经建立的连接,需要发请求需要重新建立连接。默认超时时间是2分钟。
server.setTimeout(msecs, callback);
通过监听timeout
事件来进行超时处理。
server.on('timeout',function(){
console.log('连接已经超时');
});
服务端请求对象
服务端请求对象req
它其实是http.IncomingMessage
实例,我们通常会用它来获取header
、url
、参数等信息。
获取请求链接、http版本、请求方法、请求头部
const http = require("http");
const server = http.createServer((req, res) => {
console.log("1、客户端请求url:" + req.url);
console.log("2、http版本:" + req.httpVersion);
console.log("3、http请求方法:" + req.method);
// 这里使用JSON.stringify是为了方便在控制台查看,实际上是一个对象可以直接使用
console.log("4、http请求头部" + JSON.stringify(req.headers));
res.write("hello");
res.end("world");
});
我们在浏览器键入http://localhost:3000/hello
输出如下
获取get请求参数
既然有请求,那一定会有参数,我们先来说说获取get
请求参数。
get
请求的参数都会在url
里面,我们一般会使用前面学习的url
或者querystring
模块进行处理。
const http = require("http");
const url = require("url");
const server = http.createServer((req, res) => {
// 利用前面学习的url模块进行参数处理
const params = url.parse(req.url, true);
console.log(params.query);
res.write("hello");
res.end("world");
});
我们在浏览器键入http://localhost:3000/hello?name=randy
输出如下
获取post请求参数
我们知道,get请求的参数是在浏览器路径里面,但是post请求的参数是在请求体里面,那这样我们怎么获取到参数呢?
这里就要用到请求对象req
的一些事件了。
const http = require("http");
const server = http.createServer((req, res) => {
let body = "";
req.on("data", function (thunk) {
body += thunk;
});
req.on("end", function () {
console.log("post body is: " + body);
res.end("ok");
});
});
我们用postman
构造一个post请求,http://localhost:3000
传递参数name:jack
输出如下
服务端响应对象
服务端响应对象,它其实是http.ServerResponse
实例。
当接受到来自客户端的http
请求后,用来向客户端返回响应内容,比如状态代码/状态描述信息、响应头部、响应主体。
设置状态代码、状态描述信息
我们可以通过res.statusCode
、res.statusMessage
来设置状态代码、状态描述信息。
当然你也可以直接使用设置头部方法res.writeHead
来设置。相当于是一个简写。
const server = http.createServer((req, res) => {
// 简写 res.writeHead(200, "ok")
res.statusCode = 200;
res.statusMessage = "ok";
res.write("hello");
res.end("world");
});
设置响应头
我们使用res.writeHead()
、res.setHeader()
来实现响应头部的设置。
不过需要注意,就是setHeader
只能写在writeHead
的前面,不然会报错。也就是说writeHead
可以覆盖setHeader
,但是反过来不行。
const http = require("http");
const url = require("url");
const server = http.createServer((req, res) => {
// 设置头部,只能在writeHead的前面,不能在后面。但是writeHead可以覆盖setHeader
res.setHeader("Content-Type", "text-plain");
res.writeHead(200, "ok", {
"Content-Type": "text/html",
});
res.write("hello");
res.end("world");
});
获取响应头、删除响应头
既然可以设置响应头,当然也可以获取和删除响应头。通过getHeader
、removeHeader
来获取和删除响应头。
const http = require("http");
const url = require("url");
const server = http.createServer((req, res) => {
// 设置
res.setHeader("Content-Type", "text-plain");
// 获取
console.log(res.getHeader("content-type")); //text-plain
// 删除
res.removeHeader("Content-Type");
res.writeHead(200, "ok", {
"Content-Type": "text/plain",
});
res.write("hello");
res.end("world");
});
设置响应主体
设置响应主体主要用到 res.write()
以及 res.end()
两个方法
response.write(chunk[, encoding][, callback])
- chunk:响应主体的内容,可以是string,也可以是buffer。当为string时,encoding参数用来指明编码方式。(默认是utf8)
- encoding:编码方式,默认是 utf8。
- callback:当响应体flushed时触发。
response.end([data][, encoding][, callback])
掌握了 res.write()
的话,res.end()
就很简单了。res.end() 的用处是告诉nodejs,header、body都给你了,这次响应就到这里吧。简单理解就是传递响应体并结束。
客户端
http
服务除了用在服务端,还可以用在客户端。对于客户端主要用来创建http
客户端请求。
创建GET请求
下面构造了个GET
请求,访问 http://jsonplaceholder.typicode.com/todos/1
,并将返回的内容打印在控制台。
const http = require("http");
const options = {
protocol: "http:",
hostname: "jsonplaceholder.typicode.com/todos/1",
port: "80",
path: "/",
method: "GET",
};
const client = http.request(options, function (req) {
let data = "";
req.setEncoding("utf8");
req.on("data", function (chunk) {
data += chunk;
});
req.on("end", function () {
console.log(data);
});
console.log(req.statusCode); // 200
console.log(req.statusMessage); // ok
});
client.end();
输出如下,可以看到,通过get请求,获取到了返回的内容。
当然,我们还可以用便捷方法 http.get(options)
http.get("http://jsonplaceholder.typicode.com/todos/1", function (req) {
let data = "";
req.setEncoding("utf8");
req.on("data", function (chunk) {
data += chunk;
});
req.on("end", function () {
console.log(data);
});
console.log(req.statusCode); // 200
console.log(req.statusMessage); // ok
});
创建post请求
下面构造了个POST
请求,访问 http://jsonplaceholder.typicode.com/posts
,并将返回的内容打印在控制台。
const options = {
method: "POST",
protocol: "http:",
hostname: "jsonplaceholder.typicode.com",
port: "80",
path: "/posts",
headers: {
connection: "keep-alive",
"content-type": "application/json; charset=UTF-8",
},
};
// 发送给服务端的数据
const postBody = {
title: "foo",
body: "bar",
userId: 1,
};
// 创建客户端请求
const client = http.request(options, function (req) {
let data = "";
req.on("data", function (chunk) {
data += chunk;
});
req.on("end", function () {
console.log(data);
});
console.log(req.statusCode); // 200
console.log(req.statusMessage); // ok
});
client.write(JSON.stringify(postBody));
client.end();
输出如下,可以看到,通过post
请求,获取到了返回的内容。
可以发现,服务端、客户端都有req
对象,它们其实都是http.IncomingMessage
实例。那这两者是一样的吗?其实是有细微差别的。具体如下图
取消请求
可以使用abort
方法来终止本次请求
req.abort();
域名解析
域名解析顾名思义,就是将于域名解析为ip
地址。在node
中我们可以使用dns
模块来实现该功能。
下面我们来说说dns
模块两个个常用的方法lookup
、resolve4
lookup()
比如我们要查询域名 www.qq.com
对应的ip,可以通过 dns.lookup()
。
const dns = require("dns");
dns.lookup("www.qq.com", function (err, address, family) {
if (err) throw err;
console.log("ip地址为: " + address); // 101.91.22.57
});
我们知道,同一个域名,可能对应多个不同的ip。那么,如何获取一个域名对应的多个ip呢?可以这样。
const dns = require('dns');
const options = { all: true };
dns.lookup("www.qq.com", options, function (err, address, family) {
if (err) throw err;
console.log("ip地址为: " + JSON.stringify(address)); // [{"address":"101.91.22.57","family":4},{"address":"101.91.42.232","family":4}]
});
resolve4()
上面的例子,我们使用resolve4
方法也能实现。
dns.resolve4("www.qq.com", function (err, address) {
if (err) throw err;
console.log(JSON.stringify(address)); // ["101.91.22.57","101.91.42.232"]
});
从上面的例子来看,两个方法都可以查询域名的ip列表。那么,它们的区别在什么地方呢?
可能最大的差异就在于,当配置了本地Host时,是否会对查询结果产生影响。
- dns.lookup():有影响。
- dns.resolve4():没有影响。
举例,在hosts文件里配置了如下规则。
127.0.0.1 www.qq.com
运行如下对比示例子,就可以看到区别。
const dns = require('dns');
dns.lookup('www.qq.com', function(err, address, family){
if(err) throw err;
console.log('配置host后,dns.lokup =>' + address);
});
dns.resolve4('www.qq.com', function(err, address, family){
if(err) throw err;
console.log('配置host后,dns.resolve4 =>' + address);
});
输出如下
配置host后,dns.lookup =>127.0.0.1
配置host后,dns.resolve4 =>182.254.34.74
系列文章
Node.js入门之process模块、child_process模块、cluster模块
后记
感谢小伙伴们的耐心观看,本文为笔者个人学习笔记,如有谬误,还请告知,万分感谢!如果本文对你有所帮助,还请点个关注点个赞~,您的支持是笔者不断更新的动力!