让你轻松了解什么是HTTP协议,什么是URI

1.Http简介

HTTP是一种无状态、由文本构成的请求-响应(request-response)协议,这种协议使用的是客户端-服务器(client-server)计算模型。
请求-响应是两台计算机进行通信的基本方式,其中一台计算机会向另一台计算机发送请求,而接收到请求的计算机则会对请求进行响应。在客户端-服务端计算模型中,发送请求的一方(客户端)负责向返回响应的一方(服务器)发起会话,而服务端则负责为客户提供服务。在HTTP协议中,客户端也被称为用户代理(user-agent),而服务器则通常会被称为Web服务器。
HTTP是以纯文本方式而不是二进制方式发送和接收协议数据的。

2. CGI

CGI(Common Gateway Interface)通用网关接口。简单理解,可以认为CGI是Web服务器和一个独立的进程之间的协议,它会把HTTP请求Request的Header头设置成进程的环境变量,HTTP请求的Body正文设置成进程的标准输入,进程的标准输出设置为HTTP响应Response,包含Header头和Body正文。

3. HTTP请求

HTTP是一种请求-响应协议,协议涉及的所有事情都以一个请求开始。HTTP请求跟其他所有HTTP保温(message)一样,都由一系列文本行组成,这些文本行会按照以下顺序进行排列:
(1)请求行(request-line);
(2)零个或任意多个请求首部(header);
(3)一个空行;
(4)可选的报文主体(body)。
如下图:
在这里插入图片描述
请求行的第一个单词为请求方法,之后跟着的是统一资源标识符(Uniform Resource Identifier, URI)以及所使用的HTTP版本。位于请求行之后的两个文本行为请求的首部。

3.1 请求方法

请求方法是请求行中的第一个单词,他指明了客户端想要对资源执行的操作。HTTP0.9只有GET一个方法,HTTP1.0添加了POST方法和HEAD方法,而HTTP1.1则添加了PUT、DELETE、OPTIONS、TRACE和CONNECT这五个方法,并允许开发者自行添加更多方法。
各个HTTP方法的作用说明如下:

  • GET 命令服务器返回指定的资源
  • HEAD 与GET方法的作用类似,唯一的不同在于这个方法不要求服务器返回报文的主体。这个方法通常用于在不获取报文主体的情况下,取得响应的首部。
  • POST 命令服务器将报文主体中的数据传递给URI指定的资源,至于服务器具体会对这些数据执行什么动作则取决于服务器本身。
  • PUT 命令服务器将报文主题中的数据设置为URI指定的资源。如果URI指定的位置上已经有数据存在,那么使用报文主体中的数据去代替已有的数据。如果资源尚未存在,那么URI指定的位置上新创建一个资源。
  • DELETE 命令服务器删除URI指定的资源
  • TRACE 命令服务器返回请求本身。通过这个方法,客户端可以知道介于他和服务器之间的其他服务器是如何处理请求的。
  • OPTIONS 命令服务器返回它支持的HTTP方法列表。
  • CONNECT 命令服务器与客户端建立一个网络连接。这个方法通常用于设置SSL隧道以开启HTTPS功能。
  • PATCH 命令服务器使用报文主体中的数据对URI指定的资源进行修改。
3.2 安全的请求方法

如果一个HTTP方法只要求服务器提供信息而不会对服务器的状态做任何修改,那么这个方法就是安全的(safe)。GET、HEAD、OPTIONS和TRACE都不会对服务器的状态进行修改,所以他们都是安全的方法。

3.3 幂等的请求方法

如果一个HTTP方法在使用相同的数据进行第二次调用的时候,不会对服务器的状态造成任何改变,那么设个方法就是幂等的。根据安全的方法的定义,因为多有安全的方法都不会修改服务器状态,所以他们天生就是幂等的。

PUT和DELETE虽然不安全,但却是幂等的,因为他们在进行第二次调用的时候都不会改变服务器的状态:因为服务器在执行第一个PUT请求之后URI指定的资源已经更新或者创建出来了,所以针对同一个资源的第二次PUT请求只会执行服务器已经执行过的动作;与此类似,虽然服务器对于同一个资源的第二次PUT请求只会执行服务器已经执行过的动作;与此类似,虽然服务器对于同一个资源的第二次DELETE请求肯能会返回一个错误,但这个请求并不会改变服务器的状态。

3.4 浏览器对请求方法的支持

GET方法是最基本的HTTP方法,它负责从服务器上获取内容,所有浏览器都支持这个方法。POST方法从HTML2.0开始可以通过添加HTML表单来实现:HTML的form标签有一个名为method的属性,用户通过将这个属性的值设置为get或者post来指定要使用那个方法。HTML不支持除GET和POST之外的其他HTTP方法。

但是,现在流行的浏览器通常都不会只支持HTML一种数据格式——用户可以使用XMLHttpRequest(XHR)来或得对PUT方法和DELETE方法的支持。XHR是一系列浏览器API,这些API通常由JavaScript包裹(实际上XHR就是一个名为XMLHttpRequest的浏览器对象)。XML允许程序员向服务器发送HTTP请求,并且跟“XMLHttpRequest”这个名字所暗示的不一样,这项技术并不仅仅局限于XML格式——包括JSON以及纯文本在内的任何格式的请求和响应都可以通过XHR发送。

3.5 请求首部

HTTP请求方法定义了发送请求的客户端想要执行的动作,而HTTP请求的首部则记录了与请求本身及客户端有关的信息。请求的首部由热议多个冒号隔开的纯文本键值对组成,最后以回车(CR)和换行(LF)结尾。
常见的请求首部:

