http 模块简介
核心模块 http 是 node.js 网络的关键模块,用于搭建服务器、接受请求、响应内容
const http = require('http'); // 引入 http 模块
http.createServer ( )
- 创建服务器对象 -
http.Server
实例:http.createServer()
- 接收一个回调函数,回调函数带有
req
、res
2 个参数:
req
- [请求对象],它包含了与 [客户端] 相关的数据和属性(http.ServerResponse
实例)
res
- [响应对象],它包含了与 [服务器] 相关的数据和属性
const server = http.createServer((req, res) => {
res.end('superman');
});
-
res.end([data])
:关闭响应;必须在每个响应上调用它!!!
响应结束后,服务器会将消息data
发送给客户端
data
可以是 HTML 代码,res.end()
可以解析 HTML 代码!!! -
res.write(data)
:在响应正文中 发送文本数据给客户端;它会发送缓冲的数据到 HTTP 响应流
const server = http.createServer((req, res) => {
res.write('write');
res.end('Superman');
});
拥有服务器对象后,就可以访问其方法:
-
close()
:停止服务器,不再接受新的连接 -
listen()
:启动服务器、并监听连接
server.listen(3030, _ => console.log('http://127.0.0.1:3030'));
配置响应头
getHeaderNames()
:获取已设置的 HTTP 响应头名称getHeaders()
:获取已设置的 HTTP 响应头内容setHeader('headername', value)
:设置 HTTP 响应头内容getHeader('headername')
:获取指定的 HTTP 响应头removeHeader('headername')
:删除指定的 HTTP 响应头hasHeader('headername')
:如果响应已设置该响应头,则返回true
headersSent()
:如果响应头已被发送给客户端,则返回true
const server = http.createServer((req, res) => {
// 解决中文乱码问题
res.setHeader("content-type", "text/html; charset=utf-8");
// 解决跨域问题
res.setHeader("Access-Control-Allow-Origin", "*")
// 接受自定义请求头
res.setHeader("Access-Control-Allow-Headers", "*")
// ...
res.end('superman');
});
Content-Type
- Content-Type (内容类型),用于定义网络文件的类型和网页的编码
- 编码可带可不带:
"application/json; charset=utf-8"
=="application/json"
- 值对大小写不敏感:
"Application/JSON"
=="application/json"
- 媒体格式类型:
1. "text/html":HTML 格式
2. "text/plain":纯文本格式
3. "text/xml":XML 格式
4. "image/gif":gif 图片格式
5. "image/jpeg":jpg 图片格式
6. "image/png":png 图片格式
- 以 application 开头的媒体格式类型:
1. "application/json":JSON 数据格式
2. "application/xml":XML 数据格式
3. "application/xhtml+xml":XHTML 格式
4. "application/pdf":pdf 格式
5. "application/msword":Word 文档格式
6. "application/octet-stream":二进制流数据
7. "application/x-www-form-urlencoded":<form encType=""> 中默认的 encType,form 表单数据被编码为 key/value 格式发送 到服务器(表单默认的提交数据的格式)
- 另外一种常见的媒体格式是上传文件之时使用的
1. "multipart/form-data":需要在表单中进行文件上传时,就需要使用该格式
response.writeHead()
发送消息头给客户端
response.writeHead(statusCode[, statusMessage][, headers])
:用于向请求发送响应头
① statusCode
:HTTP 状态码
② statusMessage
:携带的信息对象
③ headers
:响应头。可以是 Array,偶数偏移是键,奇数偏移是值
- 返回对
http.ServerResponse
的引用,以便可以链式调用 response.writeHead()
方法只能调用一次,且必须在response.end()
之前调用
const http = require("http");
const server = http.createServer((req, res) => {
res.writeHead(200, { // OK 请求成功
'Content-Length': Buffer.byteLength(body), // Buffer 流的长度
'Content-Type': 'text/plain' // 数据的格式
}).end('superman'); // 链式调用
});
server.listen(3030, _ => console.log('http://127.0.0.1:3030'));
Content-Length
是以字节为单位,而不是字符
使用 Buffer.byteLength()
来确定正文的长度,Node.js 不会检查 Content-Length
和已经传输的正文的长度是否相等
-
response.setHeader()
设置的标头,会与response.writeHead()
设置的标头合并
如果设置的内容一样,则response.writeHead()
的优先级较高 -
如果先调用
response.writeHead()
,后调用response.setHeader()
则response.writeHead()
会直接将提供的标头写入网络通道,且内部不缓存
在标头上response.getHeader()
不会产生预期的结果
如果需要逐步填充标头并在未来进行潜在的检索和修改,则改用response.setHeader()
const http = require('http');
const server = http.createServer((req, res) => {
res.setHeader('Content-Type', 'text/html'); // 使用 setHeader() 设置 Content-Type
res.writeHead(200, { // 又使用 writeHead() 设置 Content-Type
'Content-Type': 'text/plain'
});
res.end('ok'); // 最终 content-type = text/plain
});
server.listen(8080, _ => console.log('服务器开启成功,请访问:http://localhost:8080'));
如果设置的标头字段包含无效字符,将抛出 TypeError
- 如果消息头尚未被发送,使用
response.writeHead()
的话,会先发送消息头;
可以通过response.statusCode
和response.statusMessage
编辑请求中的状态码statusCode
和消息statusMessage
response.statusCode = 500; // Internal Server Error
response.statusMessage = '服务器内部错误,无法完成请求';
获取 get 请求的数据
req
是请求对象,它包含了与客户端相关的数据和属性
① req.url
:获取 URL 路径,默认是 /
② req.method
:获取请求方式 - GET
/ POST
<body>
<button id="box">点击触发</button>
</body>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script>
box.onclick = () => {
axios({
method: "GET",
url: "http://localhost:3030",
params: { // 通过 params 设置 GET 传递的数据
name: "superman"
}
}).then(res => {
console.log("res", res);
// res {data: 'ok', status: 200, statusText: 'OK', headers: {…}, config: {…}, …}
})
}
</script>
const http = require("http");
const url = require("url");
const server = http.createServer((req, res) => {
// 解决跨域问题
res.setHeader("Access-Control-Allow-Origin", "*")
// 使用 url 模块解析 URL 路径,获取 URL 参数
let paramsObj = url.parse(req.url, true).query;
console.log("paramsObj", paramsObj); // paramsObj { name: 'superman' }
res.write('ok'); // 响应请求
res.end();
})
server.listen("3030", () => console.log("http://127.0.0.1:3030"));
获取 post 请求的数据
<body>
<button id="box">点击触发</button>
</body>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script>
box.onclick = () => {
axios({
method: "POST",
url: "http://localhost:3030",
data: { // 通过 data 设置 POST 传递的数据
name: "superman"
}
}).then(res => {
console.log("res", res);
// res {data: 'ok', status: 200, statusText: 'OK', headers: {…}, config: {…}, …}
})
}
</script>
const http = require("http");
const server = http.createServer((req, res) => {
// 解决跨域问题
res.setHeader("Access-Control-Allow-Origin", "*")
// 设置接受的自定义请求头
res.setHeader("Access-Control-Allow-Headers", '*')
// 监听 req 的 data 事件,在其回调函数中 以参数形式获取 POST 传递的数据
req.on("data", data => console.log(data.toString())); // {"name":"superman"}
req.on("end", () => {}); // 关闭监听
res.write('ok'); // 响应请求
res.end();
})
server.listen("3030", () => console.log("http://127.0.0.1:3030"));
路由的使用
<body>
<button id="box1">点击 get 请求 1</button>
<button id="box2">点击 get 请求 2</button>
</body>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script>
box1.onclick = () => {
axios({
url: "http://localhost:3030",
method: "GET",
}).then(res1 => {
console.log('res1', res1);
// res1 {data: '/ 路由', status: 200, statusText: 'OK', headers: {…}, config: {…}, …}
})
}
box2.onclick = () => {
axios({
url: "http://localhost:3030/test",
method: "GET",
}).then(res2 => {
console.log("res2", res2);
// res2 {data: '/test 路由', status: 200, statusText: 'OK', headers: {…}, config: {…}, …}
})
}
</script>
const http = require("http");
const server = http.createServer((req, res) => {
res.setHeader("Access-Control-Allow-Origin", "*")
// 根据 req.url 设置路由
console.log("路由路径", req.url);
// 路由路径 /
// 路由路径 /test
if (req.url == "/") {
res.write("/ 路由")
} else if (req.url == "/test") {
res.write("/test 路由")
}
res.end();
})
server.listen(3030, () => console.log("http://localhost:3030"));
页面中
link
、a
、img
、script
、window.location.href
会自动发送一个请求到后端所以后端中需要设置对应的请求响应
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>node.html</title>
<link rel="stylesheet" href="./index.css">
</head>
<body>
<img src="./pic.jpg">
<div>
我是 node 页面
</div>
</body>
</html>
/* index.css */
div {
background-color: skyblue;
}
const http = require("http");
const fs = require("fs")
const server = http.createServer((req, res) => {
// 根据路由返回页面
console.log("路由地址", req.url);
if (req.url == "/") {
fs.readFile(__dirname + "/index.html", (err, data) => {
res.end(data); // res.end() 可以解析 HTML 代码!
})
} else if (req.url == "/index.css") {
fs.readFile(__dirname + "/index.css", (err, data) => {
res.end(data)
})
} else if (req.url == "/pic.jpg") {
fs.readFile(__dirname + "/pic.jpg", (err, data) => {
res.end(data)
})
}
})
server.listen(3030, _ => console.log("http://127.0.0.1:3030"))