目录
- 前言
- 一,创建HTTP模块
- 1.1 基本使用
- 1.2 注意事项
- 二,查看报文
- 2.1 浏览器查看HTTP报文
- 2.2 利用request获取HTTP请求报文
- 2.2.1 获取请求行和请求头
- 2.2.2 获取请求路径
- 2.2.3 获取查询字符串
- 三,跟请求报文相关的练习
- 四,设置响应报文
- 五,HTTP响应练习
- 六,网页资源
- 6.1 网页资源加载的基本过程
- 6.2 实现网页引入外部资源
- 6.3 静态资源与动态资源
- 后记
前言
学习本节内容要对客户端发送请求有一定了解,需要有nodejs的相关知识的基础。
如果这些知识掌握的不牢固,可以在我的专栏里面看到相关内容:
前后端交互知识储备
Nodejs
话不多说,开始学习。
一,创建HTTP模块
1.1 基本使用
HTTP是Nodejs的一个内置模块,不需要npm下载就可以直接使用,以下是基本的使用:
//导入httpmok
const http = require('http');
//创建服务对象
const server = http.createServer((request, response) => {
response.end('Hello HTTP Server');//设置响应体,结束响应
});
//监听端口,启动服务
server.listen(9000, () => {
//服务启动成功
console.log('服务已启动')
})
上面这个模块,要说的是,request和response。request封装了请求报文的相关内容,我们可以通过request看到客户端发送的请求内容;而response则是封装了响应报文的相关内容。
这里可以参考下我的这篇文章:
与前端相关的计网知识
继续说刚刚的代码,我们先在终端运行:
接着在本机回环地址的9000端口打开:
1.2 注意事项
1.命令行 ctrl + c 停止服务;
2.服务启动后,更新代码必须重启服务才能生效;
3.响应内容乱码解决:
response.setHeader('content-type', 'text/html;charset=utf-8');
二,查看报文
报文一共有两种,分为请求报文与响应报文。本节内容非常关键,教会读者如何通过浏览器、写代码来获取报文。
2.1 浏览器查看HTTP报文
运行后端代码,打开本地回环地址,f12打开终端,点开‘网络’:
点击请求:
右边就是相关内容。
但是现在我们看不到请求体,因为get请求的请求体绝大部分都是空的。所以我们现在写一个post:
<!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>Document</title>
</head>
<body>
<form action="http://127.0.0.1:9000" method="post">
<input type="text" name="username">
<input type="password" name="password">
<input type="submit" value="提交">
</form>
</body>
</html>
点击post后,会多出一个‘载荷’,里面是格式化后的请求体内容。
也可也点击上面的‘查看源代码’就可以看到原始的请求体内容了:
2.2 利用request获取HTTP请求报文
上一节讲解了报文的查看,事实上,在实际操作中,请求报文的获取更为重要,因为我们需要获取用户发起请求中的内容,然后给用户反应正确的响应结果。
2.2.1 获取请求行和请求头
通过request对象获取:
含义 | 语法 |
---|---|
请求方法 | request.method |
请求路径 | request.url |
URL路径 | request(‘url’).parse(request.url).pathname |
URL查询字符串 | request(‘url’).parse(request.url,true).query |
请求头 | request.headers |
请求体 | request.on(‘end’, function(){}) |
几个注意事项:
1.request只能获取路径及查询字符串,无法获取URL中的域名和协议内容;
2.request.headers将请求信息转化为一个对象,且属性名都是小写;
3.关于路径,如果访问网站的时候,只填写了IP地址或者是域名信息,此时请求的路径为‘/';
4.关于favicon.ico:这个请求是属于浏览器自动发送的请求。
2.2.2 获取请求路径
这里介绍一个内置模块:url。
首先也是正常的导入流程:
//导入url模块
const url = require('url')
接着是路由和监听:
const server = http.createServer((request, response) => {
//解析request.url这个内容
let res = url.parse(request.url);//parse是url本身的一个方法,单词的意思是解析
console.log(res)
response.end('url')
})
server.listen(9000, () => {
console.log('服务已启动')
})
我们用一个表单输入执行后,URL会被打印下来:
其中,pathname就是我们需要的地址。
2.2.3 获取查询字符串
在刚刚的基础之上,把parse后面加上一个’true’:
再次运行,下面会获取一些对象:
查询字符串:
三,跟请求报文相关的练习
需求:按照以下要求搭建HTTP服务:
请求类型 | 请求地址 | 响应体结果 |
---|---|---|
get | /login | 登录页面 |
get | /reg | 注册页面 |
代码:
const http = require('http');
const server = http.createServer((request, response) => {
//判断请求方法,url路径
let {method} = request
let {pathname} = new URL(request.url, 'http://127.0.0.1')
console.log(method)
console.log(pathname)
response.setHeader('content-type', 'text/html;charset=utf-8');
if(method == "GET" && pathname === '/login') {
response.end('登录页面')
}
if(method == "GET" && pathname === '/reg') {
response.end('注册页面')
} else {
response.end('404 Not Found')
}
})
server.listen(9000, () => {
console.log('服务已经启动')
})
四,设置响应报文
前面的内容我们了解了如何获取请求报文,在获取请求报文后我们需要给用户响应的反馈,所以本节,就是在告诉读者,如何设置响应报文。
作用 | 语法 |
---|---|
设置响应状态码 | response.statusCode |
设置响应状态描述 | response.statusMessage(用的非常少) |
设置响应头信息 | response.setHeader(‘头名’, ‘头值’) |
设置响应体 | response.write(‘xx’) response.end(‘xxx’) |
请求必须要有end。有且只有一次个。
五,HTTP响应练习
搭建HTTP服务,响应一个4行4列的表格:
const http = require('http')
const server = http.createServer((request, response) => {
response.setHeader('content-type', 'text/html;charset=utf-8')
response.end(`
<!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>Document</title>
<style>
td {
padding: 20px 40px;
}
table, td {
border-collapse: collapse;
}
</style>
</head>
<body>
<table border="1">
<tr><td><td/><td><td/></tr>
<tr><td><td/><td><td/></tr>
<tr><td><td/><td><td/></tr>
<tr><td><td/><td><td/></tr>
</table>
</body>
</html>
`)
})
server.listen(9000, () => {
console.log('服务已经启动')
})
在这些代码中,实际上是在js中写html、css、js。非常麻烦。如何去解决这一个问题?
优化版:把三件套写的内容给拿出来,然后直接放到end里面。
const http = require('http')
//导入fs模块
const fs = require('fs')
const server = http.createServer((request, response) => {
response.setHeader('content-type', 'text/html;charset=utf-8')
let html = fs.readFileSync(__dirname + './返回的表格.html')
response.end(html)
})
server.listen(9000, () => {
console.log('服务已经启动')
})
六,网页资源
6.1 网页资源加载的基本过程
不是一下子,一次加载,而是循序渐进的过程。
一般情况下,几次加载都是并行发送出去,等待结果回来。
6.2 实现网页引入外部资源
在第五节的案例中,我们通过fs读取文件,并把文件读取后,end出去了。
现在我们尝试,让index.html中的内容仅有html,样式和js都在index.html中导入:
<!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>Document</title>
<link rel="stylesheet" href="./index.css">
</head>
<body>
<div class="box">
<h3>这个一个引外部资源的案例</h3>
<h3>我现在一点都不快乐</h3>
<h3>我感觉我的快乐就像是一条线,被抽离走了</h3>
<button class="btn">点击按钮,还我快乐</button>
</div>
<script src="./index.js"></script>
</body>
</html>
如果直接进行如第五节一样的读取和end出去会出现的情况是:没有样式,也没有js。
样式是有了:
为何不生效?
点开css的请求一看:即使是css的请求,点开之后依旧是html:
js也是如此:
怎么解决:调整回调函数的代码。
根据内容,区分请求,也就是,根据请求头,来返回内容。
const fs = require('fs')
const http = require('http')
const server = http.createServer((request, response) => {
//获取请求路径
let {pathname} = new URL(request.url, 'http://127.0.0.1')
if(pathname === '/') {
const neirong = fs.readFileSync(__dirname + '/index.html')
response.end(neirong)
} else if(pathname === '/index.css') {
const neirong = fs.readFileSync(__dirname + '/index.css')
response.end(neirong)
} else if(pathname === '/index.js') {
const neirong = fs.readFileSync(__dirname + '/index.js')
response.end(neirong)
} else {
response.statusCode = 404;
response.end('404 not found')
}
})
server.listen('9000', () => {
console.log('服务器已启动')
})
最后就会有正常的结果了:
(请忽略我的emo,看了一下午nodejs是真的emo)
6.3 静态资源与动态资源
静态资源:内容长时间不发生改变的资源,例如图片、视频、css文件、js文件、html文件、字体文件等;
动态资源:内容经常更新的资源,例如百度首页、网易首页、京东搜索列表页等。
后记
以上就是htt模块的相关内容。欢迎关注!