HTTP协议

其它
2018年10月29日
828

HTTP协议(HyperText Transfer Protocol,超文本传输协议)是因特网上应用最为广泛的一种网络传输协议,所有的WWW文件都必须遵守这个标准。

HTTP是一个基于TCP/IP通信协议来传递数据(HTML文件、图片文件、查询结果等)。

HTTP工作原理

HTTP协议工作于客户端-服务端架构上。浏览器作为HTTP客户端通过URL向HTTP服务器即WEB服务器发送所有请求。

Web服务器根据接收到的请求后,向客户端发送响应信息。

HTTP默认的端口号为80,但你也可以改为8080或者其他端口。

HTTP注意事项:

  • HTTP是无连接:即限制每次连接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,就断开连接。采用这种方式可以节省传输时间。

  • HTTP是媒体独立的:这意味着,只要客户端和服务端知道如何处理的数据内容,任何类型的数据都可以通过HTTP发送。客户端以及服务器指定使用适合的MIME-type内容类型

  • HTTP是无状态的:HTTP协议是无状态协议。无状态指的是协议对于事务处理没有记忆能力。缺少状态意味着如果后续处理需要前面的信息,则必须重新传递,这样可能导致每次连接传送的数据量增大。另一方面,在服务器不需要前面的信息时它的应答就比较快。

HTTP协议的通信流程如下:

Web Browser <-(通过HTTP Protocol)-> HTTP Server <–> CGI Program <–> Database

HTTP消息结构

HTTP是基于客户端/服务端(C/S)的架构模型,通过一个可靠的链接来交换信息,是一个无状态的请求/响应协议。

一个HTTP“客户端”是一个应用程序(Web浏览器或其他任何客户端),通过连接到服务器达到向服务器发送一个或多个HTTP请求的目的。

一个HTTP“服务器”同样也是一个应用程序(通常是一个Web服务,比如Apache Web服务器或IIS服务器等),通过接收客户端的请求并向客户端发送HTTP响应数据。

HTTP使用统一资源标识符(Uniform Resource Identifiers,URI)来传输数据和建立连接。

一旦建立连接后,数据消息就通过类似Internet邮件的使用的格式[RFC5322]和多用途Internet邮件扩展(MIME)[RFC2045]来传送。

客户端请求消息

客户端发送一个HTTP请求到服务器的请求消息包括以下格式:请求行(request line)、请求头(header)、空行和请求数据四个部分组成.以下是请请求报文的一般格式:

http
请求方式 请求地址(URL) 协议版本 头部字段名:值 ... 头部字段名:值 请求数据

服务器响应消息

HTTP响应也由四个部分组成,分别是:状态行、消息报头、空行和响应正文。以下是响应报文的一般格式:

http
HTTP/1.1 200 OK Date: Sun, 28 Oct 2018 16:40:25 GMT Content-Length: 7724 Content-Type: image/jpeg // 响应正文

HTTP请求方法

根据HTTP标准,HTTP请求可以使用多种请求方法。

HTTP1.0定义了三种请求方法: GETPOSTHEAD方法。

HTTP1.1新增了5种请求方法:OPTIONSPUTDELETETRACECONNECT方法。

方法 描述
GET 请求指定的页面信息,并返回实体主体。
HEAD 类似于get请求,只不过返回的响应中没有具体的内容,用于获取报头
POST 向指定资源提交数据进行处理请求(比如提交表单或上传文件)。数据被包含在请求体中。POST请求可能会导致新的资源建立或已有资源的修改。
PUT 从客户端向服务器传送的数据取代指定的文档的内容。
DELETE 请求服务器删除指定的页面。
CONNECT HTTP/1.1协议中预留给能够将连接改为管道方式的代理服务器。
OPTIONS 允许客户端查看服务器的性能。
TRACE 回显服务器收到的请求,主要用于测试或诊断。

