http的Content-Type字段笔记
HTTP/1.1协议规定的HTTP请求方法有OPTIONS、GET、HEAD、POST、PUT、DELETE、TRACE、CONNECT这几种, 用的最多的是GET和POST, 这里主要说一下提交请求时的请求头中Content-Type字段
# http请求结构
http请求分为三个部分: 状态行, 请求头和消息主体, 结构如下:
<method> <request url> <version>
<headers>
<entity-body>
# Content-Type类型
Content-Type有如下常见的类型:
text/plain: 文本类型text/html: html文件类型text/css: css文件类型text/javascript: javascript文件类型application/x-www-form-urlencodedPOST讨论multipart/form-dataPOST讨论application/jsonPOST讨论text/xmlPOST中讨论
由于GET方式的数据实际上是以QueryString的方式放在<request url>中的(非ASCII字符会被转码), 例如'https://www.example.com?key1=value1&key2=value2', 所以对GET讨论Content-Type没有意义
http协议规定POST提交的数据必须放在消息主体(entity-body)中,但协议并没有规定数据必须使用什么编码方式。实际上,开发者完全可以自己决定消息主体的格式,只要最后发送的HTTP请求满足上面的格式就可以。
服务端通常是根据请求头(headers)中的Content-Type字段来获知请求中的消息主体是用何种方式编码,再对主体进行解析。所以有必要了解Content-Type的内容. 目前在POST请求中所使用的Content-Type主要有如下四种类型: application/x-www-urlencoded, multipart/form-data, application/json, text/xml, 下面详细说一下这四种类型.
# application/x-www-urlencoded
这应该是最常见的POST提交数据的方式了。浏览器的原生<form>表单,如果不设置enctype属性,那么默认就会以这种方式提交数据。这种方式会将表单中的数据按照key1=value1&key2=value2的形式连接成字符串, 同时会将出现的非ASCII字符进行编码, 编码方式可以参考encodeURIComponent()函数, 例如下面这个表单提交时的数据结构:
POST http://www.example.com HTTP/1.1
Content-Type: application/x-www-form-urlencoded;charset=utf-8
title=test&sub%5B%5D=1&sub%5B%5D=2&sub%5B%5D=3
但是需要注意的是这是在<form>表单中没有type=file形内容的时候的提交方式, 如果表单中有二进制内容需要提交, 比如文件或者图片等, 那么就无法使用application/x-www-urlencoded方式, 需要转而使用下面会谈到的multipart/form-data方式.
# multipart/form-data
当需要提交二进制数据如文件或者图片时就需要使用这种multipart/form-data, 一个常见的提交内容结构如下:
POST http://www.example.com HTTP/1.1
Content-Type:multipart/form-data; boundary=----WebKitFormBoundaryrGKCBY7qhFd3TrwA
------WebKitFormBoundaryrGKCBY7qhFd3TrwA
Content-Disposition: form-data; name="text"
title
------WebKitFormBoundaryrGKCBY7qhFd3TrwA
Content-Disposition: form-data; name="file"; filename="chrome.png"
Content-Type: image/png
PNG ... content of chrome.png ...
------WebKitFormBoundaryrGKCBY7qhFd3TrwA--
请求头中的boundary代表将使用后面这一长串的字符串来分隔不同的字段, 消息主体里按照字段个数又分为多个结构类似的部分,每部分都是以--boundary开始,紧接着是内容描述信息,然后是回车,最后是字段具体内容(文本或二进制)。如果传输的是文件,还要包含文件名和文件类型信息。消息主体最后以--boundary--标示结束, 关于multipart/form-data的详细定义,请前往rfc1867查看。
application/x-www-urlencoded和multipart/form-data都是浏览器原生支持的,而且现阶段标准中原生<form>表单也只支持这两种方式(通过<form>元素的enctype属性指定,默认为 application/x-www-form-urlencoded。其实enctype还支持text/plain,不过用得非常少)。
下面提到的Content-Type属于随着技术的发展, 我们自定义出来的新的数据提交方式, 更为便捷.
# application/json
因为json格式数据的读写性非常好, 用的也极为广泛, 所以application/json这个请求头也用的越来越多, 这个请求头就是告诉服务器发送的数据是序列化后的json字符串, 现在在做的Vue项目中用到的Axios所使用的默认就是application/json, 这里有一个问题就是Axios全局设置Content-Type为application/x-www-urlencoded不生效, 需要在请求发出前拦截方法中修改配置才能生效, 不知道是不是bug, 如下:
function _interceptorRequest(config) {
config.headers['Content-Type'] = 'application/x-www-form-urlencoded; charset=utf-8';
return config
}
使用application/json方式发送的数据结构类似下面这个:
POST http://www.example.com HTTP/1.1
Content-Type: application/json;charset=utf-8
{"title":"test","sub":[1,2,3]}
json格式可以提交结构复杂的数据,在抓包工具或者调试中查看起来也很方便, 尤其适合RESEful的接口, 需要注意的是不论我们使用application/x-www-urlencoded还是application/json都要注意和服务器相配合, 因为毕竟我们发送的数据是希望服务器来正确接收和处理的, 如果客户端设置的Content-Type与服务端期望接收的Content-Type不一致就很有可能导致服务器无妨正常处理这个请求.
# text/xml
这是一种使用HTTP作为传输协议,XML作为编码方式的远程调用规范, 典型的XML-RPC请求如下:
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>
XML-RPC协议简单、功能够用,各种语言的实现都有。它的使用也很广泛,如WordPress的XML-RPCApi,搜索引擎的ping服务等等。JavaScript中,也有现成的库支持以这种方式进行数据交互,能很好的支持已有的 XML-RPC服务。