HTTP协议 - HTTP请求

协议是指计算机通信网络中两台计算机之间进行通信所必须共同遵守的规定或规则,超文本传输协议(HTTP)是一种通信协议,它允许将超文本标记语言(HTML)文档从Web服务器传送到客户端的浏览。

超文本传输协议(英文:HyperText Transfer Protocol,缩写:HTTP)是互联网上应用最为广泛的一种网络协议。设计HTTP最初的目的是为了提供一种发布和接收HTML页面的方法。

通过HTTP或者HTTPS协议请求的资源由统一资源标识符(Uniform Resource Identifiers,URI)来标识。

超文本传输协议,是一种无状态协议,就是说客户端发送一次请求,服务器端接收请求,经过处理返回给客户端信息,然后客户端和服务器端的链接就断开了,为了维护他们之间的链接,让服务器知道这是前一个用户发送的请求,必须在一个地方保存客户端的信息,有2中解决方案,一是在客户端保存,二是在服务器端保存。
1.在客户端保存:Cookie
2.在服务器端保存:Session(session需要依靠cookie来实现)
3.在用户禁用cookie的限制下,只能使用URL重写的方式在每次请求之后附上一个键值对来保存客户端的信息。
4.隐藏表单。<input type="hidden" name="method" value="login">

URI统一资源标识符

统一资源标识符(Uniform Resource Identifier,或URI)是一个用于标识某一互联网资源名称的字符串。 该种标识允许用户对网络中(一般指万维网)的资源通过特定的协议进行交互操作。URI的最常见的形式是统一资源定位符(URL),经常指定为非正式的网址。

更罕见的用法是统一资源名称(URN),其目的是通过提供一种途径。用于在特定的命名空间资源的标识,以补充网址。

URI可被视为定位符(URL),名称(URN)或两者兼备。统一资源名(URN)如同一个人的名称,而统一资源定位符(URL)代表一个人的住址。换言之,URN定义某事物的身份,而URL提供查找该事物的方法。

用于标识唯一书目的ISBN系统是一个典型的URN使用范例。例如,ISBN 0-486-27557-4( urn:isbn:0-486-27557-4 )无二义性地标识出莎士比亚的戏剧《罗密欧与朱丽叶》的某一特定版本。为获得该资源并阅读该书,人们需要它的位置,也就是一个URL地址。在类Unix操作系统中,一个典型的URL地址可能是一个文件目录,例如file:///home/username/RomeoAndJuliet.pdf。该URL标识出存储于本地硬盘中的电子书文件。因此,URL和URN有着互补的作用。

URL统一资源定位符

统一资源定位符(或称统一资源定位器/定位地址、URL地址等,英语:Uniform / Universal Resource Locator,常缩写为URL),有时也被俗称为网页地址(网址)。如同在网络上的门牌,是因特网上标准的资源的地址(Address)。

在因特网的历史上,统一资源定位符的发明是一个非常基础的步骤。统一资源定位符的语法是一般的,可扩展的,它使用ASCII代码的一部分来表示因特网的地址。统一资源定位符的开始,一般会标志着一个计算机网络所使用的网络协议。

统一资源定位符的标准格式如下:

1
2
协议类型://服务器地址:端口名/路径/文件名/?参数名=参数#锚点名
schema://host[:port#]/path/.../[?query-string][#anchor]
名称 描述
scheme 指定低层使用的协议,如 http, https, ftp。
host HTTP服务器的IP地址或者域名。
port HTTP服务器的断开,默认是80。如非默认端口必须显式指明。
path 访问资源的路径。
query-string 发送给http服务器的数据。
anchor 锚点。

http://www.mywebsite.com/sj/test;id=8079?name=sviergn&x=true#stuff 举例:

  • schema: http
  • host: www.mywebsite.com
  • path: /sj/test
  • query string: name=sviergn&x=true
  • anchor: stuff

HTTP请求

http请求由三部分组成,分别是:请求行,请求头,请求正文。

请求行主要由三部分组成,请求方法、请求路径、协议版本,其格式如下:

1
2
3
4
5
6
MethodRequest URI/HTTP-Version CRLF
MethodRequest:HTTP规范定义了8种可能的请求方法,常用的是GET、POST和HEAD方法。
URI:请求路径可以是相对或者绝对的方式。
HTTP-Version:目前常用的支持HTTP/1.0和HTTP/1.1方式。
CRLF:回车和换行,除了作为结尾的CRLF,其余位置不允许出现单独的CR或LF。

