1.3 HTTP请求与响应
通过以上对HTTP通信方式的介绍可以发现,HTTP请求和HTTP响应在HTTP通信中起到了至关重要的作用,因为浏览器和 Web 应用之间的所有通信都是依靠请求和响应完成的。一个典型的 HTTP请求消息的内容如下:
GET / HTTP/1.1 Accept:image/gif,image/x-xbitmap,image/jpeg,image/pjpeg,application/x-shockwave-flash,application/vnd. ms-excel, application/vnd.ms-powerpoint, application/msword, */* Accept-Language: zh-cn Accept-Encoding: gzip, deflate User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1) Host: www.csai.cn …
该消息用于请求http://www.csai.cn的主页。对请求的响应消息如下(HTML页面内容部分用“…”省略):
HTTP/1.1 200 OK Server: Microsoft-IIS/5.0 Content-Location: http://www.csai.cn/index.htm Date: Mon, 24 Dec 2007 08:31:08 GMT Content-Type: text/html Accept-Ranges: bytes Last-Modified: Mon, 24 Dec 2007 02:48:20 GMT Content-Length: 60744 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/ xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" lang="zh-CN"> <head> <title>希赛网 中国IT技术门户 为企业和IT技术人员提供最全面的服务平台</title> … </body> </html>
这一对请求/响应消息是使用IE浏览器访问希赛主页时产生的HTTP消息流。在IE的地址栏中键入希赛网主页的地址http://www.csai.cn,单击回车后,IE浏览器便会将这一段请求消息以文本的形式发送出去,经过网络传递到希赛网的Web服务器上,Web服务器经过分析发现该客户端请求的是希赛网的主页,于是将希赛网的主页放在响应消息中发送回客户机的浏览器。下面对HTTP请求和响应消息分别进行详细介绍。
1.3.1 HTTP请求消息
HTTP请求消息由Request-Line(请求行)、Header Field(头域)和Message-Body(消息体)组成,如图1.4所示。
图1.4 HTTP请求消息格式
Request-Line在HTTP请求消息的第一行,一般格式是:
Request-Line = Method[SP]Request-URI[SP]HTTP-Version CRLF
其中Method称为HTTP方法(HTTP Method),它表示该请求所要进行的操作类型;Request-URI称为请求URI,它表示与该请求有关的Web服务器中的资源定位符;HTTP-Version表示该请求使用的HTTP协议的版本号,一般是 HTTP/1.0 或 HTTP/1.1,目前使用的 HTTP 版本大部分都是HTTP/1.1。[SP]表示空格,CRLF表示回车换行,它们都是格式信息,用于分隔各部分信息。例如:
GET /index.htm HTTP/1.1
就是一个典型的 Request-Line,其中 GET 是 HTTP 方法、/index.htm是Request-URI、HTTP/1.1是HTTP版本号。
头域紧跟在 Request-Line 的后面,每个域一行,本节后面部分将会详细介绍头域。消息体在头域后面,与头域隔一个空行,不过并不是所有HTTP请求消息都有消息体,有些就没有消息体,这是由该HTTP请求消息的HTTP方法类型决定的。
1.HTTP方法
HTTP请求消息通过使用不同的HTTP方法来向接收到请求的主机说明其请求所期望执行的操作。HTTP/1.1总共定义了OPTIONS、GET、HEAD、POST、PUT、DELETE、TRACE和CONNECT八种HTTP方法,其中GET方法和POST方法是最常见的也是使用最多的HTTP方法,其他方法使用得很少,甚至有些方法在很多服务器中都会被屏蔽或者忽略,所以本书将只重点针对GET方法和POST方法进行详细介绍。
平时读者在上网浏览网页时基本上都是用GET方法,GET方法向服务器申请请求URI指定的资源。请求URI可能指向的是一个服务器Web路径下的一个文件,接收到请求后Web服务器会将该文件的内容作为HTTP响应的内容返回给浏览器;请求URI也可能指向一个数据处理过程(比如一个Servlet),那么Web服务器会执行该过程并将该过程执行结束后向客户端反馈的结果信息加入到HTTP响应中返回。可见在使用GET方法进行的请求响应过程中,数据流向主要是从服务器向客户机,所以GET请求消息的消息体通常不包含任何内容。一般在如下场景会使用GET方法:
● 在浏览器中键入网页地址,从Web服务器上获取网页中的所有内容,例如HTML、图片、Flash、JavaScript等。请求每一项内容时都会将一个GET请求提交给服务器,然后服务器会处理每一个请求并将请求的内容作为响应返回给浏览器。
● 单击网页上的一个图片链接打开一个图片。浏览器会将图片的URI构造成一个请求消息,并将请求消息提交给服务器,服务器接收到请求消息,解析请求URI,然后将URI指向的图片返回给浏览器。
POST方法则恰好与GET方法相反,POST方法主要用于向服务器提交数据内容;所以一般来说,POST消息的消息体中会包含提交的数据内容。POST消息中请求URI也可以是一个文件位置或者数据处理过程,假如指向的是一个文件位置,那么Web服务器会将POST消息体中携带的数据作为一个文件保存在指定的位置;如果指向的是一个数据处理过程,那么Web服务器会将POST消息体中携带的数据传递给该数据处理过程,并启动该数据处理过程对数据进行处理。通常POST方法会被使用到如下场景:
● 提交登录信息。当输入完用户名和密码、单击登录按钮时,浏览器就会将登录信息(用户名和密码,为了安全起见,很多系统会对密码加密)作为POST消息的消息体提交给Web服务器。
● 在论坛中发帖子。帖子的标题和内容会作为POST消息的消息体提交给Web服务器。
● 发送E-mail。E-mail的各项信息(发件人、收件人、抄送、密送、标题、正文等)会组织成一定的格式,然后作为POST消息的消息体提交给Web服务器。
2.Request-URI
Request-URI称为请求URI,它是一个不含空白字符的字符串,符合URI(资源定位符)的格式规范,表示Web服务器上的一个资源位置,可以是以下四种格式:
Request-URI = "*" | absoluteURI | abs path | authority
● * 表示该Request-URI并不指向某个特定的位置,说明该HTTP请求消息所请求的操作是针对整个Web服务器、而不是针对某个特定资源的。当然并不是所有的HTTP方法都能够使用 * 作为Request-URI,只有某些特定的HTTP方法才可以,比如OPTIONS。
● absoluteURI是一个用绝对形式表示的URI,即以协议开头的URI,比如:“http://www.csai.cn/image/bg.png”,这种表示形式单独就能指定一个唯一的网络资源位置。
● abs_path是一个用相对形式表示的URI,但它必须是一个Web服务器上的绝对路径,必须以一个 / 开头,例如:/image/bg.png。这种表示形式指定了一个从Web服务器根目录开始的相对路径。Web服务器根目录是服务器设置的所有Web资源的顶层目录。假设,域名为“csai.cn”的Web服务器设置的根目录是“D:\webroot”,那么URL“http://www.csai.cn/index.htm”就是请求Web服务器上的文件“D:\webroot\index.htm”。可见,使用abs_path的Request-URI只是指定了Web服务器内部的路径,并没有指定Web服务器的主机地址,所以它不能单独用于指定一个网络位置。用这种Request-URI的HTTP请求消息都会有一个名为Host的头域,它的值就用于指定一个主机的地址,比如:Host头域值为“www.csai.cn”,Request-URI为“/image/bg.png”的HTTP请求消息所指定资源位置也是“http://www.csai.cn/image/bg.png”。
● authority仅能被用于CONNECT方法。
1.3.2 HTTP响应消息
HTTP响应消息是Web服务器在处理完HTTP请求消息后返回给客户机浏览器的消息,它也由状态行、头域和消息体组成,如图1.5所示:
图1.5 HTTP响应消息格式
状态行的一般格式如下:
Status-Line = HTTP-Version[SP]Status-Code[SP]Reason-Phrase CRLF
其中,HTTP-Version、SP和CRLF的意义与请求消息中的一样。Status-Code是响应状态码,它是3位十进制数,HTTP/1.1预定义了很多状态码,用于表示服务器处理请求的状态;Reason-Phrase是一个简短的文字,它对响应码进行文字性说明。Status-Code根据首位数字的不同可分为如下五大类:
1.1xx:信息响应类,表示接收到请求并且继续处理。例如“100 Continue”表示服务器已接收并开始处理请求,要求客户机继续发送请求的剩余部分,如果请求已被发送完全,客户机可以忽略该消息。
2.2xx:处理成功响应类,表示动作被成功接收、理解和接受。例如“200 OK”表示请求的操作已成功完成,对于GET请求则表示请求的资源已附在响应消息中,对于 POST 请求则表示提交的内容已被处理。
3.3xx:重定向响应类,为了完成指定的动作,必须接受进一步处理。例如“301 Moved Permanently”表示请求的资源已被永久移往另外一个 URI,往后对该资源的请求应该都替换成新的 URI,新的URI将由响应消息的Location头域说明;“302 Found”表示请求应该暂时被重定向为另外一个URI,以后对该资源的请求应该还是使用当前的URI。
4.4xx:客户端错误类,客户请求包含语法错误或者是不能被正确执行。例如“400 Bad Request”表示客户端提交的请求无法被服务器理解,客户端需要对请求重新改动后再提交请求;“403 Forbidden”表示服务器已理解客户端的请求,但是服务器拒绝执行客户端请求的操作;“404 Not Found”表示客户端请求中Request-URI指定的资源位置不存在。
5.5xx:服务端错误类,服务器不能正确执行一个正确的请求。例如“500 Internal Server Error”表示服务器遭遇一个非预期错误而导致无法完成请求的操作。
1.3.3 Header Field
如前面所述,在HTTP请求消息和响应消息中都包含Header Field,这些头域用于说明一些辅助信息,以便于丰富客户机和服务器之间的通信。有些头域用于说明一些通用信息,称为General Header Field (通用头域),即可以用于请求消息也可以用于响应消息;有些头域只被用于请求消息,称为 Request Header Field(请求头域);有些头域只被用于响应消息,称为Response Header Field(响应头域);有些头域用于说明传输内容的信息,它们可以被用于请求消息也可以被用于响应消息。整个头域由多条头域项组成,每条头域项占一行。头域项的一般格式为:
Field-Name: Field -Value
其中Field -Name是头域名,Field -Value是头域值。
1.General Header Field
这类头域既可以出现在请求消息中也可以出现在响应消息中,它们只描述了传递消息的一些属性,而不能用于描述传送文件的信息。常见的有如下几种。
● Cache-Control:用于指定一种缓冲机制,这种缓冲机制在整个请求/响应过程中必须被遵守。该头域中指定的缓冲机制将覆盖默认的缓冲机制。例如:
Cache-Control: no-cache
● Date:表示消息生成时的日期时间,该域所使用的日期格式必须符合HTTP日期格式,例如:
Date: Tue, 13 Nov 2007 08:12:31 GMT
● Pragma:用于指定一些实现相关的参数,在HTTP协议中并没有规定该头域所携带参数的意义,例如:
Pragma: “string”
其中“string”表示一个由引号括起的字符串,各种对 HTTP 协议的不同实现(例如不同的浏览器和服务器)可以利用该头域定义用于传递特定信息的一系列字符串。
● Transfer-Encoding:如果该头域被指定,那就说明消息体采用了所指定的传输类型进行传输。例如最常见的:
Transfer-Encoding: chunked
表示消息体采用分块传输的方式进行传输。
2.Request Header Field
这类头域只出现在请求消息中,它们通常被客户机用于向服务器传递一些客户机的信息或者请求消息的信息。常见的有如下几种。
● Accept:可以被用来说明客户机浏览器能够接受的媒体格式,例如:
Accept: text/html, text/plain, image/*
表示客户机浏览器接受HTML和纯文本以及各种图片格式。
● Accept-Charset:可以被用来说明客户机浏览器能够接受的字符编码方式,例如:
Accept-Charset: iso-8859-1, gb2312
表示客户机浏览器接受的字符编码格式有ISO—8859—1(也就是ASCII编码)和gb2312(一种简体中文编码)。
● Accept-Encoding:可以被用来说明客户机浏览器能够接受的内容编码方法,通常用来指定内容的压缩方法,例如:
Accept-Encoding: gzip, identity
表示客户机浏览器接受gzip压缩方式和不压缩。
● Accept-Language:可以被用来说明客户机浏览器能够接受的语言,例如:
Accept-Language: zh-CN
表示客户机浏览器接受简体中文。
● From:表示提交该请求的终端用户的电子邮件,例如:
From: user@company.com
表示提交该请求的终端用户的电子邮件地址为user@company.com。
● Host:指示Internet上的一个主机和端口号,主机通常是域名或者IP地址,例如:
Host: www.csai.cn
表示该请求访问的主机的域名为www.csai.cn。
● If-Match:如果HTTP请求中含有该头域或者后面将要提到的If-ModifiedSince,If-None-Match,If-Range和If-Unmodified-Since头域时,那么该请求就变成了“条件请求”,即只有满足上述描述的条件时请求的操作才要被执行,这样可以减少不必要的资源浪费。该域的值是一个匹配字符串,如果该匹配字符串匹配成功则执行操作,否则不执行操作。在匹配字符串中*表示任意。例如:
If-Match: *
表示匹配任何资源。
● If-None-Match:意义与If-Match恰好相反,表示匹配不成功则执行,否则不执行。
● If-Modified-Since:值是一个日期,表示请求的资源如果从给定的日期后修改过则执行操作,否则不执行。例如
If-Modified-Since: Tue, 13 Nov 2007 08:12:31 GMT
表示:如果请求的文件在2007-11-13 08:12:31后被更改过,则执行操作。
● If-Unmodified-Since:意义与If-Modified-Since恰好相反,表示:请求的资源如果从给定的日期后没有被修改过则执行操作,否则不执行。
● If-Range:假如客户机的缓冲池中已有了资源实体的一部分,而期望获得剩余部分,则客户机的请求可以使用该头域。它表示:“如果指定的资源实体没有被更改则将缺少的发给我,否则发给我整个资源实体”。
● Max-Forwards:在TRACE和OPTIONS方法中使用,用于限制消息在网络中传播的跳数,即消息被代理或者网关转发的次数,以此来限制消息的生命期。
● Range:用于指定一个范围,它表示请求的资源实体的范围,可以使用字节数指定。If-Range需要的范围就是通过该头域指定的。
● Referer:客户机用该域告诉服务器,请求中的Request-URI是如何获得的。例如
Referer: http://www.csai.cn/index.htm
表示当前请求资源的URI是从页面http://www.csai.cn/index.htm中获得的。
● User-Agent:可以被用来说明客户机浏览器的型号,例如
Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)
表示客户机是使用Mozilla/4.0兼容浏览器、IE6.0等。
3.Response Header Field
这类头域只出现在响应消息中,它们通常被服务器用于向客户机传递一些服务器的信息或者响应消息的信息。常见的有以下几类。
● Accept-Ranges:服务器用于指示它所接受的Range类型,比如
Accept-Ranges: bytes
表示服务器接受以byte形式指示的Range。
Accept-Ranges: none
表示服务器不接受任何形式的Range。
● Age:顾名思义,在响应消息中该头域表示响应消息的“年龄”,也就是服务器估计的该响应消息产生后的时间长度。
● Location:当响应消息的响应码为3xx时,该头域会被响应消息用于指示重定向后新的URL。
● Retry-After:通常用于响应码为503的响应消息,503响应消息表示服务器当前不可用,该头域估计了一个服务器不可用的时间。头域值可以是一个HTTP日期或者是一个数字。例如:
Retry-After: Tue, 13 Nov 2007 08:12:31 GMT
表示服务器在2007-11-13 08:12:31之前不可用,请在该时间以后重试。
Retry-After: 120
表示服务器当前不可用,请在120秒后重试。
● Server:表示运行在服务器上用于处理请求的软件的信息。
4.Entity Header Field
该类头域描述了消息体中携带的数据的元数据(即对数据的长度、类型、修改时间等属性的描述信息),请求消息和响应消息中都可以包含这类头域。常见的有以下几类。
● Allow:表示Request-URI指定的资源实体所支持的HTTP方法列表,在响应码为405的响应消息中必须包含该头域。例如:
Allow: GET, HEAD, PUT
表示Request-URI指定的资源实体仅支持GET、HEAD和PUT三种HTTP方法。
● Content-Encoding:指示消息内容的编码方法,通常指示内容的压缩算法。例如:
Content-Encoding: gzip
表示消息中数据采用gzip算法编码。
● Content-Language:表示消息内容所采用的自然语言。例如:
Content-Language: en
表示消息体中数据表示的内容是英文的。
● Content-Length:表示消息长度。头域值是十进制数,表示字节数。例如:
Content-Length: 2353
表示消息体中数据的长度为2353字节。
● Content-Location:表示除了Request-URI指定的位置外,其他可以访问到消息内容的位置。
● Content-MD5:表示消息体中数据的MD5校验码,用来实现端到端的消息完整性检查。
● Content-Range:当传递的数据是整个资源实体的一部分时,用该域说明当前传递的数据是资源实体的哪一部分。例如:
Content-Range: 0-500/1023
表示资源实体总共范围为0-1023,而当前传递的是0-500。
● Content-Type:指示消息体中内容的媒体格式。例如:
Content-Type: text/html; charset=iso-8859-1
表示消息体中携带的内容是HTML文档,它的媒体格式是text大类中的HTML子类,文档的字符编码是ISO—8859—1;
● Expires:指定了一个日期,表示消息体中的内容在该日期之前有效,过了该日期则消息内容就过时了。
● Last-Modified:表示消息中携带的内容实体的最后修改时间。