HTTP结构之request
http请求由三部分组成,分别是:请求行、消息报头、请求正文
1.请求行
请求行以一个方法符号开头,以空格分开,后面跟着请求的URI和协议的版本,格式如下:Method Request-URI HTTP-Version CRLF 其中 Method表示请求方法;Request-URI是一个统一资源标识符;HTTP-Version表示请求的HTTP协议版本;CRLF表示回车和换行(除了作为结尾的CRLF外,不允许出现单独的CR或LF字符)。
2.请求方法:
HTTP/1.1协议中共定义了八种方法(有时也叫“动作”)来表明RequestURI指定的资源的不同操作方式:
- OPTIONS :返回服务器针对特定资源所支持的HTTP请求方法。也可以利用向Web服务器发送'*'的请求来测试服务器的功能性。
- HEAD :向服务器索要与GET请求相一致的响应,只不过响应体将不会被返回。这一方法可以在不必传输整个响应内容的情况下,就可以获取包含在响应消息头中的元信息。该方法常用于测试超链接的有效性,是否可以访问,以及最近是否更新。
- GET :向特定的资源发出请求。注意:GET方法不应当被用于产生“副作用”的操作中,例如在web app.中。其中一个原因是GET可能会被网络蜘蛛等随意访问。
- POST :向指定资源提交数据进行处理请求(例如提交表单或者上传文件)。数据被包含在请求体中。POST请求可能会导致新的资源的建立和/或已有资源的修改。
- PUT :向指定资源位置上传其最新内容。
- DELETE :请求服务器删除RequestURI所标识的资源。
- TRACE :回显服务器收到的请求,主要用于测试或诊断。
- CONNECT :HTTP/1.1协议中预留给能够将连接改为管道方式的代理服务器。
- PATCH :用来将局部修改应用于某一资源,添加于规范RFC5789。
方法名称是区分大小写的。当某个请求所针对的资源不支持对应的请求方法的时候,服务器应当返回状态码405(Method Not Allowed);当服务器不认识或者不支持对应的请求方法的时候,应当返回状态码501(Not Implemented)。HTTP服务器至少应该实现GET和HEAD方法,其他方法都是可选的。此外,除了上述方法,特定的HTTP服务器还能够扩展自定义的方法。
GET和POST的区别:
- 1、GET提交的数据会放在URL之后,以?分割URL和传输数据,参数之间以&相连,如EditPosts.aspx?name=test1&id=123456. POST方法是把提交的数据放在HTTP包的Body中。
- 2、GET提交的数据大小有限制,最多只能有1024字节(因为浏览器对URL的长度有限制),而POST方法提交的数据没有限制。
- 3、GET方式需要使用Request.QueryString来取得变量的值,而POST方式通过Request.Form来获取变量的值。
- 4、GET方式提交数据,会带来安全问题,比如一个登录页面,通过GET方式提交数据时,用户名和密码将出现在URL上,如果页面可以被缓存或者其他人可以访问这台机器,就可以从历史记录获得该用户的账号和密码。
3.请求报头
请求报头允许客户端向服务器端传递请求的附加信息以及客户端自身的信息。
常用的请求报头
- Accept:Accept请求报头域用于指定客户端接受哪些类型的信息。Accept:image/gif,表明客户端希望接受GIF图象格式的资源;Accept:text/html,表明客户端希望接受html文本。
- Accept-Charset:Accept-Charset请求报头域用于指定客户端接受的字符集。Accept-Charset:gb2312.如果在请求消息中没有设置这个域,缺省是任何字符集都可以接受。
- Accept-Encoding:Accept-Encoding请求报头域类似于Accept,但是它是用于指定可接受的内容编码。Accept-Encoding:gzip.deflate.如果请求消息中没有设置这个域服务器假定客户端对各种内容编码都可以接受。
- Accept-Language:Accept-Language请求报头域类似于Accept,但是它是用于指定一种自然语言。Accept-Language:zh-cn.如果请求消息中没有设置这个报头域,服务器假定客户端对各种语言都可以接受。
- Authorization:Authorization请求报头域主要用于证明客户端有权查看某个资源。当浏览器访问一个页面时,如果收到服务器的响应代码为401(未授权),可以发送一个包含Authorization请求报头域的请求,要求服务器对其进行验证。
- Host(发送请求时,该报头域是必需的):Host请求报头域主要用于指定被请求资源的Internet主机和端口号,它通常从HTTP URL中提取出来的,我们在浏览器中输入:http://www.guet.edu.cn/index.... 浏览器发送的请求消息中,就会包含Host请求报头域,如下:Host:www.guet.edu.cn
此处使用缺省端口号80,若指定了端口号,则变成:Host:www.guet.edu.cn:指定端口号
- User-Agent:我们上网登陆论坛的时候,往往会看到一些欢迎信息,其中列出了你的操作系统的名称和版本,你所使用的浏览器的名称和版本,这往往让很多人感到很神奇,实际上,服务器应用程序就是从User-Agent这个请求报头域中获取到这些信息。User-Agent请求报头域允许客户端将它的操作系统、浏览器和其它属性告诉服务器。不过,这个报头域不是必需的,如果我们自己编写一个浏览器,不使用User-Agent请求报头域,那么服务器端就无法得知我们的信息了。
- Connection:Connection: keep-alive 当一个网页打开完成后,客户端和服务器之间用于传输HTTP数据的TCP连接不会关闭,如果客户端再次访问这个服务器上的网页,会继续使用这一条已经建立的连接。HTTP 1.1默认进行持久连接。利用持久连接的优点,当页面包含多个元素时(例如Applet,图片),显著地减少下载所需要的时间。
Connection: close 代表一个Request完成后,客户端和服务器之间用于传输HTTP数据的TCP连接会关闭,当客户端再次发送Request,需要重新建立TCP连接
- If-Modified-Since:把浏览器端缓存页面的最后修改时间发送到服务器去,服务器会把这个时间与服务器上实际文件的最后修改时间进行对比。如果时间一致,那么返回304,客户端就直接使用本地缓存文件。如果时间不一致,就会返回200和新的文件内容。客户端接到之后,会丢弃旧文件,把新文件缓存起来,并显示在浏览器中
- IfNoneMatch:IfNoneMatch和ETag一起工作,工作原理是在HTTP Response中添加ETag信息。 当用户再次请求该资源时,将在HTTP Request 中加入IfNoneMatch信息(ETag的值)。如果服务器验证资源的ETag没有改变(该资源没有更新),将返回一个304状态告诉客户端使用本地缓存文件。否则将返回200状态和新的资源和Etag. 使用这样的机制将提高网站的性能
- Referer:包含一个URL,用户从该URL代表的页面出发访问当前请求的页面。提供了Request的上下文信息的服务器,告诉服务器我是从哪个链接过来的,比如从我主页上链接到一个朋友那里,他的服务器就能够从HTTP Referer中统计出每天有多少用户点击我主页上的链接访问他的网站。
HTTP结构之response
在接收和解释请求消息后,服务器返回一个HTTP响应消息。HTTP响应也是由三个部分组成,分别是:状态行、消息报头、响应正文
1、状态行格式如下:
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 //服务器当前不能处理客户端的请求,一段时间后可能恢复正常
2.响应报头
响应报头允许服务器传递不能放在状态行中的附加响应信息,以及关于服务器的信息和对Request-URI所标识的资源进行下一步访问的信息。
常用的响应报头
- Allow:服务器支持哪些请求方法(如GET、POST等)。
- Date:表示消息发送的时间,时间的描述格式由rfc822定义。例如,Date:Mon,31Dec200104:25:57GMT。Date描述的时间表示世界标准时,换算成本地时间,需要知道用户所在的时区。你可以用setDateHeader来设置这个头以避免转换时间格式的麻烦
- Expires:指明应该在什么时候认为文档已经过期,从而不再缓存它,重新从服务器获取,会更新缓存。过期之前使用本地缓存。HTTP1.1的客户端和缓存会将非法的日期格式(包括0)看作已经过期。eg:为了让浏览器不要缓存页面,我们也可以将Expires实体报头域,设置为0。
例如: Expires: Tue, 08 Feb 2022 11:35:14 GMT
- P3P:用于跨域设置Cookie, 这样可以解决iframe跨域访问cookie的问题
例如: P3P: CP=CURa ADMa DEVa PSAo PSDo OUR BUS UNI PUR INT DEM STA PRE COM NAV OTC NOI DSP COR
- SetCookie:非常重要的header, 用于把cookie发送到客户端浏览器,每一个写入cookie都会生成一个SetCookie。
例如: SetCookie: sc=4c31523a; path=/; domain=.acookie.taobao.com
- ETag:和IfNoneMatch 配合使用。
- LastModified:用于指示资源的最后修改日期和时间。LastModified也可用setDateHeader方法来设置。
- ContentType:WEB服务器告诉浏览器自己响应的对象的类型和字符集。Servlet默认为text/plain,但通常需要显式地指定为text/html。由于经常要设置ContentType,因此HttpServletResponse提供了一个专用的方法setContentType。可在web.xml文件中配置扩展名和MIME类型的对应关系。
- 例如:ContentType: text/html;charset=utf8
- ContentType:text/html;charset=GB2312
- ContentType: image/jpeg
媒体类型的格式为:大类/小类,比如text/html。
- IANA(The Internet Assigned Numbers Authority,互联网数字分配机构)定义了8个大类的媒体类型,分别是:
- application— (比如: application/vnd.msexcel.)
- audio (比如: audio/mpeg.)
- image (比如: image/png.)
- message (比如,:message/http.)
- model(比如:model/vrml.)
- multipart (比如:multipart/formdata.)
- text(比如:text/html.)
- video(比如:video/quicktime.)
- ContentLength:指明实体正文的长度,以字节方式存储的十进制数字来表示。在数据下行的过程中,ContentLength的方式要预先在服务器中缓存所有数据,然后所有数据再一股脑儿地发给客户端。只有当浏览器使用持久HTTP连接时才需要这个数据。如果你想要利用持久连接的优势,可以把输出文档写入ByteArrayOutputStram,完成后查看其大小,然后把该值放入ContentLength头,最后通过
byteArrayStream.writeTo(response.getOutputStream()发送内容。例如: ContentLength: 19847
- ContentEncodingWEB:服务器表明自己使用了什么压缩方法(gzip,deflate)压缩响应中的对象。只有在解码之后才可以得到ContentType头指定的内容类型。利用gzip压缩文档能够显著地减少HTML文档的下载时间。
- ContentLanguage:WEB服务器告诉浏览器自己响应的对象所用的自然语言。例如: ContentLanguage:da。没有设置该域则认为实体内容将提供给所有的语言阅读。
- Server:指明HTTP服务器用来处理请求的软件信息。例如:Server: MicrosoftIIS/7.5、Server:ApacheCoyote/1.1。此域能包含多个产品标识和注释,产品标识一般按照重要性排序。
- Connection:例如:Connection: keep-alive 当一个网页打开完成后,客户端和服务器之间用于传输HTTP数据的TCP连接不会关闭,如果客户端再次访问这个服务器上的网页,会继续使用这一条已经建立的连接。
- Connection: close 代表一个Request完成后,客户端和服务器之间用于传输HTTP数据的TCP连接会关闭,当客户端再次发送Request,需要重新建立TCP连接。
- Location:用于重定向一个新的位置,包含新的URL地址。表示客户应当到哪里去提取文档。Location通常不是直接设置的,而是通过HttpServletResponse的
- Refresh:表示浏览器应该在多少时间之后刷新文档,以秒计。除了刷新当前文档之外,你还可以通过setHeader("Refresh", "5; URL=http://host/path") 让浏览器读取指定的页面。注意这种功能通常是通过设置HTML页面HEAD区的<META HTTPEQUIV="Refresh" CONTENT="5;URL=http://host/path">实现,这是因为,自动刷新或重定向对于那些不能使用CGI或Servlet的HTML编写者十分重要。但是,对于Servlet来说,直接设置Refresh头更加方便。注意Refresh的意义是“N秒之后刷新本页面或访问指定页面”,而不是“每隔N秒刷新本页面或访问指定页面”。因此,连续刷新要求每次都发送一个Refresh头,而发送204状态代码则可以阻止浏览器继续刷新,不管是使用Refresh头还是<META HTTPEQUIV="Refresh" ...> 。注意Refresh头不属于HTTP 1.1正式规范的一部分,而是一个扩展,但Netscape和IE都支持它。
- WWWAuthenticate:该响应报头域必须被包含在401(未授权的)响应消息中,客户端收到401响应消息时候,并发送Authorization报头域请求服务器对其进行验证时,服务端响应报头就包含该报头域。eg:WWWAuthenticate:Basic realm="Basic Auth Test!" //可以看出服务器对请求资源采用的是基本验证机制。
3.解决HTTP无状态的问题
http是一种无状态的协议。那么我们怎么来解决两次事务直接的记忆问题呢,就出现了chookie 与session两种回话机制
- 通过cookie来保存状态信息:
通过Cookies,服务器就可以清楚的知道请求2和请求1来自同一个客户端
- 通过Session保存状态信息:
Session机制是一种服务器端的机制,服务器使用一种类似于散列表的结构(也可能就是使用散列表)来保存信息。当程序需要为某个客户端的请求创建一个session的时候,服务器首先检查这个客户端的请求里是否已包含了一个session标识 称为 session id,如果已包含一个session id则说明以前已经为此客户端创建过session,服务器就按照session id把这个 session检索出来使用(如果检索不到,可能会新建一个),如果客户端请求不包含session id,则为此客户端创建一个session并且生成一个与此session相关联的session id,session id的值应该是一个既不会重复,又不容易被找到规律以仿造的字符串,这个session id将被在本次响应中返回给客户端保存。
Session的实现方式:
- 1、使用Cookie来实现
服务器给每个Session分配一个唯一的JSESSIONID,并通过Cookie发送给客户端。
当客户端发起新的请求的时候,将在Cookie头中携带这个JSESSIONID。这样服务器能够找到这个客户端对应的Session
- 2、使用URL回写来实现
URL回写是指服务器在发送给浏览器页面的所有链接中都携带JSESSIONID的参数,这样客户端点击任何一个链接都会把JSESSIONID带会服务器。如果直接在浏览器输入服务端资源的url来请求该资源,那么Session是匹配不到的。
Cookie和Session有以下明显的不同点:
- 1)Cookie将状态保存在客户端,Session将状态保存在服务器端;
- 2)Cookies是服务器在本地机器上存储的小段文本并随每一个请求发送至同一个服务器。Cookie最早在RFC2109中实现,后续RFC2965做了增强。网络服务器用HTTP头向客户端发送cookies,在客户终端,浏览器解析这些cookies并将它们保存为一个本地文件,它会自动将同一服务器的任何请求缚上这些cookies。Session并没有在HTTP的协议中定义;
- 3)Session是针对每一个用户的,变量的值保存在服务器上,用一个sessionID来区分是哪个用户session变量,这个值是通过用户的浏览器在访问的时候返回给服务器,当客户禁用cookie时,这个值也可能设置为由get来返回给服务器;
- 4)就安全性来说:当你访问一个使用session 的站点,同时在自己机子上建立一个cookie,建议在服务器端的SESSION机制更安全些。因为它不会任意读取客户存储的信息。
通过表单变量保持状态
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。