HTTP是一个无状态的请求、响应协议,通过一个可靠的传输连接来交换信息。一个Http客户端是一个用来和服务端进行连接的程序,主要是用来发送一个或多个http请求;服务端是用来接受请求连接,响应请求并返回结果
URI 统一资源定位符
URI(Uniform Resource Identifier)统一资源定位符,在http里面用来识别资源,对应的标准文件是[RFC3986]
通用的URI格式定义如下
URI = scheme ":" hier-part [ "?" query ] [ "#" fragment ]
hier-part = "//" authority path-abempty
/ path-absolute
/ path-rootless
/ path-empty
其中scheme和path是必须的,尽管path可能为空。当authority存在时,path必须为空或者以/开头。当authority不存在时,path不能为//开关
- scheme 协议名,表示资源应该使用哪种协议来访问
scheme = ALPHA *( ALPHA / DIGIT / “+” / “-” / “.” )
- authority 表示资源所在的主机名
authority = [ userinfo “@” ] host [ “:” port ]
- path 标记资源所在的位置,URI的path部分必须以/开始
path = path-abempty ; begins with "/" or is empty / path-absolute ; begins with "/" but not "//" / path-noscheme ; begins with a non-colon segment / path-rootless ; begins with a segment / path-empty ; zero characters
- query 表示对资源的附件额外的要求,在path之后,用一个?开始,但不包括?,通常是由多个key-value组成的字符串,KV值之间用&连接
query = *( pchar / “/” / “?” )
- fragment 在query后面,以#开头,片段标识符,是Uri所定位的资源内部的一个锚点或标签,浏览器会根据这个跳转到指示的位置
fragment = *( pchar / “/” / “?” )
下面是一个具体的实例
foo://example.com:8042/over/there?name=ferret#nose
\_/ \______________/\_________/ \_________/ \__/
| | | | |
scheme authority path query fragment
| _____________________|__
/ \ / \
urn:example:animal:ferret:nose
Message Format 消息格式
所有HTTP/1.1 消息由一个起始行+0或多个head字段+空行+可选的消息body
- start line 起始行,描述请求或响应的基本信息
- headers 头部字段,使用key-value的形式来描述消息
- body 消息正文,实际传输的数据
HTTP 消息格式如下
HTTP-message = start-line
*( header-field CRLF )
CRLF
[ message-body ]
start line 起始行
起始行分2类:请求行和状态行
request-line 请求行
一个请求行由3部分组成
- method 请求方法,表示对资源的操作,如GET/POST
- request-target 请求目标,通常是一个Uri,标记请求方法要操作的资源
- HTTP-version 表示使用的http协议版本号
这3个部分使用空格(space)来,最后用CRLF换行表示结束。
格式如下:
request-line = method SP request-target SP HTTP-version CRLF
示例:
status-line 状态行
一个状态行(表示服务器响应ruddy)由3部分组成
- HTTP-version 表示使用的http协议版本号
- status-code 状态码,一个三位数,表示处理的结果
- reason-phrase 原因,作为数字状态码的补充,是更详细的解释
和请求行类似,这3个部分使用空格(space)来,最后用CRLF换行表示结束。
格式如下:
status-line = HTTP-version SP status-code SP reason-phrase CRLF
其中状态值由3位数字组成
status-code = 3DIGIT
Header Fields 头字段
头部字段是key-value的形式,Key和value之间用:分隔,最后用CRLF换行表示结束,不区分大小写
头字段非常灵活,除了可以使用标准的host/connection等字段,也可以任意添加自定义头,给http协议提供了扩展可能
字段的顺序是没有意义的,可以任意排列,不影响语义
在一个HTTP/1.1请求中,请求头里面必须包含有host字段,如果没有,就是一个错误的消息。 A client MUST send a Host header field in all HTTP/1.1 request
messages
常见的请求头和响应头如下
Message Body 消息体
消息体是可选的,从前面的定义可以知道,head之后,有一个空行,再然后才是消息body
- Content-Length 表示消息body的长度,在head后面空行之后的数据长度
- Transfer-Encoding 文件传输编码