get方法的请求方式比较简单,所有请求的参数都显示追加在请求的url后面,而且请求长度有限制。

post方式的请求参数都追加在请求体当中,消息长度没有限制而且以隐式的方式进行发送,安全性相对较高。

head方法通常用于测试超链接的有效性,是否可以访问,以及最近是否更新。

head方法与get方法几乎是一样的,head请求的回应部分中HTTP头部的信息与get请求所得到信息是相同的,利用这个方法,不必传输整个资源内容,就可以得到这个URI所标识的资源内容的信息,例如在下载文件前,需要知道文件的大小,格式,文件名等,就可以使用该方法。

在下面的例子中,GET 是请求方法,http://www.microsoft.com 是请求路径,HTTP/1.1 是协议和版本。

1
GET http://www.microsoft.com/HTTP/1.1

在下面的例子,请求方法是 POST ,获得的额外数据是 user=jeffrey&pwd=1234

1
2
3
4
5
6
7
8
9
10
11
12
13
POST /reg.jsp HTTP/ (CRLF)
Accept:image/gif,image/x-xbit,... (CRLF)
...
HOST:www.guet.edu.cn (CRLF)
Content-Length:22 (CRLF)
Connection:Keep-Alive (CRLF)
Cache-Control:no-cache (CRLF)
(CRLF) //该CRLF表示消息报头已经结束,在此之前为请求头
user=jeffrey&pwd=1234

请求头都是以key:value形式进行保存的,里面记录了客户端的一些基本信息,常用的请求头如下所示:

Accept:浏览器可接受的MIME类型,也就是文件类型。

Accept-Charset:浏览器可接受的字符集,如GBK。

Accept-Encoding:浏览器能够进行解码的数据编码方式,比如gzip。

Accept-Language:浏览器所希望的语言种类,当服务器能够提供一种以上的语言版本时要用到。

Authorization:授权信息,通常出现在对服务器发送的WWW-Authenticate头的应答中。

Connection:表示是否需要持久连接。

Cache-Control:指定请求和响应遵循的缓存机制。

Content-Length:表示请求消息正文的长度。

Cookie:HTTP请求发送时,会把保存在该请求域名下的所有cookie值一起发送给web服务器。

From:请求发送者的email地址,由一些特殊的Web客户程序使用,浏览器不会用到它。

Host:指定请求的服务器的域名和端口号。

UA-Pixels,UA-Color,UA-OS,UA-CPU:表示屏幕大小、颜色深度、操作系统和CPU类型。

请求体(又叫请求正文)是post请求方式当中的请求参数,以key=value形式进行存储,多个请求参数之间用&连接,如果请求当中有请求提,那么在请求头当中的Content-Length属性中记录的是该请求体的长度。

下面来看一个还算完整的请求消息吧,这样可能会稍微直观一点:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
POST hysj.jsp HTTP/1.1
********************************
Host: search.cnipr.com
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.0; zh-CN; rv:1.9.1.13) Gecko/20100914 Firefox/3.5.13 ( .NET CLR 3.5.30729)
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-cn,zh;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: GB2312,utf-8;q=0.7,*;q=0.7
Keep-Alive: 300
Connection: keep-alive
Referer: http://search.cnipr.com/cnipr/zljs/hyjs-biaodan-y.jsp
Content-Length: 405
********************************
username=guest&extension=&issearch=on&searchword=pd%3D%2820100901%29&presearchword=&sortfield=RELEVANCE&sRecordNumber=&searchType=0&searchFrom=0&channelid=14%2C15%2C16&searchChannel=14%2C15%2C16&strdb=14&strdb=15&strdb=16&cizi=2&sortcolumn=RELEVANCE&R1=-&txtA=&txtB=&txtC=&txtD=20100901&txtE=&txtF=&txtG=&txtH=&txtI=&txtJ=&txtK=&txtL=&txtM=&txtN=&txtP=&txtQ=&txtR=&txtSearchWord=&Submit=%BC%EC%A1%A1%CB%F7

HTTP响应

在接收和解释请求消息后,服务器返回一个HTTP响应消息。

HTTP响应也是由三个部分组成,分别是:响应行、响应头、响应正文。

响应行是标识服务器端对客户端请求的处理结果,主要由响应状态信息,响应状态码,服务器协议组成:

1
2
3
4
5
HTTP-Version Status-Code Reason-Phrase CRLF
HTTP-Version:表示服务器HTTP协议的版本
Status-Code:表示服务器发回的响应状态代码
Reason-Phrase:表示状态代码的文本描述

