开始之前先抛出一个疑问
1.GET、POST、DELETE、PUT这些http请求方法之间有什么区别。为什么会有区别
准备的工具
1.Visual Studio code 编辑器
2.Visual Studio code的插件:rest Client
3.node服务器
//运行之前先安装下面这些依赖
npm install koa @koa/router koa-body @koa/cors koa-static
//使用koa构建了一个测试服务器。
const Koa = require('koa');
const Router = require('@koa/router');
const cors = require('@koa/cors');
const static = require('koa-static'); // 新增静态资源中间件
const path = require('path');
const { koaBody } = require('koa-body')
const app = new Koa();
const router = new Router();
// 新增配置:托管静态资源目录
app.use(static(path.join(__dirname, 'public')));
// 中间件配置
app.use(cors());
app.use(koaBody({
jsonLimit: '1mb',
multipart: true, // 启用文件上传支持
formidable: {
uploadDir: path.join(__dirname, 'public/uploads'), // 上传目录
keepExtensions: true, // 保留文件扩展名
maxFileSize: 10 * 1024 * 1024, // 最大文件大小10MB
onFileBegin: (name, file) => {
// 文件名规范化(防止中文乱码)
file.newFilename = `${Date.now()}-${file.originalFilename}`;
file.filepath = path.join(__dirname, 'public/uploads', file.newFilename);
}
},
parsedMethods: ['POST', 'PUT', 'PATCH', 'GET']
}));
// RESTful 路由
router.get('/users', (ctx) => {
const { name, age } = ctx.request.query;
ctx.body = {
name,
age
}
});
router.post('/users', async (ctx) => {
const { name, age } = ctx.request.query;
ctx.body = {
name,
age
}
});
router.get('/info', (ctx) => {
const { name, age } = ctx.request.body;
ctx.body = {
name,
age,
url: ctx.request.url,
method: ctx.request.method,
ContentType: ctx.request.headers['content-type'],
}
});
router.post('/info', async (ctx) => {
const { name, age } = ctx.request.body;
ctx.body = {
name,
age,
url: ctx.request.url,
method: ctx.request.method,
ContentType: ctx.request.headers['content-type'],
}
});
//post文件上传
router.post('/upload', async (ctx) => {
const files = ctx.request.files; // 接收的所有文件
const { name, age } = ctx.request.body;
const uploadedUrls = [];
// 多文件遍历处理
for (const fieldName in files) {
const fileArr = Array.isArray(files[fieldName]) ?
files[fieldName] :
[files[fieldName]];
fileArr.forEach(file => {
uploadedUrls.push(`${ctx.origin}/uploads/${file.newFilename}`);
});
}
ctx.body = {
name,
age,
method: ctx.request.method,
ContentType: ctx.request.headers['content-type'],
urls: uploadedUrls[0]
};
});
router.get('/upload', async (ctx) => {
const files = ctx.request.files; // 接收的所有文件
const { name, age } = ctx.request.body;
const uploadedUrls = [];
// 多文件遍历处理
for (const fieldName in files) {
const fileArr = Array.isArray(files[fieldName]) ?
files[fieldName] :
[files[fieldName]];
fileArr.forEach(file => {
uploadedUrls.push(`${ctx.origin}/uploads/${file.newFilename}`);
});
}
ctx.body = {
name,
age,
method: ctx.request.method,
ContentType: ctx.request.headers['content-type'],
urls: uploadedUrls[0]
};
});
// 注册路由
app.use(router.routes());
app.use(router.allowedMethods());
// 启动服务
const PORT = 3000;
app.listen(PORT, () => {
console.log(`Koa server running on http://localhost:${PORT}`);
});
工程目录
传递消息的模式
HTTP使用了一种极为简单的消息传递模式【请求-响应】模式
发起请求的称之为客户端,接收请求并完成响应的称之为服务器
【请求-响应】完成后,一次交互结束
传递消息的格式
HTTP的消息各分是一种纯文本的格式,文本分为三部分
1 起始行(请求行、响应行)
2 头部字段(请求体、响应体)
3
4 消息体(请求体、响应体)
注意:HTTP协议的规范。根据RFC 7230,HTTP消息的结构是起始行、头部字段、空行,然后是消息体,每一部分最后结尾都要换行。在window中,换行符为/r/n。mac系统中,换行符为/n
请求端
1.安装rest client插件后
2.启动服务器
3.创建一个 http后缀的文件,例如:test.http
理解(很重要):
第一行:请求行
第一个属性:请求方法--->GET
第二个属性:请求路径---> /user
第三个属性:请求协议和版本号---> HTTP/1.1
第二行:请求头(这里可以写很多参数,例如Host、content-type等等。一个属性一行)
Host属性:代表连接的源,域名和ip都可以---> localhost:3000
Content-Type属性:代表传输过去的数据格式---> application/json
最后就是请求体,注意:请求头和请求体中间一定要空一行(两个换行符)在这个插件中,我们不需要手动编写换行符,只需要按键盘的Enter键,换行即可。
path传输
在HTTP协议中,请求方法仅有语义的区别,只是表达了这次请求的[愿望]。例如GET请求所完成的所有事情,POST请求也能完成,POST请求能完成的,GET请求也能完成。
例如:我使用GET和POST请求,通过path传输数据
左边是客户端
右边是服务端
中间是响应的结果
1. GET请求 通过path传输name和age
2. POST请求 通过path传输name和age
application/json传输
如果有请求体,必须配置相应的请求的方法,才能解析请求体的参数,以下是koa-body中间件的配置
同理,GET请求也可以通过请求体传输数据
1. GET请求 发送json格式数据
2. POST请求 发送json格式数据
注意:浏览器中无法使用GET请求携带请求体发送请求,浏览做了限制。通过apifox也可以进行模拟。
application/x-www-form-urlencoded格式传输
1. GET请求:发送 application/x-www-form-urlencoded 格式数据
2.POST请求:发送 application/x-www-form-urlencoded 格式数据
文件传输multipart/form-data
multipart/form-data 格式主要用于文件传输(推荐)
1. POST请求:传输文件
2. GET请求:传输文件
拓展:其实application/json和application/x-www-form-urlencoded两种格式也可以进行文件传输。不过需要把文件的二进制数据转换成base64,然后传输base64。因为在本地把文件二进制数据转换成base64会非常耗时,而且转换之后的数据量会大于原始二进制的数据量,网络通信的数据会变多,更加消耗带宽(不推荐)。
图解:左边为json格式,右边为x-www-form-urlencoded格式
响应端
第一行第一个属性表示协议和版本:HTTP的协议,版本是1.1
第一行第二个和第三个属性表示响应码和响应消息,常见的有:
| 分类 | 分类描述 |
|---|---|
| 1** | 信息,服务器收到请求,需要请求者继续执行操作 |
| 2** | 成功,操作被成功接收并处理 |
| 3** | 重定向,需要进一步的操作以完成请求 |
| 4** | 客户端错误,请求包含语法错误或无法完成请求 |
| 5** | 服务器错误,服务器在处理请求的过程中发生了错误 |
| 状态码 | 推荐消息 | 说明 |
|---|---|---|
| 200 | OK | 标准成功响应 |
| 301 | Moved Permanently | 永久重定向 |
| 201 | Created | 资源创建成功 |
| 404 | Not Found | 资源未找到 |
| 500 | Internal Error | 服务器内部错误 |
从空行到响应行之间的全部都是响应头。空行后面的全部都是响应体
最后总结
所有HTTP请求方法(GET/POST/PUT等)在传输过程中均被规范为统一报文结构:由请求行、报文头、空行、载荷体四部分构成的文本流。请求端将结构化数据(如JSON对象)通过序列化转换为字符串,并按协议规范拼接元数据:请求行声明方法与目标资源,报文头设定编码类型与内容长度,空行作为分隔符,最终以UTF-8编码的二进制字节流通过TCP连接传输。这个过程实质上是将高级数据形态降维到文本协议的平面表达。
通俗一点:无论上层写的是啥,最终都会转成字符串(文本),使用流的形式进行传输。
GET、POST、DELETE、PUT这些http请求方法之间有什么区别。为什么会有区别。
解析:这个问题需要从不同的层面去分析。在http层面其实区别不大,区别逐渐增大是由上层服务自行实现的,比如一些框架呀,一些请求库呀。如果自己开发一个客户端和一个服务端,get和post完全可以相互换着用。只要客户端可以发送,服务端认,完全是ok的。
答案从前端角度出发,从两个层面进行解答:
从http层面去看:
所有的请求方式除去语义的区别,没有任何区别。比如GET用于获取资源,POST用于提交数据等,但技术上这些方法本身并没有限制,服务器可以自由处理。比如,用GET提交数据或者用DELETE创建资源都是可能的,不过这不推荐,因为违背了RESTful的设计原则。
从浏览器层面去看:区别就更细化了,例如:
1.get请求可以直接输入在浏览器进行获取数据,post不行。
2.get请求可以收藏为书签,会有历史记录,post不行。
3.get请求不能携带请求体,post可以。
4.相对而言,post请求比get请求安全。
5.页面刷新get请求会直接重新请求,post会提示重新提交表单
6.get有长度限制,post没有
还有很多就不一一列举了哈哈哈哈。谈到浏览器层面,好像八股文啊。。。。。。