一、创建一个简单的HTTP服务器
- 第一步:导入http模块。
- 第二步:创建服务对象,
createServer()方法的参数是回调函数,回调函数有两个参数,分别是request和response对象。 - 第三步:启动http服务,
listen()方法的第一个参数是端口号,第二个参数是回调函数,当服务启动时,执行回调函数。
示例:
const http = require('http');
//创建服务对象
const server = http.createServer((request,response)=>{
//当服务接收到http请求后执行回调函数
response.end('Hello HTTP Server'); //设置响应体,并返回响应内容
});
//监听端口,启动服务器
server.listen(9000,()=>{
//服务启动成功后执行回调函数
console.log('服务启动成功');
});
注意事项:
- 使用
Ctrl + c停止服务 - 中文乱码的解决方法
response.setHeader('content-type','text/html;charset=utf-8'); //设置响应头
- 端口被占用的解决方法:杀死占用端口的进程或者换一个端口号
- HTTP的默认端口是80
二、HTTP请求
1、获取请求行和请求头
服务端代码
const server = http.createServer((request,response)=>{
console.log(request);
});
获取请求的方法
request.method
获取请求的URL
request.url
获取请求头
requrest.headers
请求头的内容如下
{
host: 'localhost:9000',
connection: 'keep-alive',
'cache-control': 'max-age=0',
'sec-ch-ua': '"Not.A/Brand";v="8", "Chromium";v="114", "Google Chrome";v="114"',
'sec-ch-ua-mobile': '?0',
'sec-ch-ua-platform': '"Windows"',
'upgrade-insecure-requests': '1',
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36',
accept: 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7',
'sec-fetch-site': 'none',
'sec-fetch-mode': 'navigate',
'sec-fetch-user': '?1',
'sec-fetch-dest': 'document',
'accept-encoding': 'gzip, deflate, br',
'accept-language': 'zh-CN,zh;q=0.9',
cookie: 'Idea-8525aa25f9=d3805295-ca45-4555-9a3f-37900fb1ec59'
}
2、获取请求体
创建一个 HTTP 服务器,并在 request 对象上监听 data 和 end 事件。当浏览器发送请求时,将请求体分块发送。在每个分块被接收时,都会触发一次data事件,需要将其转换为字符串并将其附加到 body 变量中。当请求体接受完毕后, end 事件被触发,此时打印出请求体,并向浏览器发送响应。
const http = require('http');
const server = http.createServer((request,response)=>{
//当服务接收到http请求后执行回调函数
response.setHeader('content-type','text/html;charset=utf-8'); //设置响应头
let body = '';
request.on('data',chunk=>{
body += chunk.toString();
});
request.on('end',()=>{
console.log(body);
response.end('Hello HTTP Server'); //设置响应体,并返回响应内容
});
});
//监听端口,启动服务器
server.listen(9000,()=>{
//服务启动成功后执行回调函数
console.log('服务启动成功');
});
3、获取请求路径和请求参数
(1)方式一:
请求URL:http://localhost:9000/search?param=hello
使用url模块解析请求路径和参数
const url = require('url');
1.解析前的URL
console.log(request.url);
结果是"请求路径 + 请求参数"
/search?param=hello
2.解析request.url,url.parse()不传第二个参数
let res = url.parse(request.url); //解析URL
console.log(res);
解析后的res对象,请求路径是pathname属性,请求参数query属性被解析成字符串。
Url {
protocol: null,
slashes: null,
auth: null,
host: null,
port: null,
hostname: null,
hash: null,
search: '?param=hello',
query: 'param=hello',
pathname: '/search',
path: '/?param=hello',
href: '/?param=hello'
}
注意:请求参数query属性是一个字符串
3.解析request.url,url.parse()的第二个参数是true
let res = url.parse(request.url,true); //获取请求路径,第二个参数为true表示解析请求参数
解析后的res对象,请求参数被解析成对象
Url {
protocol: null,
slashes: null,
auth: null,
host: null,
port: null,
hostname: null,
hash: null,
search: '?param=hello',
query: [Object: null prototype] { param: 'hello' },
pathname: '/search',
path: '/?param=hello',
href: '/?param=hello'
}
注意:请求参数query属性是一个对象,请求参数被拆成了键值对的形式
4.完整示例
const http = require('http');
const url = require('url');
const server = http.createServer((request,response)=>{
let res = url.parse(request.url,true); //获取请求路径,第二个参数为true表示解析请求参数
let pathname = res.pathname; //请求路径
let param = res.query.param; //请求参数
console.log(pathname,param);
//当服务接收到http请求后执行回调函数
response.setHeader('content-type','text/html;charset=utf-8'); //设置响应头
response.end('Hello HTTP Server'); //设置响应体,并返回响应内容
});
//监听端口,启动服务器
server.listen(9000,()=>{
//服务启动成功后执行回调函数
console.log('服务启动成功');
});
请求http://localhost:9000/search?param=hello的执行结果
/search hello
(2)方式二(推荐使用):
使用URL对象解析请求路径
//第一个参数是请求路径和参数,第二个参数是请求的IP和端口
let url = new URL(request.url,'http://localhost:9000');
console.log(url);
打印结果
URL {
href: 'http://localhost:9000/search?param=hello',
origin: 'http://localhost:9000',
protocol: 'http:',
username: '',
password: '',
host: 'localhost:9000',
hostname: 'localhost',
port: '9000',
pathname: '/search',
search: '?param=hello',
searchParams: URLSearchParams { 'param' => 'hello' },
hash: ''
}
注:pathname属性是请求路径,searchParams属性是请求参数
完整实例
const http = require('http');
const server = http.createServer((request,response)=>{
let url = new URL(request.url,'http://localhost:9000');
console.log(url.pathname);
//使用get方法获取请求参数的value,参数是key
console.log(url.searchParams.get('param'));
//当服务接收到http请求后执行回调函数
response.setHeader('content-type','text/html;charset=utf-8'); //设置响应头
response.end('Hello HTTP Server'); //设置响应体,并返回响应内容
});
//监听端口,启动服务器
server.listen(9000,()=>{
//服务启动成功后执行回调函数
console.log('服务启动成功');
});
访问http://localhost:9000/search?param=hello的执行结果
/search
hello
三、HTTP响应
1、设置响应行和响应头
(1)设置响应状态码和状态描述
const http = require('http');
const server = http.createServer((request,response)=>{
//当服务接收到http请求后执行回调函数
response.statusCode = 202; //设置响应状态码
response.statusMessage = 'hello,world!'; //设置响应状态描述
response.end('Hello HTTP Server'); //设置响应体,并返回响应内容
});
//监听端口,启动服务器
server.listen(9000,()=>{
//服务启动成功后执行回调函数
console.log('服务启动成功');
});
(2)设置响应头
使用response.setHeader(key,value)方法,第一个参数是响应头名称,第二个参数是响应头的值
response.setHeader('content-type','text/html;charset=utf-8'); //设置响应头
response.setHeader('Server','Node.js'); //设置服务器名称
response.setHeader('Customer-Header','hello,world!'); //设置自定义响应头
(3)设置多个响应头
response.setHeader('multiple-header',['first-header','second-header','third-header']);
2、设置响应体
(1)使用response.write(内容);设置响应体
response.write('hello,');
response.write('world!\n');
response.end();
页面显示“hello,world!”
(2)使用response.end(内容);设置响应体
response.end()方法会在设置响应体之后,将响应返回给浏览器。
response.end('Hello HTTP Server'); //设置响应体,并返回响应内容
页面显示“Hello HTTP Server”
3、静态资源
(1)获取静态资源
如果一个HTML页面引用了静态资源,则浏览器会发送多个请求,每个请求都会获取一个静态资源,例如:css、javascript、图片等。
浏览器发送的请求
(2)处理静态资源请求
因为每个静态资源都对应一个请求路径(http://localhost:9000/请求路径/静态资源名称),因此需要对静态资源请求进行处理,当请求到达时,读取对应的静态资源文件,然后将静态资源的内容返回给浏览器。
(3)编写一个静态资源服务
为了演示静态资源请求和普通的请求一样,下面的代码直接将请求路径写死在程序中,在实际开发中不应该这样写。
目录结构
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" href="./index.css">
</head>
<body>
<table border="1">
<tr>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td></td>
<td></td>
</tr>
</table>
<script src="./index.js"></script>
</body>
</html>
index.css
td {
padding: 20px 40px;
}
table tr:nth-child(odd){
background: #aef;
}
table tr:nth-child(even){
background: #fcb;
}
table,td{
border-collapse: collapse;
}
index.js
let tds = document.querySelectorAll('td');
tds.forEach(item => {
item.onclick = function(){
this.style.background = '#222';
}
});
10_响应练习.js
const http = require('http');
const fs = require('fs');
const server = http.createServer((requrest,response)=>{
//获取请求URL的路径
let {pathname} = new URL(requrest.url,'http://localhost:9000');
if(pathname === '/'){
let html = fs.readFileSync(__dirname + '/index.html');
response.end(html); //end方法的参数可以是字符串,也可以是buffer
}else if(pathname === '/index.css'){
let css = fs.readFileSync(__dirname + '/index.css');
response.end(css);
}else if(pathname === '/index.js'){
let js = fs.readFileSync(__dirname + '/index.js');
response.end(js);
}else{
response.statusCode = 404;
response.end('<h1>404 Not Found</h1>');
}
});
server.listen(9000,()=>{
console.log('服务已启动......');
});