Node.js-http模块
HTTP 协议
概念
- HTTP(hypertext transport protocol)协议;中文叫超文本传输协议,是一种基于TCP/IP的应用层通信协议
- 这个协议详细规定了 浏览器 和万维网 服务器 之间互相通信的规则。
- 协议中主要规定了两个方面的内容
- 客户端:用来向服务器发送数据,可以被称之为请求报文
- 服务端:向客户端返回数据,可以被称之为响应报文
客户端请求规范(请求报文组成)
1. 请求行
- 由三部分组成:
- 请求方法
- 常用的请求方法
- GET:获取资源
- POST:提交资源
- PUT:更新资源
- DELETE:删除资源
- HEAD:获取资源的元信息
- OPTIONS:获取服务器支持的请求方法
- 请求URL:统一资源定位符
http://www.example.com:8080/path/to/resource?query=param#fragment
// 协议:http(https、ftp、ssh等) 通信协议
// 域名:www.example.com 服务器地址
// 端口:8080 端口号,默认端口号为80,可省略
// 路径:/path/to/resource 资源位置
// 查询参数:?query=param 用于向服务器传递额外信息
// 锚点:#fragment 页面内定位(浏览器端使用),哈希(锚点链接)
- HTTP 协议版本
- 例如:HTTP/1.1或HTTP/2
2.请求头
- 采用键值对格式:头名: 头值
头名 | 作用 | 示例 |
---|---|---|
Host | 目标主机 | Host: www.example.com |
User-Agent | 客户端标识,用户代理,客户端字符串标识,服务器可以通过这个标识来识别这个请求来自User-Agent,哪个客户端 ,一般在PC端和手机端的区分 | User-Agent: Mozilla/5.0 |
Accept | 可接收的响应类型 | Accept: text/html |
Accept-Encoding | 可接受的压缩编码类型 | Accept-Encoding: gzip, deflate |
Cookie | 客户端存储信息 | Cookie: session_id=abc123 |
Content-Type | 请求体类型 | Content-Type: application/json |
Authorization | 身份验证 | Authorization: Bearer token |
Connection | 连接的设置 keep-alive(保持连接);close(关闭连接) | Connection: keep-alive |
Cache-Control | 缓存控制 max-age = 0 (没有缓存) | Cache-Control: no-cache |
Upgrade-Insecure-Requests | 将网页中的http请求转化为https请求(很少用)老网站升级 | Upgrade-Insecure-Requests: 1 |
Accept-Language | 可接受的语言 | Accept-Language: en-US,en;q=0.9 |
3.空行
- 用于分隔请求头和请求体
4.请求体
包含客户端发送给服务器的数据:
- GET请求:通常没有请求体
- POST/PUT请求:包含表单数据、JSON、文件等
- 用于向服务器提交数据,例如表单数据、JSON数据等。
- 请求体的格式取决于请求头中的Content-Type字段。
- 常见的请求体格式有:
- application/x-www-form-urlencoded:表单数据
- multipart/form-data:文件上传
- 表单:name=John&age=30
- JSON:{“name”: “John”, “age”: 30}
- XML:John
服务端响应规范(响应报文组成)
1.状态行(Status Line)
- 由三部分组成:
- HTTP协议版本
- HTTP/1.1:HTTP协议版本号
- 状态码(Status Code)
//1xx 信息响应 ,请求已接收,继续处理 //2xx 成功响应,请求成功处理 //3xx 重定向,需要进一步操作 //4xx 客户端错误,客户端请求错误 //5xx 服务器错误,服务器处理错误 //例如: //200 OK:请求成功 //301 Moved Permanently:永久重定向 //404 Not Found:资源不存在 //500 Internal Server Error:服务器内部错误
- 状态描述(Reason Phrase)
- OK:请求成功
- Not Found:请求的资源不存在
- Internal Server Error:服务器内部错误
- Bad Request:客户端请求错误
- Unauthorized:未授权
- Forbidden:禁止访问
- HTTP协议版本
- 响应头
服务器返回的元数据信息
常见的响应头 | 作用 | 示例 |
---|---|---|
Content-Type | 响应体类型 | Content-Type: text/html;charset=utf-8,设置响应体的数据类型以及字符集,响应体为html,字符集utf-8 |
Content-Length | 响应体的长度,单位为字节 | Content-Length: 1234 |
Set-Cookie | 设置客户端Cookie | Set-Cookie: session_id=abc123 |
Cache-Control | 缓存控制 | Cache-Control: max-age=3600 |
Location | 重定向目标 | Location: /new-path |
- 空行
分隔响应头和响应体的空行 - 响应体
服务器返回的实际内容 - HTML页面
- JSON/XML数据
- 图片/视频等二进制文件
- JavaScript/CSS等资源
MIME类型处理
HTTP通过Content-Type头指定数据的MIME类型
文件类型 | MIME类型 | 说明 |
---|---|---|
HTML | text/html | 网页内容 |
CSS | text/css | 样式表 |
JavaScript | application/javascript | 脚本 |
JSON | application/json | 结构化数据 |
TEXT | text/plain | 文本 |
JPEG | image/jpeg | 图片 |
application/pdf | 文档 | |
XML | application/xml | XML数据 |
ZIP | application/zip | 压缩文件 |
GIF | image/gif | GIF图片 |
PNG | image/png | PNG图片 |
SVG | image/svg+xml | SVG图片 |
MP3 | audio/mpeg | 音频 |
MP4 | video/mp4 | 视频 |
连接管理
HTTP协议支持不同的连接策略
- HTTP/1.0:短连接(每次请求新建连接)
- HTTP/1.1:持久连接(默认启用Keep-Alive)
- HTTP/2:多路复用(多个请求共享一个连接)
- HTTP/3:QUIC协议(基于UDP的快速传输协议)
Node.js 创建 HTTP 服务
Node.js 内置的 http 模块可以轻松创建高性能的 HTTP 服务器
// 1.导入 http 模块
const http = require('http');//2. 创建服务对象 create 创建 server 服务
//request 意为请求. 是对请求报文的封装对象, 通过 request 对象可以获得请求报文的数据
//response 意为响应. 是对响应报文的封装对象, 通过 response 对象可以设置响应报文
const server = http.createServer((req, res) => {// 设置响应头//res.setHeader('Content-Type', 'text/plain');// 设置响应头防止中文乱码res.setHeader('content-type','text/html;charset=utf-8');// 发送响应res.end('哈哈哈Hello, World!\n');})
//3. 启动服务器监听指定端口
server.listen(3000, () => {console.log('服务启动成功, 端口号为 3000')
})
注意:
- 1.响应内容中文乱码的解决办法
// 设置响应头防止中文乱码
res.setHeader('content-type','text/html;charset=utf-8');
-
2.端口号被占用
解决办法:修改端口号
-
3.HTTP 协议默认端口是 80 。HTTPS 协议的默认端口是 443, HTTP 服务开发常用端口有 3000,
8080,8090,9000 等
获取 HTTP 请求报文(请求对象 (request) 详解)
想要获取请求的数据,需要通过 request 对象
const server = http.createServer((req, res) => {// 1. 获取请求方法const method = req.method; // GET, POST 等// 2. 解析请求URLconst url = new URL(req.url, `http://${req.headers.host}`);
// URL {
// href: 'http://localhost:3000/?a=1',
// origin: 'http://localhost:3000',
// protocol: 'http:',
// username: '',
// password: '',
// host: 'localhost:3000',
// hostname: 'localhost',
// port: '3000',
// pathname: '/',
// search: '?a=1',
// searchParams: URLSearchParams { 'a' => '1' },
// hash: ''
// } url1111// 3. 获取请求路径const pathname = url.pathname; // 如:'/api/user'// 4. 获取查询参数const query = Object.fromEntries(url.searchParams);// 5. 获取请求头const contentType = req.headers['content-type'];// 6. 获取请求体 (POST/PUT)let body = '';req.on('data', chunk => body += chunk);req.on('end', () => {console.log('请求体内容:', body);// 设置响应res.end(`请求方法: ${method}, 路径: ${pathname}`);});
});
注意:
- request.headers 将请求信息转化成一个对象,并将属性名都转化成了『小写』
- 关于路径:如果访问网站的时候,只填写了 IP 地址或者是域名信息,此时请求的路径为『 / 』
- 关于 favicon.ico:这个请求是属于浏览器自动发送的请求
const http = require('http');
const server = http.createServer((req, res) => {// 获取请求方法和路径// const {method, url} = req;// console.log(req.url,'xxxxxxx') // /sm/api/user http://localhost:3000/sm/api/user post// console.log(req.url,'xxxxxxx') // / http://localhost:3000/ Get// console.log(req.url,'xxxxxxx') // /about http://localhost:3000/about Getconst { method } = req;const url = new URL(req.url, `http://${req.headers.host}`);const pathname = url.pathname;// 设置响应头res.setHeader('Content-Type', 'text/html; charset=utf-8');// 路由处理if (method === 'GET' && pathname === '/') {res.end('<h1>首页</h1>');} else if (method === 'GET' && pathname === '/about') {res.end('<h1>关于我们</h1>');} else if (method === 'POST' && pathname === '/api/user') {// 处理API请求...res.end(JSON.stringify({ code: 200, data: { name: '苏木' } }));} else {res.statusCode = 404;res.end('<h1>页面不存在</h1>');}});server.listen(3000, () => {console.log('服务器已启动,监听端口 3000');});
设置 HTTP 响应报文(响应对象 (response) 详解)
const server = http.createServer((req, res) => {// 1. 设置状态码res.statusCode = 200; // 默认200,可以设置为404等// 2. 设置响应头res.setHeader('Content-Type', 'application/json');res.setHeader('Cache-Control', 'public, max-age=3600');// 3. 写入响应内容(多次写入)res.write('第一部分数据');res.write('第二部分数据');// 4. 结束响应并发送res.end('最后内容');// 5. 一次性写入并结束// res.end(JSON.stringify({ message: 'Hello' }));
});
静态文件服务
实现静态资源服务器
const http = require('http');
const fs = require('fs');
const path = require('path');// MIME 类型映射
const mimeTypes = {'.html': 'text/html','.js': 'text/javascript','.css': 'text/css','.json': 'application/json','.png': 'image/png','.jpg': 'image/jpeg','.gif': 'image/gif','.svg': 'image/svg+xml',
};const server = http.createServer((req, res) => {// 获取文件路径 public 文件夹下的文件的静态资源const filePath = path.join(__dirname, 'public', req.url);// 获取文件扩展名const extname = path.extname(filePath);// 设置默认内容类型let contentType = mimeTypes[extname] || 'application/octet-stream';// 读取文件fs.readFile(filePath, (err, data) => {if (err) {// 文件不存在if (err.code === 'ENOENT') {res.statusCode = 404;res.end('<h1>404 Not Found</h1>');} else {// 成功读取文件res.setHeader('Content-Type', contentType);res.end(data);}});
});server.listen(9000);// 访问: http://localhost:3000/232.png
// 结果如下