状态代码有三位数字组成,第一个数字定义了响应的类别,且有五种可能取值:

状态码 描述
1xx 指示信息–表示请求已接收,继续处理。
2xx 成功–表示请求已被成功接收、理解、接受。
3xx 重定向–要完成请求必须进行更进一步的操作。
4xx 客户端错误–请求有语法错误或请求无法实现。
5xx 服务器端错误–服务器未能实现合法的请求。

常见状态代码、状态描述、说明:

状态码 描述
200 OK 客户端请求成功。
400 Bad Request 客户端请求有语法错误,不能被服务器所理解。
401 Unauthorized 请求未经授权,这个状态代码必须和WWW-Authenticate报头域一起使用。
403 Forbidden 服务器收到请求,但是拒绝提供服务。
404 Not Found 请求资源不存在,eg:输入了错误的URL。
500 Internal Server Error 服务器发生不可预期的错误。
503 Server Unavailable 服务器当前不能处理客户端的请求,一段时间后可能恢复正常。

响应头域允许服务器传递不能放在状态行的附加信息,这些域主要描述服务器的信息和 Request-URI进一步的信息。响应头域包含Age、Location、Proxy-Authenticate、Public、Retry- After、Server、Vary、Warning、WWW-Authenticate。对响应头域的扩展要求通讯双方都支持,如果存在不支持的响应头域,一般将会作为实体头域处理。

常见的响应头信息如下:

Allow

服务器支持哪些请求方法(如GET、POST等)。

Content-Encoding

文档的编码(Encode)方法。只有在解码之后才可以得到Content-Type头指定的内容类型。利用gzip压缩文档能够显著地减少HTML文档的下载时间。Java的GZIPOutputStream可以很方便地进行gzip压缩,但只有Unix上的Netscape和Windows上的IE 4、IE 5才支持它。因此,Servlet应该通过查看Accept-Encoding头(即request.getHeader(“Accept-Encoding”))检查浏览器是否支持gzip,为支持gzip的浏览器返回经gzip压缩的HTML页面,为其他浏览器返回普通页面。

Content-Length

表示内容长度。只有当浏览器使用持久HTTP连接时才需要这个数据。如果你想要利用持久连接的优势,可以把输出文档写入ByteArrayOutputStram,完成后查看其大小,然后把该值放入Content-Length头,最后通过byteArrayStream.writeTo(response.getOutputStream()发送内容。

Content-Type

表示后面的文档属于什么MIME类型。Servlet默认为text/plain,但通常需要显式地指定为text/html。由于经常要设置Content-Type,因此HttpServletResponse提供了一个专用的方法setContentType。

Date

当前的GMT时间。你可以用setDateHeader来设置这个头以避免转换时间格式的麻烦。

Last-Modified

文档的最后改动时间。客户可以通过If-Modified-Since请求头提供一个日期,该请求将被视为一个条件GET,只有改动时间迟于指定时间的文档才会返回,否则返回一个304(Not Modified)状态。Last-Modified也可用setDateHeader方法来设置。

Location

表示客户应当到哪里去提取文档。Location通常不是直接设置的,而是通过HttpServletResponse的sendRedirect方法,该方法同时设置状态代码为302

Refresh

表示浏览器应该在多少时间之后刷新文档,以秒计。

Server

服务器名字。Servlet一般不设置这个值,而是由Web服务器自己设置。

Set-Cookie

设置和页面关联的Cookie。Servlet不应使用response.setHeader(“Set-Cookie”, …),而是应使用HttpServletResponse提供的专用方法addCookie。

WWW-Authenticate

客户应该在Authorization头中提供什么类型的授权信息?在包含401(Unauthorized)状态行的应答中这个头是必需的。例如,response.setHeader("WWW-Authenticate", "BASIC realm=\"executives\"")
注意Servlet一般不进行这方面的处理,而是让Web服务器的专门机制来控制受密码保护页面的访问(例如.htaccess)。

下面是一个典型的响应消息:

1
2
3
4
5
6
7
8
HTTP/1.0200OK
Date:Mon,31Dec200104:25:57GMT
Server:Apache/1.3.14(Unix)
Content-type:text/html
Last-modified:Tue,17Apr200106:46:28GMT
Etag:"a030f020ac7c01:1e9f"
Content-length:39725426
Content-range:bytes554554-40279979/40279980

下面是以Charles工具抓取的优酷响应消息的截图:

youku