首部字段 作用描述
Accept 客户端在HTTP响应中能够接收的内容类型。比如说,客户端可以通过Accept:text/html这个首部,告知服务器自己希望在响应的主体中收到HTML类型的内容
Accept-Charset 客户端要求服务器使用的字符集编码。比如客户端可以通过Accept-Charset:uft-8这个首部,告知服务器自己希望响应的主体使用UTF-8字符集。
Authorization 这个首部用于向服务器发送基本的身份验证证书
Cookie 客户端应该在这个首部中把服务器之前设置的所有cookie回传给服务器。比如说,如果服务器之前在浏览器上设置了3个cookie,那么Cookie首部字段将在一个字符串里面包含这三个cookie,并使用分号对这些cookie进行分割。以下是一个Cookie首部示例:Cookie: my_first_cookie=hello; my_second_cookie=world
Content-Length 请求主体的字节长度
Content-Type 当请求包含主体的时候,这个首部用于记录主体内容的类型。在发送POST或PUT请求时,内容的类型默认为x-www-form-urlen-coded,但是在上传文件时,内容的类型应该设置为multipart/form-data(上传文件这一操作可以通过将input标签的类型设置为file来实现)
Host 服务器的名字以及端口号。如果这个首部没有记录服务器的端口号,就表示服务器使用的是80端口。
Referrer 发送请求的页面所在的地址
User-Agent 对发起的客户端进行描述

4. HTTP响应

HTTP响应报文是对HTTP请求报文的回复。跟HTTP请求一样,HTTP响应也由一系列文本行组成,其中包括:

  • 一个状态行;
  • 零个或任意数量的响应首部,
  • 一个空行;
  • 一个可选的报文主体。
    如下图:
    在这里插入图片描述
    HTTP响应的第一行为状态行,这个文本行包括了状态码( status code )和相应的原因短语( reason phrase ),原因短语对状态码进行了简单的描述。除此之外,这个例子中的HTTP响应还包含了一个HTML格式的报文主体。
4.1 响应状态码:

HTTP响应状态码总共有5种类型,他么分别以不同的数字作为前缀,如下表:

状态码类型 作用描述
1XX 情报状态码。服务器通过这些状态码来告知客户端,自己已经接收到了客户端发送的请求,并且已经对请求进行了处理。
2XX 成功状态码。这些状态码说明服务器已经接收到了客户端发送的请求,并且已经成功的对请求进行了处理。这类状态码的标准响应为“200 OK”
3XX 重定向状态码。这些状态码表示服务器已经接收到了客户端发送的请求,并且已经处理了请求,但是为了完成指定的动作,客户端还需要在做一切其他的 工作。这类状态码大多用于实现URL重定向。
4XX 客户端错误状态码。这类状态码说明客户端发送的请求出现了某些问题。在这一类型的状态码种,最常见的就是“404 Not Found”,这个状态码表示服务器无法从请求的URL中找到客户端想要的资源。
5XX 服务器错误状态码。当服务器因为某些原因而无法正确的处理请求时,服务器就会使用这类状态码来通知客户端。这一类状态码中,最常见的就是”500 Internal Server Error“状态码。
4.2 响应首部

响应首部跟请求首部一样,都是由冒号分隔的纯文本键值对组成,并且同样以(CR)和换行符(LF)结尾。下表为常见的响应首部:

首部字段 作用描述
Allow 告知客户端,服务器支持那些请求方法
Content-Length 响应主体的字节长度
Content-Type 如果响应包含可选的主体,那么这个首部记录的就是主体内容的类型
Date 以格林尼治标准时间(GMT)格式记录的当前事件
Location 这个首部仅在重定向时使用,他会告知客户端接下来应该向那个URL发送请求
Server 返回响应的服务器的域名
Set-Cookie 在客户端里面设置一个Cookie。这个相应里面可以包含多个Set-Cookie的首部。
W-W-W-Authenticate 服务器通过这个首部告知客户端,在Authorization请求首部中应该提供哪些类型的身份验证信息。服务器常常会把这个首部与“401 Unauthorized”状态行一同发送。除此之外,这个首部还会向服务器许可的认证授权模式(schema)提供验证信息

5.URI

URI(Uniform Resource Location, 统一资源定位符)是一个涵盖性术语,它包含了URN(Uniform Resource Name, 统一资源名称)和URL,并且这两者也拥有相似的语法和格式。

URI的一般格式为:<方案名称>:<分层部分>[ ? <查询参数> ][ # <片段> ]

URI中的方案名称(scheme name)记录了URI正在使用的方案,它定义了URI其余部分的结构。因为URI是一种非常常用的资源标识方式,所以它拥有大量的方案可供使用。

URI的分层部分(hierarchical part)包含了资源的识别信息,这些信息会以分层的方式进行组织。如果分层部分以双斜线(//)开头,那么说明它包含了可选的用户信息,这些信息将以@符号结尾,后跟分层路径。不带用户信息的分层部分就是一份单纯的路径,每个路径都由一连串的分段(segment)组成,各个分段之间使用但斜杠(/)分隔。

在URI的各个部分当中,只有“方案名称”和“分层部分”是必须的。以问好(?)为前缀的查询参数(query)是可选的,这些参数用于包含无法使用分层方式表示的其他信息。多个查询参数会被组织成一连串的键值对,各个键值对之间只用&符号分割。

URI的零一个可选部分为片段(fragment),片段使用井号(#)作为前缀,它可以对URI定义的资源中的次级资源(secondary resource)进行标识。当URI包含查询参数时,URI的片段将被放到查询参数之后。因为URI的片段是由客户端负责处理的,所以Web浏览器在将URI发送给服务器之前,一般都会先把URI中的片段移除掉。如果程序员想要取得URI片段,那么可以通过JavaScript或者某个HTTP客户端库,将URI片段包含在一个GET请求里面。