根据HTTP协议规范,GET用于信息获取,而且应该是安全的和幂等的。

  1. 所谓安全的,意味着该操作用于获取信息而非修改信息。换句话说,GET请求一般不应产生副作用。也就是说,它仅仅是获取资源信息,就像数据库查询一样,不会修改、增加数据,不会影响资源的状态。

    注意:这里的安全的含义仅仅指不会修改信息。

  2. 幂等的意味着对同一URL的多个请求应该返回相同的结果。

    幂等(idempotent/idempotence)是一个数学或计算机学概念,常见于抽象代数中。

    幂等有以下几种定于:

    • 对于单目运算,如果一个运算对于在范围内所有的一个数多次进行该运算所得的结果和进行一次运算所得的结果是一样的,那么我们就称该运算是幂等的。比如,绝对值运算就是幂等的,在实数集中abs(a) = abs(abs(a))

    • 对于双目运算,则要求参与运算的两个值是等值的情况下,如果满足运算结果与参与运算的两个值相等,则称该运算幂等。比如,求两个数的最大值函数max(x, x) = a

    但在实际应用中,以上2条规定并没有那么严格。比如,新闻站点的头版不断更新,虽然第二次请求会返回不同的信息,该操作仍被认为是安全的和幂等的,因为它总是返回当前的新闻。从根本上说,如果目标是当用户打开一个链接时,他可以确信从自身的角度来看有没有改变资源即可。

根据HTTP规范,POST表示可能修改服务器上的资源的请求。

还是以新闻网站为例,读者对新闻发表自己的评论应该通过POST实现,因为在评论提交后,站点的资源就已经不同了,或者说是资源被修改了。

上面大概说了一下HTTP规范中GET和POST的一些原理性问题,但在实际操作中,很多人却没有按照HTTP规范去做,导致这个问题的原因有很多,比如:

  • 很多人贪方便,更新资源时用了GET,因为POST必须要用到FORM(表单),这样会麻烦一点。

  • 对资源的增、删、查、改操作,其实都可以通过GET/POST来完成,不需要用到PUT和DELETE。

  • 还有就是,早期的Web MVC框架设计者们并没有意识地将URL当作抽象的资源来看待和设计,所以导致一个比较严重的问题是传统的Web MVC框架基本上都只支持GET和POST两种方法,而不支持PUT和DELETE方法。

以上3点典型地描述了老一套的风格(没有严格遵守HTTP规范),随着架构的发展,现在出现REST(Representional State Transfer),一套支持HTTP规范的新风格。可以参考《RESTfull Web Services》。

从表面现象上面看GET和POST的区别:

  1. GET请求的数据会附在URL之后(就是把数据放置在HTTP协议头中),以?分割URL和传输数据,参数之间以&相连。如果数据是英文或数字,则原样发送;如果是空格,则转换为+,如果是中文或其它字符,则把字符串用BASE64加密。而POST则是把提交的数据放置在HTTP包的包体中。

  2. GET方式提交的数据最多只能是1024字节,理论上POST是没有限制的,但是一些服务器比如IIS会作出限制。

  • 因为GET是通过URL提交数据,那么GET可提交的数据量就与URL长度有直接的关系。实际上,URL不存在参数上限的问题,HTTP协议规范没有对URL长度进行限制。这个限制是特写的浏览器及服务器对它的限制。注意这个限制是整个URL长度,而不仅仅是你的参数值数据的长度。

  • 理论上讲,POST是没有大小限制的,HTTP协议规范也没有进行大小限制,起限制作用的是服务器的处理程序的处理能力。

  1. 在PHPT中,用$_GET$_POST分别获取GET和POST数据,而$_REQUEST则可以获取GET和POST两种请求中的数据。

  2. POST的安全性要比GET高。注意:这里所说的安全性和上面GET提到的“安全”是两个不同的概念。这里的安全的含义是真正的Security的含义。比如:通过GET提交数据,用户名和密码将明文出现在URL中,因为登陆页面有可能被浏览器缓存,其他人查看浏览器的记录,就可以拿到你的账号和密码。除此之外,使用GET提交数据还可能会千万Cross-site request forgery攻击。

总结一下,GET是向服务器发索取数据的一种请求,而POST是向服务器提交数据的一种请求。在FORM表单中,Method默认为“GET”,实质上,GET和POST只是发送机制不同,并不是一个取一个发!

PUT:把消息本体中的消息发送到一个URL中,与POST类似,但不常用。

