接口请求格式详解
# 数据格式
一般我们会在HTTP请求中Content-Type(互联网媒体类型)里面看到,表示请求和响应中的媒体类型信息。它用来告诉服务端如何处理请求的数据,以及告诉客户端(一般是浏览器)如何解析响应的数据,比如显示图片,解析并展示html等等。
# application/x-www-form-urlencoded
数据被编码为key/value格式发送到服务器(表单默认的提交数据的格式)。
getTicketInfo: (params) => {
return api.get(`/blank/ite?cinemaId=${params}`).then(
(res) => {
return res;
},(error) => {
throw error;
}
);
}
2
3
4
5
6
7
8
9
可能我们传了参数
title=test&sub[]=1&sub[]=2&sub[]=3
到请求的时候会发现变成了
title=test&sub%5B%5D=1&sub%5B%5D=2&sub%5B%5D=3
这是因为当我们发送请求的时候会进行编码。
x-www-form-urlencoded的编码规则就是url编码规则,规则比较多;
# 几个比较常见的规则
1.字符"a"-"z","A"-"Z","0"-"9",".","-","*",和"_" 都不会被编码(中文会被编码);
2.将空格转换为加号 (+) ;
3.将非文本内容转换成"%xy"的形式,xy是两位16进制的数值;
4.在每个 name=value 对之间放置 & 符号。
在线编码解码:www.jsons.cn/urlencode/ (opens new window)
# application/json
现在越来越多的人把它作为请求头,用来告诉服务端消息主体是序列化后的 JSON 字符串。
由于 JSON 规范的流行,除了低版本 IE 之外的各大浏览器都原生支持 JSON.stringify,服务端语言也都有处理 JSON 的函数,使用 JSON 不会遇上什么麻烦。
我们传数据一般会这么写:
addOperator: (data) => {
return api.post(`/blcank/ite`, data).then(
(res) => {
if (res.status === 0) {
return res.data;
} else {
throw openNotification(res.status, res.msg);
}
},
(err) => {
throw err;
}
);
}
2
3
4
5
6
7
8
9
10
11
12
13
14
发送请求时会发现,参数会被直接放到请求实体里,没有进行任何处理:
application/json对比application/x-www-form-urlencoded来说,Json格式支持比键值对复杂得多的结构化数据,非常适合 RESTful 的接口。
# multipart/form-data
与application/x-www-form-urlencoded和application/json不同,这是一个多部分多媒体类型。
平常上传图片时经常会用到这种格式。
首先生成了一个 boundary 用于分割不同的字段,在请求实体里每个参数以------boundary开始,然后是附加信息和参数名,然后是空行,最后是参数内容。多个参数将会有多个boundary块。
可以上传键值对,也可以上传文件。当上传的字段是文件时,会有Content-Type来表名文件类型;content-disposition,用来说明字段的一些信息。
由于有boundary隔离,所以multipart/form-data既可以上传文件,也可以上传键值对,它采用了键值对的方式,所以可以上传多个文件。
可以把boundary理解为网格,数据装在格子中,有很多格子可以装载不同的数据。
# text/xml
这个数据格式比较麻烦,是一种使用HTTP作为传输协议,XML作为编码方式的远程调用规范。
它发送请求是这个样子的:
POST http://www.example.com HTTP/1.1
Content-Type: text/xml
<?xml version="1.0"?>
<methodCall>
<methodName>examples.getStateName</methodName>
<params>
<param>
<value><i4>41</i4></value>
</param>
</params>
</methodCall>
2
3
4
5
6
7
8
9
10
11
12
JavaScript 中,也有现成的库支持以这种方式进行数据交互,能很好的支持这个数据格式。但是 XML 结构还是过于臃肿,一般场景用 JSON 会更灵活方便。
# 请求方式
# GET
这是我们经常会用到的请求方式,根据 HTTP 规范,GET 用于信息获取,请求指定的资源。
而且应该是安全的和 幂等的。所谓安全的意味着该操作用于获取信息而非修改信息。换句话说,GET 请求一般不应产生副作用。幂等的意味着对同一 URL 的多个请求应该返回同样的结果。
还有一点,GET请求是可缓存的,当我们使用GET请求方法时,请求可能会被浏览器缓存。
当发送请求时,GET 方法向 URL 添加数据;URL 的长度是受限制的(URL 的最大长度是 2048 个字符),所以说GET方法不能传过长的数据。而且,GET方法发送的数据只允许 ASCII 字符。
我说ASCII字符你可能不太理解,简单来说,数字,大写字母,小写字母,符号,空格都属于ASCII字符,中文不是。但是为什么我们使用GET请求可以发送中文?
因为GET有自己的编码规则: 如果数据是英文字母/数字,原样发送,如果是空格,转换为+,如果是中文/其他字符,则直接把字符串用BASE64加密,得出如:
%E4%BD%A0%E5%A5%BD
其中%XX中的XX为该符号以16进制表示的ASCII。
# POST
POST和GET的区别
GET方法提交的url参数数据大小没有限制,在http协议中没有对url长度进行限制,这个限制是特定的浏览器及服务器对它的限制。
所以说,GET本身是没有数据长度限制的,是浏览器和服务器对它的限制。
# CONNECT
在 HTTP 协议中,CONNECT
方法可以开启一个客户端与所请求资源之间的双向沟通的通道。它可以用来创建隧道(tunnel)。
这个方法不是很常用,它主要是用来做什么的呢,很重要的功能之一,翻墙。
CONNECT将服务器作为代理,让服务器代替用户去访问其他网页,之后将数据返回给用户。
# DELETE
DELETE
请求方法用于删除指定的资源。
DELETE是一个很朴素的方法,没有请求正文,没有返回主体,也不会缓存,很单纯的告诉你我不需要她了,我要删了她,你只要告诉我删没删成功就行。
如果 DELETE
方法成功执行,那么可能会有以下几种状态码:
- 状态码
202
(opens new window) (Accepted
) 表示请求的操作可能会成功执行,但是尚未开始执行。 - 状态码
204
(opens new window) (No Content
) 表示操作已执行,但是无进一步的相关信息。 - 状态码
200
(opens new window) (OK
) 表示操作已执行,并且响应中提供了相关状态的描述信息。
# HEAD
HEAD
请求资源的头部信息, 并且这些头部与 GET
(opens new window) 方法请求时返回的一致。该请求方法的一个使用场景是在下载一个大文件前先获取其大小再决定是否要下载,,以此可以节约带宽资源。
简单的来说,HEAD与GET方法使用起来差不多,可以理解为nimi GET。当我们想要获取这个数据的信息比如它是否存在而不需要获取数据时就可以用到它。
# OPTIONS
OPTIONS
用于获取目的资源所支持的通信选项。客户端可以对特定的 URL 使用 OPTIONS 方法,也可以对整站(通过将 URL 设置为“*”)使用该方法。
估计你没听明白它是做什么的。这个方法很有趣,它用于获取当前URL所支持的方法。若请求成功,则它会在HTTP头中包含一个名为“Allow”的头,值是所支持的方法,如“GET, POST”。
它有一个很大的用处:CORS 中的预检请求。
在 CORS (opens new window) 中,可以使用 OPTIONS 方法发起一个预检请求,以检测实际请求是否可以被服务器所接受。预检请求报文中的 Access-Control-Request-Method
(opens new window) 首部字段告知服务器实际请求所使用的 HTTP 方法;Access-Control-Request-Headers
(opens new window) 首部字段告知服务器实际请求所携带的自定义首部字段。服务器基于从预检请求获得的信息来判断,是否接受接下来的实际请求。
# PUT
PUT 请求方法使用请求中的负载创建或者替换目标资源。
简单的来说,PUT用于向服务器发送请求,如果URI不存在,则要求服务器根据请求创建资源,如果存在,服务器就接受请求内容,并修改URI资源的原始版本。
在我们平常开发的时候也会用到PUT,使用起来和POST差不多,都是向服务器发送数据,但它们之间有一个重要区别,PUT通常指定了资源的存放位置,而POST则没有,POST的数据存放位置由服务器自己决定。
# PATCH
PATCH 用于对资源进行部分修改。
PATCH方法和PUT方法所请求的目标地址都是直接指向资源的。
PUT
(opens new window) 方法已经被用来表示对资源进行整体覆盖, 而 POST
(opens new window) 方法则没有对标准的补丁格式的提供支持。不同于 PUT
方法,而与 POST
方法类似,PATCH
方法是非幂等的,这就意味着连续多个的相同请求会产生不同的效果。
PATCH提供的实体则需要根据程序或其它协议的定义,解析后在服务器上执行,以此来修改服务器上的数据。
# TRACE
TRACE
实现沿通向目标资源的路径的消息环回(loop-back)测试 ,提供了一种实用的 debug 机制
我的理解就是一种协议调试方法。
# 响应报文
详见http协议相关
客户端向服务端发送请求之后,服务器接收并处理客户端发过来的请求后正常情况下会返回一个HTTP的响应消息,这个就是响应报文。
# 组成
HTTP响应由四个部分组成,分别是:状态行、消息报头、空行和响应正文。
# 响应头
响应头由键值对组成,每行一对,键和值用英文冒号 : 分隔。响应头域允许服务器传递不能放在状态行的附加信息,这些域主要描述服务器的信息和Request-URI进一步的信息。
这个也是我想说的报文中的重点,可以给我们带来很多信息的地方。
列出一些比较常见的响应头:
响应头
说明
Allow
服务器支持哪些请求方法(如GET、POST等)。
Content-Encoding
文档的编码(Encode)方法。只有在解码之后才可以得到Content-Type头指定的内容类型。利用gzip压缩文档能够显著地减少HTML文档的下载时间。Java的GZIPOutputStream可以很方便地进行gzip压缩,但只有Unix上的Netscape和Windows上的IE 4、IE 5才支持它。因此,Servlet应该通过查看Accept-Encoding头(即request.getHeader("Accept-Encoding"))检查浏览器是否支持gzip,为支持gzip的浏览器返回经gzip压缩的HTML页面,为其他浏览器返回普通页面。
Content-Length
表示内容长度。只有当浏览器使用持久HTTP连接时才需要这个数据。如果你想要利用持久连接的优势,可以把输出文档写入 ByteArrayOutputStream,完成后查看其大小,然后把该值放入Content-Length头,最后通过byteArrayStream.writeTo(response.getOutputStream()发送内容。
Content-Type
表示后面的文档属于什么MIME类型。Servlet默认为text/plain,但通常需要显式地指定为text/html。由于经常要设置Content-Type,因此HttpServletResponse提供了一个专用的方法setContentType。
Date
当前的GMT时间。你可以用setDateHeader来设置这个头以避免转换时间格式的麻烦。
Expires
应该在什么时候认为文档已经过期,从而不再缓存它?
Last-Modified
文档的最后改动时间。客户可以通过If-Modified-Since请求头提供一个日期,该请求将被视为一个条件GET,只有改动时间迟于指定时间的文档才会返回,否则返回一个304(Not Modified)状态。Last-Modified也可用setDateHeader方法来设置。
Location
表示客户应当到哪里去提取文档。Location通常不是直接设置的,而是通过HttpServletResponse的sendRedirect方法,该方法同时设置状态代码为302。
Refresh
表示浏览器应该在多少时间之后刷新文档,以秒计。除了刷新当前文档之外,你还可以通过setHeader("Refresh", "5; URL=http://host/path")让浏览器读取指定的页面。 注意这种功能通常是通过设置HTML页面HEAD区的<META HTTP-EQUIV="Refresh" CONTENT="5;URL=http://host/path">实现,这是因为,自动刷新或重定向对于那些不能使用CGI或Servlet的HTML编写者十分重要。但是,对于Servlet来说,直接设置Refresh头更加方便。
注意Refresh的意义是"N秒之后刷新本页面或访问指定页面",而不是"每隔N秒刷新本页面或访问指定页面"。因此,连续刷新要求每次都发送一个Refresh头,而发送204状态代码则可以阻止浏览器继续刷新,不管是使用Refresh头还是<META HTTP-EQUIV="Refresh" ...>。
注意Refresh头不属于HTTP 1.1正式规范的一部分,而是一个扩展,但Netscape和IE都支持它。
Server
服务器名字。Servlet一般不设置这个值,而是由Web服务器自己设置。
Set-Cookie
设置和页面关联的Cookie。Servlet不应使用response.setHeader("Set-Cookie", ...),而是应使用HttpServletResponse提供的专用方法addCookie。参见下文有关Cookie设置的讨论。
WWW-Authenticate
客户应该在Authorization头中提供什么类型的授权信息?在包含401(Unauthorized)状态行的应答中这个头是必需的。例如,response.setHeader("WWW-Authenticate", "BASIC realm=\"executives\"")。 注意Servlet一般不进行这方面的处理,而是让Web服务器的专门机制来控制受密码保护页面的访问(例如.htaccess)。
# 参考链接
https://juejin.cn/post/6917143120048029704