简单地说:通常是用于向服务器发送请求,如果URI不存在,则要求服务器根据请求创建资源,如果存在,服务器就接受请求内容,并修改URI资源的原始版本。

PUT请求的那些封装在Request-URI的实体。如果Request-URI引用一个已存在的资源,则该封装实体应该作为原始服务器上的修改版本。如果Request-URI不是指向一个已存在的资源,并且该URI可被请求的用户定义为资源,则原始服务器可用此URI创建新的资源。如果新的资源被创建,这个原始服务器就必须通过201(Created)响应通知用户代理。如果已有资源被修改,则发送200或者204响应,表示成功完成了该请求。如果Request-URI既没有创建也没有修改资源,则应该给予适当的错误响应来反映问题本质。实体的接受者不能忽略任何不理解或没有实现的Content-*头部(比如Content-Range),并且必须返回501响应

如果请求经过缓存,并且Request-URI标识出一个或多个当前缓存的实体,则那些实体视为过期了,该方法的响应不会被缓存。

POST和PUT的根本区别

POST请求的URI表示处理该封闭实体的资源,该资源可能是个数据接收过程、某种协议的网关、或者接收注解的独立实体。然而,PUT请求中的URI表示请求中封闭的实体-用户代理知道URI的目标,并且服务器无法将请求应用到其他资源。如果服务器希望请求应用到另一个URI,就必须发送一个304响应;用户代码可通过自己的判断来决定是否转为该请求。

HTTP/1.1没有定义一个PUT请求如何影响原始服务器的状态。

PUT请求必须遵守信息传输要求。除非另有说明,PUT请求中的实体头部应该用于PUT创建或修改的资源上。

其实,大部分情况下,我们都只用到了GET和POST。如果想设计一个符合RESTful规范的web应用程序,则这六种方法都会用到:

  1. GET:GET可以说是最常见的,它本质就是发送一个请求来获取服务器上的某一个资源。资源通过HTTP头和呈现数据(如HTML文本、图片、视频)返回给客户端。GET请求中,永远不会包含呈现数据。

  2. HEAD:HEAD和GET本质是一样的,区别在于HEAD响应不含有呈现数据,而仅仅上HTTP头信息。比如判断某个资源是否存在,使用HEAD的意义就很明确。

  3. PUT:这个方法比较少见。HTML表单也不支持这个方法。本质上讲,PUT和POST极为相似,都是向服务器发送数据,但它们之间有一个重要的区别是:PUT通过指定了资源存放的位置,而POST则没有,POST的数据存放位置由服务器自己决定。比如:一个用于提交博文的URL(/addBlog),如果用PUT,则提交的URL会像是这样的:/addBlog/adc123,其中abc123就是这个博文的地址。

  4. DELETE:删除某一个资源。基本上也很少见,不过有一些地方,比如amazon的S3云服务器里面就用这个方法来删除资源。

  5. POST:向服务器提交数据。这个方法用途广泛,几乎目前所有的提交操作都是靠这个完成。

  6. OPTIONS:这个方法很有趣,但是极少使用。它用于获取当前URL所支持的方法。若请求成功,则它会在HTTP头中包含一个名为“Allow”的头,值是所支持的方法,比如“GET”、“POST”。

HTTP响应头信息

响应头 说明
Allow 服务器支持哪些请求方法(如GET、POST等)。
Content-Encoding 文档的编码(Encode)方式。只有在解码之后才可以得到Content-Type头指定的内容类型。
Content-Length 内容长度。只有当浏览器使用持久HTTP连接时才需要这个数据。
Content-Type 表示后面的文档属于什么MIME类型。默认为text/plain,但通常需要显式地指定为text/html。
Date 当前的GMT时间。
Expires 应该在什么时候认为文档已经过期,从而不再缓存它?
Last-Modified 文档最后的改动时间。
Location 表示客户应该到哪里去提取文档
Refresh 表示浏览器应该在多少秒之后刷新文档。
Server 服务器名字
Set-Cookie 设置和页面关联的Cookie
WWW-Authenticate 客户应该在Authorization头中提供什么类型的授权信息?在包含401状态行的响应中这个头是必需的。

HTTP状态码

下面是常见的HTTP状态码:

  • 200 - 请求成功
  • 301 - 资源(网页等)被永久转移到其它URL
  • 404 - 请求的资源(网页等)不存在
  • 500 - 服务器内部错误

HTTP状态码分类

HTTP状态码由三个十进制的数字组成,第一个十进制数字定义了状态码的类型。

HTTP状态码共分为5种类型:

  • 1** 信息,服务器收到请求,需要请求者继续执行操作
  • 2** 成功,操作被成功接收并处理
  • 3** 重定向,需要进一步的操作以完成请求
  • 4** 客户端错误,请求包含的语法错误或无法完成请求
  • 5** 服务端错误,服务器在处理请求的过程中发生了错误

HTTP状态码列表:

状态码 英文名称 描述
100 Continue 继续。客户端应继续其请求
101 Switching Protocols 切换协议。服务器根据客户端的请求切换协议。只能切换到更高级的协议。
200 OK 请求成功。一般用于GET与POST请求
202 Created 已创建。成功请求并创建了新的资源
203 Accepted 已接受。已经接受请求,但未处理完成
204 Non-Authoritative Information 非授权信息。请求成功,但是返回的meta信息不在原始的服务器,而是一个副本
205 Reset Content 重置内容。服务器处理成功,用户终端(如:浏览器)应重置文档视图。可通过此返回码清除浏览器的表单域
206 Partial Content 部分内容。服务器成功处理了部分GET请求
300 Multiple Choices 多种选择。请求的资源可包括多个位置,相应可返回一个资源特征与地址的列表用于用户终端选择
301 Moved Permanently 永久移动。请求的资源已被永久移到新的URI,返回信息会包括新的URI,浏览器会自动定向到新的URI。今后任何新的请求都应使用新的URI代替
302 Found 临时移动。与301类似,但资源只是临时被移动。
303 See Other 查看其他地址。与301类似,使用GET和POST请求查看
304 Not Modified 未修改。所请求的资源未修改,服务器返回些状态码时,不会返回任何资源。客户端通常会缓存访问过的资源,通过提供一个头信息指出客户端希望只返回在指定日期之后修改的资源
305 Use Proxy 使用代码。所请求的资源必须通过代理访问
306 Unused 已废弃的状态码
307 Temporary Redirect 临时重定向。与302类似
400 Bad Request 客户端请求的语法错误,服务器无法理解
401 Unauthorized 请求要求用户的身份认证
402 Payment Required 保留,将来使用
403 Forbidden 服务器理解客户端的请求,但是拒绝执行此请求
404 Not Found 服务器无法根据客户端请求到资源
405 Method Not Allowed 客户端请求中的方法被禁止
406 Not Acceptable 服务器无法根据客户端请求的内容特性完成请求
407 Proxy Authentication Required 请求代码的身份认证,与401类似,但请求者应使用代理进行授权
408 Request Time-out 请求超时
409 Conflict 服务器完成客户端的PUT请求是可能返回此代码,服务器处理请求时发生了冲突
410 Gone 资源已经不存在。与404不同,如果资源以前有但现在被永久删除了可使用410
411 Length Required 服务器无法处理客户端发送的不带Content-Length的请求信息
412 Procondition Failed 客户端请求信息的先决条件错误
413 Request Entity Too Large 由于请求的实体过大,服务器无法处理,因此拒绝请求。
414 Request-URI Too Large 请求的URI过长(URI通常为网址),服务器无法处理
415 Unsupported Media Type 服务器无法处理请求附带的媒体格式
416 Requested range not satisfiable 客户端请求的范围无效
417 Expectation Failed 服务器无法满足Expect的请求头信息
500 Internal Server Error 服务器内部错误,无法完成请求
501 Not Implemented 服务器不支持请求的功能,无法完成请求
502 Bad Gateway 充当网关或代理的服务器,从远端服务器接收到了一个无效的请求
503 Service Unavailable 由于超载或系统维护,服务器暂时无法处理客户端的请求。
504 Gateway Time-out 充当网关或代理的服务器,未及时从远端服务器获取请求
505 HTTP Version not supported 不支持请求的HTTP协议版本,无法完成处理