Http工作原理(转)

Stella981
• 阅读 349

  HTTP协议(HyperText Transfer Protocol,超文本传输协议)是用于从WWW服务器传输超文本到本地浏览器的传送协议。它可以使浏览器更加高效,使网络传输减少。它不仅保证计算机正确快速地传输超文本文档,还确定传输文档中的哪一部分,以及哪部分内容首先显示(如文本先于图形)等。

         在了解HTTP如何工作之前,我们先了解计算机之间的通信。

2. 计算机相互之间的通信

        互联网的关键技术就是TCP/IP协议。两台计算机之间的通信是通过TCP/IP协议在因特网上进行的。实际上这个是两个协议:

        TCP : Transmission Control Protocol 传输控制协议和IP: Internet Protocol  网际协议。

        IP:计算机之间的通信

        IP协议是计算机用来相互识别的通信的一种机制,每台计算机都有一个IP.用来在internet上标识这台计算机。  IP 负责在因特网上发送和接收数据包。通过 IP,消息(或者其他数据)被分割为小的独立的包,并通过因特网在计算机之间传送。IP 负责将每个包路由至它的目的地。

        IP协议仅仅是允许计算机相互发消息,但它并不检查消息是否以发送的次序到达而且没有损坏(只检查关键的头数据)。为了提供消息检验功能,直接在IP协议上设计了传输控制协议TCP.

       TCP : 应用程序之间的通信

       TCP确保数据包以正确的次序到达,并且尝试确认数据包的内容没有改变。TCP在IP地址之上引端口(port),它允许计算机通过网络提供各种服务。一些端口号为不同的服务保留,而且这些端口号是众所周知。

       服务或者守护进程:在提供服务的机器上,有程序监听特定端口上的通信流。例如大多数电子邮件通信流出现在端口25上,用于wwww的HTTP通信流出现在80端口上。

       当应用程序希望通过 TCP 与另一个应用程序通信时,它会发送一个通信请求。这个请求必须被送到一个确切的地址。在双方“握手”之后,TCP 将在两个应用程序之间建立一个全双工 (full-duplex) 的通信,占用两个计算机之间整个的通信线路。TCP 用于从应用程序到网络的数据传输控制。TCP 负责在数据传送之前将它们分割为 IP 包,然后在它们到达的时候将它们重组。

       TCP/IP 就是TCP 和 IP 两个协议在一起协同工作,有上下层次的关系。

       TCP 负责应用软件(比如你的浏览器)和网络软件之间的通信。IP 负责计算机之间的通信。TCP 负责将数据分割并装入 IP 包,IP 负责将包发送至接收者,传输过程要经IP路由器负责根据通信量、网络中的错误或者其他参数来进行正确地寻址,然后在它们到达的时候重新组合它们。

3. HTTP协议所在的协议层

      HTTP是基于TCP协议之上的。在TCP/IP协议参考模型的各层对应的协议如下图,其中HTTP是应用层的协议。

      Http工作原理(转)

4. HTTP请求响应模型   

       HTTP由请求和响应构成,是一个标准的客户端服务器模型(B/S)。HTTP协议永远都是客户端发起请求,服务器回送响应。见下图:

    Http工作原理(转)

       HTTP是一个无状态的协议。无状态是指客户机(Web浏览器)和服务器之间不需要建立持久的连接,这意味着当一个客户端向服务器端发出请求,然后服务器返回响应(response),连接就被关闭了,在服务器端不保留连接的有关信息.HTTP遵循请求(Request)/应答(Response)模型。客户机(浏览器)向服务器发送请求,服务器处理请求并返回适当的应答。所有HTTP连接都被构造成一套请求和应答。

5. HTTP工作过程      

     一次HTTP操作称为一个事务,其工作整个过程如下:

     1 ) 、地址解析,

     如用客户端浏览器请求这个页面:http://localhost.com:8080/index.htm

     从中分解出协议名、主机名、端口、对象路径等部分,对于我们的这个地址,解析得到的结果如下:
     协议名:http
     主机名:localhost.com
     端口:8080
     对象路径:/index.htm

      在这一步,需要域名系统DNS解析域名localhost.com,得主机的IP地址。

    2)、封装HTTP请求数据包

     把以上部分结合本机自己的信息,封装成一个HTTP请求数据包

     3)封装成TCP包,建立TCP连接(TCP的三次握手)

       在HTTP工作开始之前,客户机(Web浏览器)首先要通过网络与服务器建立连接,该连接是通过TCP来完成的,该协议与IP协议共同构建Internet,即著名的TCP/IP协议族,因此Internet又被称作是TCP/IP网络。HTTP是比TCP更高层次的应用层协议,根据规则,只有低层协议建立之后才能进行更高层协议的连接,因此,首先要建立TCP连接,一般TCP连接的端口号是80。这里是8080端口

     4)客户机发送请求命令

       建立连接后,客户机发送一个请求给服务器,请求方式的格式为:统一资源标识符(URI:Uniform Resource Identifier)、协议版本号,后边是MIME信息包括请求修饰符、客户机信息和可能的内容。

     5)服务器响应

     服务器接到请求后,给予相应的响应信息,其格式为一个状态行,包括信息的协议版本号、一个成功或错误的代码,后边是MIME信息包括服务器信息、实体信息和可能的内容。

        实体消息是服务器向浏览器发送头信息后,它会发送一个空白行来表示头信息的发送到此结束,接着,它就以Content-Type应答头信息所描述的格式发送用户所请求的实际数据

     6)服务器关闭TCP连接

     一般情况下,一旦Web服务器向浏览器发送了请求数据,它就要关闭TCP连接,然后如果浏览器或者服务器在其头信息加入了这行代码

    Connection:keep-alive

   TCP连接在发送后将仍然保持打开状态,于是,浏览器可以继续通过相同的连接发送请求。保持连接节省了为每个请求建立新连接所需的时间,还节约了网络带宽。

6. HTTP协议栈中各层数据流

首先我们看看客户端请求的时候,数据在各层协议的数据组织如下图:

         Http工作原理(转)

            而服务器解析客户机请求就是反向操作的过程,如下图:

           Http工作原理(转)

       客户机发起一次请求的时候:

       客户机会将请求封装成http数据包-->封装成Tcp数据包-->封装成Ip数据包--->封装成数据帧--->硬件将帧数据转换成bit流(二进制数据)-->最后通过物理硬件(网卡芯片)发送到指定地点。

       服务器硬件首先收到bit流....... 然后转换成ip数据包。于是通过ip协议解析Ip数据包,然后又发现里面是tcp数据包,就通过tcp协议解析Tcp数据包,接着发现是http数据包通过http协议再解析http数据包得到数据。

6. HTTPS实现原理    

      HTTPS(全称:Hypertext Transfer Protocol over Secure Socket Layer),是以安全为目标的HTTP通道,简单讲是HTTP的安全版。即HTTP下加入SSL层,HTTPS的安全基础是SSL。其所用的端口号是443。

      SSL:安全套接层,是netscape公司设计的主要用于web的安全传输协议。这种协议在WEB上获得了广泛的应用。通过证书认证来确保客户端和网站服务器之间的通信数据是加密安全的。

      有两种基本的加解密算法类型:

      1)对称加密(symmetric encryption):密钥只有一个,加密解密为同一个密码,且加解密速度快,典型的对称加密算法有DES、AES,RC5,3DES等;

       对称加密主要问题是共享秘钥,除你的计算机(客户端)知道另外一台计算机(服务器)的私钥秘钥,否则无法对通信流进行加密解密。解决这个问题的方案非对称秘钥。

      2)非对称加密:使用两个秘钥:公共秘钥和私有秘钥。私有秘钥由一方密码保存(一般是服务器保存),另一方任何人都可以获得公共秘钥。

      这种密钥成对出现(且根据公钥无法推知私钥,根据私钥也无法推知公钥),加密解密使用不同密钥(公钥加密需要私钥解密),相对对称加密速度较慢,典型的非对称加密算法有RSA、DSA等。

  下面看一下https的通信过程:

        过程大致如下:

        1) SSL客户端通过TCP和服务器建立连接之后(443端口),并且在一般的tcp连接协商(握手)过程中请求证书。

              即客户端发出一个消息给服务器,这个消息里面包含了自己可实现的算法列表和其它一些需要的消息,SSL的服务器端会回应一个数据包,这里面确定了这次通信所需要的算法,然后服务器向客户端返回证书。(证书里面包含了服务器信息:域名。申请证书的公司,公共秘钥)。                 

       2)Client在收到服务器返回的证书后,判断签发这个证书的公共签发机构,并使用这个机构的公共秘钥确认签名是否有效,客户端还会确保证书中列出的域名就是它正在连接的域名。

       3)  如果确认证书有效,那么生成对称秘钥并使用服务器的公共秘钥进行加密。然后发送给服务器,服务器使用它的私钥对它进行解密,这样两台计算机可以开始进行对称加密进行通信。

  https通信的优点:

  1)客户端产生的密钥只有客户端和服务器端能得到;

  2)加密的数据只有客户端和服务器端才能得到明文;

  3)客户端到服务端的通信是安全的。

7. HTTP各种长度限制   

1. URI长度限制

  在Http1.1协议中并没有提出针对URI的长度进行限制,RFC协议里面是这样描述的,HTTP协议并不对URI的长度做任何的限制,服务器端必须能够处理任何它们所提供服务多能接受的URI,并且能够处理无限长度的URI,如果服务器不能处理过长的URI,那么应该返回414状态码。

  虽然Http协议规定了,但是Web服务器和浏览器对URI都有自己的长度限制。

  服务器的限制:我接触的最多的服务器类型就是Nginx和Tomcat,对于url的长度限制,它们都是通过控制http请求头的长度来进行限制的,nginx的配置参数为large_client_header_buffers,tomcat的请求配置参数为maxHttpHeaderSize,都是可以自己去进行设置。

  浏览器的限制:每种浏览器也会对url的长度有所限制,下面是几种常见浏览器的url长度限制:(单位:字符)

  IE : 2803

  Firefox:65536

  Chrome:8182

  Safari:80000

  Opera:190000

  对于get请求,在url的长度限制范围之内,请求的参数个数没有限制。

2. Post数据的长度限制

  Post数据的长度限制与url长度限制类似,也是在Http协议中没有规定长度限制,长度限制可以在服务器端配置最大http请求头长度的方式来实现。

3. Cookie的长度限制

  Cookie的长度限制分这么几个方面来总结。

  (1) 浏览器所允许的每个域下的最大cookie数目,没有去自己测试,从网上找到的资料大概是这么个情况

  IE :原先为20个,后来升级为50个

  Firefox: 50个

  Opera:30个

  Chrome:180个

  Safari:无限制

  当Cookie数超过限制数时浏览器的行为:IE和Opera会采用LRU算法将老的不常使用的Cookie清除掉,Firefox的行为是随机踢出某些Cookie的值。当然无论怎样的策略,还是尽量不要让Cookie数目超过浏览器所允许的范围。

(2) 浏览器所允许的每个Cookie的最大长度

  Firefox和Safari:4079字节

  Opera:4096字节

  IE:4095字节

(3) 服务器中Http请求头长度的限制。Cookie会被附在每次http请求头中传递给服务器,因此还会受到服务器请求头长度的影响。

4. Html5 LocalStorage

Html5提供了本地存储机制来供Web应用在客户端存储数据,尽管这个并不属于Http协议的一部分,但是随着Html5的流行,我们可能需要越来越多使用LocalStorage,甚至当它普及的时候跟它打交道就会同今天我们跟Cookie打交道一样多。

对于LocalStorage的长度限制,同Cookie的限制类似,也是浏览器针对域来限制,只不过cookie限制的是个数,LocalStorage限制的是长度:

Firefox\Chrome\Opera都是允许每个域的最大长度为5MB

但是这次IE比较大方,允许的最大长度是10MB

客户端通过发送 HTTP 请求向服务器请求对资源的访问。 它向服务器传递了一个数据块,也就是请求信息,HTTP 请求由三部分组成:请求行、  请求头和请求正文。

 请求行:请求方法 URI 协议/版本

  请求头(Request Header)

 请求正文

下面是一个HTTP请求的数据:

POST /index.php HTTP/1.1
Host: localhost
User-Agent: Mozilla/5.0 (Windows NT 5.1; rv:10.0.2) Gecko/20100101 Firefox/10.0.2
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
Connection: keep-alive
Referer: http://localhost/
Content-Length:25
Content-Type:application/x-www-form-urlencoded
username=aa&password=1234

1、请求行:请求方法URI协议/版本

 请求的第一行是“方法 URL  协议/版本”,并以 回车换行作为结尾。请求行以空格分隔。格式如下:

POST /index.php HTTP/1.1

以上代码中“GET”代表请求方法,“//ndex.php”表示URI,“HTTP/1.1代表协议和协议的版本。

        根据HTTP标准,HTTP请求可以使用多种请求方法。例如:HTTP1.1支持7种请求方法:GET、POST、HEAD、OPTIONS、PUT、DELETE和TARCE。在Internet应用中,最常用的方法是GET和POST。

         URL完整地指定了要访问的网络资源,通常只要给出相对于服务器的根目录的相对目录即可,因此总是以“/”开头,最后,协议版本声明了通信过程中使用HTTP的版本。   

请求方法

在 HTTP 协议中,HTTP 请求可以使用多种请求方法,这些方法指明了要以何种方式来访问 Request-URI 所标识的资源。HTTP1.1 支持的请求方法如下表所示:

HTTP1.1 中的请求方式:

方法

作用

GET

请求获取由 Request-URI 所标识的资源

POST

请求服务器接收在请求中封装的实体,并将其作为由 Request-Line 中的 Request-URI 所标识的资源的一部分

HEAD

请求获取由 Request-URI 所标识的资源的响应消息报头

PUT

请求服务器存储一个资源,并用 Request-URI 作为其标识符

DELETE

请求服务器删除由 Request-URI 所标识的资源

TRACE

请求服务器回送到的请求信息,主要用于测试或诊断

CONNECT

保留将来使用

OPTIONS

请求查询服务器的性能,或者查询与资源相关的选项和需求

重点介绍 GET、POST 和 HEAD 三个方法:

(1)GET

        GET 方法用于获取由 Request-URI 所标识的资源的信息,常见的形式是:

        GET Request-URI HTTP/1.1
        GET方法是默认的HTTP请求方法,例如当我们通过在浏览器的地址栏中直接输入网址的方式去访问网页的时候,浏览器采用的就是 GET 方法向服务器获取资源。

        我们可以使用GET方法来提交表单数据,用GET方法提交的表单数据只经过了简单的编码,同时它将作为URL的一部分向服务器发送,因此,如果使用GET方法来提交表单数据就存在着安全隐患上。例如:
         Http://localhost/login.php?username=aa&password=1234

        从上面的URL请求中,很容易就可以辩认出表单提交的内容。(?之后的内容)另外由于GET方法提交的数据是作为URL请求的一部分所以提交的数据量不能太大。这是因为浏览器对url的长度有限制

       各种浏览器也会对url的长度有所限制,下面是几种常见浏览器的url长度限制:(单位:字符)

IE : 2803

Firefox:65536

Chrome:8182

Safari:80000

Opera:190000 

(2)POST

          POST方法是GET方法的一个替代方法,它主要是向Web服务器提交表单数据,尤其是大批量的数据。 在请求头信息结束之后的两个回车换行之后(实际是空一行),就是表单提交的数据。如上面提到的post表单数据:

        username=aa&password=1234

        POST方法克服了GET方法的一些缺点。通过POST方法提交表单数据时,数据不是作为URL请求的一部分而是作为标准数据传送给Web服务器,这就克服了GET方法中的信息无法保密和数据量太小的缺点。因此,出于安全的考虑以及对用户隐私的尊重,通常表单提交时采用POST方法。

  从编程的角度来讲,如果用户通过GET方法提交数据,则数据存放在QUERY_STRING环境变量中,而POST方法提交的数据则可以从标准输入流中获取。

 GET与POST方法有以下区别:

      1、  在客户端,Get方式在通过URL提交数据,数据在URL中可以看到;POST方式,数据放在HTTP包的body中。

      2、 GET方式提交的数据大小有限制(因为浏览器对URL的长度有限制),而POST则没有此限制。

      3、安全性问题。正如在(1)中提到,使用 Get 的时候,参数会显示在地址栏上,而 Post 不会。所以,如果这些数据是中文数据而且是非敏感数据,那么使用 get;如果用户输入的数据不是中文字符而且包含敏感数据,那么还是使用 post为好。

      4.、服务器取值方式不一样。GET方式取值,如php可以使用$_GET来取得变量的值,而POST方式通过$_POST来获取变量的值。

(3)HEAD

     HEAD 方法与 GET 方法几乎是相同的,它们的区别在于 HEAD 方法只是请求消息报头,而不是完整的内容。对于 HEAD 请求的回应部分来说,它的 HTTP 头部中包含的信息与通过 GET 请求所得到的信息是相同的。利用这个方法,不必传输整个资源内容,就可以得到 Request-URI 所标识的资源的信息。这个方法通常被用于测试超链接的有效性,是否可以访问,以及最近是否更新。

    要注意的是,在 HTML 文档中,书写 get 和 post,大小写都可以,但在 HTTP 协议中的 GET 和 POST 只能是大写形式。

2. 请求头

每个头域由一个域名,冒号(:)和域值三部分组成。域名是大小写无关的,域值前可以添加任何数量的空格符,头域可以被扩展为多行,在每行开始处,使用至少一个空格或制表符。

HTTP最常见的请求头如下:

Transport 头域

Connection:

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

如果服务器看到这里的值为“Keep-Alive”,或者看到请求使用的是HTTP 1.1(HTTP 1.1默认进行持久连接),它就可以利用持久连接的优点,当页面包含多个元素时(例如Applet,图片),显著地减少下载所需要的时间。要实现这一点,服务器需要在应答中发送一个Content-Length头,最简单的实现方法是:先把内容写入 ByteArrayOutputStream,然后在正式写出内容之前计算它的大小;

例如: Connection: keep-alive   当一个网页打开完成后,客户端和服务器之间用于传输HTTP数据的TCP连接不会关闭,如果客户端再次访问这个服务器上的  网页,会继续使用这一条已经建立的连接

例如:  Connection: close  代表一个Request完成后,客户端和服务器之间用于传输HTTP数据的TCP连接会关闭,  当客户端再次发送Request,需要重新建立TCP连接。

Host(发送请求时,该报头域是必需的)

Host请求报头域主要用于指定被请求资源的Internet主机和端口号,它通常从HTTP URL中提取出来的。

eg:http://;localhost/index.html
浏览器发送的请求消息中,就会包含Host请求报头域,如下:
Host:localhost

此处使用缺省端口号80,若指定了端口号8080,则变成:Host:localhost:8080

Client 头域

Accept:

作用:浏览器可以接受的媒体类型(MIME类型),

例如:  Accept: text/html  代表浏览器可以接受服务器回发的类型为 text/html  也就是我们常说的html文档, 如果服务器无法返回text/html类型的数据,服务器应该返回一个406错误(non acceptable)。

通配符 * 代表任意类型。例如  Accept: */*  代表浏览器可以处理所有类型,(一般浏览器发给服务器都是发这个)

Accept-Encoding:

作用: 浏览器申明自己接收的编码方法,通常指定压缩方法,是否支持压缩,支持什么压缩方法(gzip,deflate),(注意:这不是只字符编码);

例如: Accept-Encoding: gzip, deflate。Server能够向支持gzip/deflate的浏览器返回经gzip或者deflate编码的HTML页面。 许多情形下这可以减少5到10倍的下载时间,也节省带宽。

Accept-Language:

作用: 浏览器申明自己接收的语言。 

语言跟字符集的区别:中文是语言,中文有多种字符集,比如big5,gb2312,gbk等等;

例如: Accept-Language:zh-cn 。如果请求消息中没有设置这个报头域,服务器假定客户端对各种语言都可以接受。

User-Agent:

作用:告诉HTTP服务器, 客户端使用的操作系统和浏览器的名称和版本.

我们上网登陆论坛的时候,往往会看到一些欢迎信息,其中列出了你的操作系统的名称和版本,你所使用的浏览器的名称和版本,这往往让很多人感到很神奇,实际上, 服务器应用程序就是从User-Agent这个请求报头域中获取到这些信息User-Agent请求报头域允许客户端将它的操作系统、浏览器和其它属性告诉服务器。

例如: User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; CIBA; .NET CLR 2.0.50727; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; .NET4.0C; InfoPath.2; .NET4.0E)

Accept-Charset:

作用:浏览器申明自己接收的字符集,这就是本文前面介绍的各种字符集和字符编码,如gb2312,utf-8(通常我们说Charset包括了相应的字符编码方案);

例如:Accept-Charset:iso-8859-1,gb2312.如果在请求消息中没有设置这个域,缺省是任何字符集都可以接受。

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

Authorization请求报头域主要用于证明客户端有权查看某个资源。当浏览器访问一个页面时,如果收到服务器的响应代码为401(未授权),可以发送一个包含Authorization请求报头域的请求,要求服务器对其进行验证。

Cookie/Login 头域

Cookie:

作用: 最重要的header, 将cookie的值发送给HTTP 服务器

Entity头域

Content-Length

作用:发送给HTTP服务器数据的长度。即请求消息正文的长度;

例如: Content-Length: 38

Content-Type:

作用:

例如:Content-Type: application/x-www-form-urlencoded

Miscellaneous 头域

Referer:

作用: 提供了Request的上下文信息的服务器,告诉服务器我是从哪个链接过来的,比如从我主页上链接到一个朋友那里, 他的服务器就能够从HTTP Referer中统计出每天有多少用户点击我主页上的链接访问    他的网站。

例如: Referer:http://translate.google.cn/?hl=zh-cn&tab=wT

Cache 头域

If-Modified-Since:

作用: 把浏览器端缓存页面的最后修改时间发送到服务器去,服务器会把这个时间与服务器上实际文件的最后修改时间进行对比。如果时间一致,那么返回304,客户端就直接使用本地缓存文件。如果时间不一致,就会返回200和新的文件内容。客户端接到之后,会丢弃旧文件,把新文件缓存起来,并显示在浏览器中。

例如:If-Modified-Since: Thu, 09 Feb 2012 09:07:57 GMT。

If-None-Match:

作用: If-None-Match和ETag一起工作,工作原理是在HTTP Response中添加ETag信息。 当用户再次请求该资源时,将在HTTP Request 中加入If-None-Match信息(ETag的值)。如果服务器验证资源的ETag没有改变(该资源没有更新),将返回一个304状态告诉客户端使用本地缓存文件。否则将返回200状态和新的资源和Etag.  使用这样的机制将提高网站的性能

例如: If-None-Match: "03f2b33c0bfcc1:0"

Pragma:

作用: 防止页面被缓存, 在HTTP/1.1版本中,它和Cache-Control:no-cache作用一模一样

Pargma只有一个用法, 例如: Pragma: no-cache

注意: 在HTTP/1.0版本中,只实现了Pragema:no-cache, 没有实现Cache-Control

Cache-Control:

作用: 这个是非常重要的规则。 这个用来指定Response-Request遵循的缓存机制。各个指令含义如下

Cache-Control:Public   可以被任何缓存所缓存()

Cache-Control:Private     内容只缓存到私有缓存中

Cache-Control:no-cache  所有内容都不会被缓存

2. HTTP响应格式      

      在接收和解释请求消息后,服务器会返回一个 HTTP 响应消息。与 HTTP 请求类似,HTTP 响应也是由三个部分组成,分别是:状态行、消息报头和响应正文。如:

HTTP/1.1 200 OK Date: Sun, 17 Mar 2013 08:12:54 GMT Server: Apache/2.2.8 (Win32) PHP/5.2.5 X-Powered-By: PHP/5.2.5 Set-Cookie: PHPSESSID=c0huq7pdkmm5gg6osoe3mgjmm3; path=/ Expires: Thu, 19 Nov 1981 08:52:00 GMT Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0 Pragma: no-cache Content-Length: 4393 Keep-Alive: timeout=5, max=100 Connection: Keep-Alive Content-Type: text/html; charset=utf-8

HTTP响应示例<title> </head> <body> Hello HTTP! </body> </html> <h3 id="1、状态行">1、状态行</h3> <p>       状态行由协议版本、数字形式的状态代码,及相应的状态描述组成,各元素之间以空格分隔,结尾时回车换行符,格式如下:</p> <p>HTTP-Version Status-Code Reason-Phrase CRLF</p> <p>HTTP-Version 表示服务器 HTTP 协议的版本,Status-Code 表示服务器发回的响应代码,Reason-Phrase 表示状态代码的文本描述,CRLF 表示回车换行。例如:</p> <p>HTTP/1.1 200 OK (CRLF)</p> <p>      状态代码与状态描述</p> <p>      状态代码由 3 位数字组成, 表示请求是否被理解或被满足,状态描述给出了关于状态码的简短的文字描述。状态码的第一个数字定义了响应类别,后面两位数字没有具体分类。第一个数字有 5 种取值,如下所示。</p> <ul> <li>1xx:指示信息——表示请求已经接受,继续处理</li> <li>2xx:成功——表示请求已经被成功接收、理解、接受。</li> <li>3xx:重定向——要完成请求必须进行更进一步的操作</li> <li>4xx:客户端错误——客户端请求有错误或请求无法实现</li> <li>5xx:服务器端错误——服务器未能实现合法的请求。</li> </ul> <p>常见状态代码、状态描述、说明:<br>200 OK      //客户端请求成功</p> <p>303:重定向,即从原url重定向到新的url。 例如php 的hear函数header("localtion:/index.php")</p> <p>400 Bad Request  //客户端请求有语法错误,不能被服务器所理解<br>401 Unauthorized //请求未经授权,这个状态代码必须和WWW-Authenticate报头域一起使用 <br>403 Forbidden  //服务器收到请求,但是拒绝提供服务,一般是服务器路径没有权限或者是其他权限相关问题<br>404 Not Found  //请求资源不存在,eg:输入了错误的URL<br>500 Internal Server Error //服务器发生不可预期的错误:一般来说,这个问题都会在服务器端的源代码出现错误时出现,比如出现死循环。</p> <p>502 Bad Gateway//作为网关或者代理工作的服务器尝试执行请求时,从上游服务器接收到无效的响应。比如LNMP ,php-fpm没有启动就会报502错误。</p> <p>503 Server Unavailable  //服务器当前不能处理客户端的请求,一段时间后可能恢复正常,比如java 容器部署war的时候,就出现503, <br>                                           或者是nginx处理的文件没有权限。</p> <p>504 Gateway Time-out:作为网关或者代理工作的服务器尝试执行请求时,未能及时从上游服务器(URI标识出的服务器,例如HTTP、FTP、LDAP)或者辅助服务器(例如DNS)收到响应,比如nginx和php-fpm, php设置sleep(200),就会收到504 Gateway Time-out。注意:某些代理服务器在DNS查询超时时会返回400或者500错误</p> <h3 id="2、响应正文">2、响应正文</h3> <p>响应正文就是服务器返回的资源的内容,响应头和正文之间也必须用空行分隔。如:</p> <p><strong>[html]</strong>  <a href="https://www.helloworld.net/redirect?target=https://www.oschina.net/action/GoToLink?url=https://blog.csdn.net/hguisu/article/details/8683290#" rel="nofollow noopener noreferrer" target="_blank">view plain</a> <a href="https://www.helloworld.net/redirect?target=https://www.oschina.net/action/GoToLink?url=https://blog.csdn.net/hguisu/article/details/8683290#" rel="nofollow noopener noreferrer" target="_blank">copy</a></p> <ol> <li><html> </li> <li><head> </li> <li><title>HTTP响应示例<title> </li> <li></head> </li> <li><body> </li> <li>Hello HTTP!  </li> <li></body> </li> <li></html></li> </ol> <h3 id="3-、响应头信息">3 、响应头信息</h3> <p>HTTP最常见的响应头如下所示:</p> <h4 id="cache头域">Cache头域</h4> <blockquote> <p>Date:</p> <p>作用:生成消息的具体时间和日期,即当前的GMT时间。</p> <p>例如: Date: Sun, 17 Mar 2013 08:12:54 GMT</p> <p>Expires:</p> <p>作用: 浏览器会在指定过期时间内使用本地缓存,指明应该在什么时候认为文档已经过期,从而不再缓存它。</p> <p>例如: Expires: Thu, 19 Nov 1981 08:52:00 GMT  </p> <p>Vary</p> <p>作用:</p> <p>例如: Vary: Accept-Encoding</p> </blockquote> <h4 id="cookielogin-头域-1">Cookie/Login 头域</h4> <blockquote> <p>P3P</p> <p>作用: 用于跨域设置Cookie, 这样可以解决iframe跨域访问cookie的问题</p> <p>例如: P3P: CP=CURa ADMa DEVa PSAo PSDo OUR BUS UNI PUR INT DEM STA PRE COM NAV OTC NOI DSP COR</p> <p>Set-Cookie</p> <p>作用: 非常重要的header, 用于把cookie 发送到客户端浏览器, 每一个写入cookie都会生成一个Set-Cookie.</p> <p>例如: Set-Cookie: PHPSESSID=c0huq7pdkmm5gg6osoe3mgjmm3; path=/</p> </blockquote> <h4 id="entity实体头域:">Entity实体头域:</h4> <p>            实体内容的属性,包括实体信息类型,长度,压缩方法,最后一次修改时间,数据有效性等。</p> <blockquote> <p>ETag:</p> <p>作用:  和If-None-Match 配合使用。 (实例请看上节中If-None-Match的实例)</p> <p>例如: ETag: "03f2b33c0bfcc1:0"</p> <p>Last-Modified:</p> <p>作用: 用于指示资源的最后修改日期和时间。(实例请看上节的If-Modified-Since的实例)</p> <p>例如: Last-Modified: Wed, 21 Dec 2011 09:09:10 GMT</p> <p>Content-Type:</p> <p>作用:WEB服务器告诉浏览器自己响应的对象的类型和字符集,</p> <p>例如:</p> <p>        Content-Type: text/html; charset=utf-8</p> <p>  Content-Type:text/html;charset=GB2312</p> <p>  Content-Type: image/jpeg</p> <p>Content-Length:</p> <p>指明实体正文的长度,以字节方式存储的十进制数字来表示。在数据下行的过程中,Content-Length的方式要预先在服务器中缓存所有数据,然后所有数据再一股脑儿地发给客户端。</p> <p>  例如: Content-Length: 19847</p> <p>Content-Encoding:</p> <p>作用:文档的编码(Encode)方法。一般是压缩方式。</p> <p>WEB服务器表明自己使用了什么压缩方法(gzip,deflate)压缩响应中的对象。利用gzip压缩文档能够显著地减少HTML文档的下载时间。</p> <p>例如:Content-Encoding:gzip</p> <p>Content-Language:</p> <p>作用: WEB服务器告诉浏览器自己响应的对象的语言者</p> <p>例如: Content-Language:da</p> </blockquote> <h4 id="miscellaneous-头域-1">Miscellaneous 头域</h4> <blockquote> <p>Server:</p> <p>作用:指明HTTP服务器的软件信息</p> <p>例如:Apache/2.2.8 (Win32) PHP/5.2.5</p> <p>X-Powered-By:</p> <p>作用:表示网站是用什么技术开发的</p> <p>例如: X-Powered-By: PHP/5.2.5</p> </blockquote> <h4 id="transport头域">Transport头域</h4> <blockquote> <p>Connection:</p> <p>例如: Connection: keep-alive   当一个网页打开完成后,客户端和服务器之间用于传输HTTP数据的TCP连接不会关闭,如果客户端再次访问这个服务器上的网页,会继续使用这一条已经建立的连接</p> <p>例如:  Connection: close  代表一个Request完成后,客户端和服务器之间用于传输HTTP数据的TCP连接会关闭, 当客户端再次发送Request,需要重新建立TCP连接。</p> </blockquote> <h4 id="location头域">Location头域</h4> <blockquote> <p>Location:</p> <p>作用: 用于重定向一个新的位置, 包含新的URL地址</p> <p>实例请看304状态实例</p> </blockquote> <h3 id="http协议是无状态的和connection-keep-alive的区别">HTTP协议是无状态的和Connection: keep-alive的区别</h3> <p>  无状态是指协议对于事务处理没有记忆能力,服务器不知道客户端是什么状态。从另一方面讲,打开一个服务器上的网页和你之前打开这个服务器上的网页之间没有任何联系。</p> <p>  HTTP是一个无状态的面向连接的协议,无状态不代表HTTP不能保持TCP连接,更不能代表HTTP使用的是UDP协议(无连接)。</p> <p>  从HTTP/1.1起,默认都开启了Keep-Alive,保持连接特性,简单地说,当一个网页打开完成后,客户端和服务器之间用于传输HTTP数据的TCP连接不会关闭,如果客户端再次访问这个服务器上的网页,会继续使用这一条已经建立的连接。</p> <p>  Keep-Alive不会永久保持连接,它有一个保持时间,可以在不同的服务器软件(如Apache)中设定这个时间。</p> <h2 id="3-浏览器缓存">3. 浏览器缓存      </h2> <p>       浏览器缓存:包括页面html缓存和图片js,css等资源的缓存。如下图,浏览器缓存是基于把页面信息保存到用户本地电脑硬盘里。</p> <h3 id="1、缓存的优点:">1、缓存的优点:</h3> <p>     1)服务器响应更快:因为请求从缓存服务器(离客户端更近)而不是源服务器被相应,这个过程耗时更少,让服务器看上去响应更快。</p> <p>     2)减少网络带宽消耗:当副本被重用时会减低客户端的带宽消耗;客户可以节省带宽费用,控制带宽的需求的增长并更易于管理。</p> <h3 id="1、缓存工作原理">1、缓存工作原理</h3> <p>       页面缓存状态是由http header决定的,一个浏览器请求信息,一个是服务器响应信息。主要包括Pragma: no-cache、Cache-Control、 Expires、 Last-Modified、If-Modified-Since。其中Pragma: no-cache由HTTP/1.0规定,Cache-Control由HTTP/1.1规定。</p> <p>       工作原理图:</p> <p><img src="http://img.my.csdn.net/uploads/201303/17/1363512757_1013.png" alt="Http工作原理(转) " /></p> <p>从图中我们可以看到原理主要分三步:</p> <ol> <li>第一次请求:浏览器通过http的header报头,附带Expires,Cache-Control,Last-Modified/Etag向服务器请求,此时服务器记录第一次请求的Last-Modified/Etag                  </li> <li>再次请求:当浏览器再次请求的时候,请求头附带Expires,Cache-Control,If-Modified-Since/Etag向服务器请求</li> <li>服务器根据第一次记录的Last-Modified/Etag和再次请求的If-Modified-Since/Etag做对比,判断是否需要更新,服务器通过这两个头判断本地资源未发生变化,客 户端不需要重新下载,返回304响应。常见流程如下图所示:</li> </ol> <p><img src="http://img.my.csdn.net/uploads/201303/19/1363670410_3844.jpg" alt="Http工作原理(转) " /></p> <h3 id="与缓存相关的http扩展消息头">与缓存相关的HTTP扩展消息头</h3> <p>    Expires:设置页面过期时间,格林威治时间GMT</p> <p>    Cache-Control:更细致的控制缓存的内容</p> <p>    Last-Modified:请求对象最后一次的修改时间 用来判断缓存是否过期 通常由文件的时间信息产生 </p> <p>    ETag:响应中资源的校验值,在服务器上某个时段是唯一标识的。ETag是一个可以 与Web资源关联的记号(token),和Last-Modified功能才不多,也是一个标识符,一般和Last-Modified一起使用,加强服务器判断的准确度。</p> <p>    Date:服务器的时间</p> <p>    If-Modified-Since:客户端存取的该资源最后一次修改的时间,用来和服务器端的Last-Modified做比较</p> <p>    If-None-Match:客户端存取的该资源的检验值,同ETag。</p> <p>Cache-Control的主要参数 <br>      Cache-Control: private/public Public 响应会被缓存,并且在多用户间共享。 Private 响应只能够作为私有的缓存,不能再用户间共享。<br>      Cache-Control: no-cache:不进行缓存 <br>      Cache-Control: max-age=x:缓存时间 以秒为单位 <br>      Cache-Control: must-revalidate:如果页面是过期的 则去服务器进行获取。</p> <p>我们nginx测试:</p> <p>server {<br>        listen       8081;<br>        server_name  10.163.1.175;<br>        if ($host != '<a href="https://www.helloworld.net/redirect?target=http://www.test1.com'" rel="nofollow noopener noreferrer" target="_blank">www.test1.com'</a> ) {<br>            #rewrite ^/(.*)$ <a href="https://www.helloworld.net/redirect?target=http://www.test1.com/$1" rel="nofollow noopener noreferrer" target="_blank">http://www.test1.com/$1</a> permanent;<br>        }<br>        index index.html index.htm index.php;<br>        root  /home/www/app/;<br>        access_log  /mnt/app/nginx/logs/test1.home.log  main;<br>        location ~ .*\.zip?$<br>        {<br>               access_log off;<br>        }<br>        location ~ .*\.txt?$ {<br>                access_log off;<br>        }<br>        location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$<br>        {<br>                expires      30d;<br>        }<br>        location ~ .*\.(js|css|zip)?$<br>        {<br>                expires      12h;<br>        }<br>        if (!-e $request_filename) {<br>            rewrite ^/(.+)$ /index.php?url=$1 last;<br>            break;<br>        } </p> <p>        location ~ .*\.(php|php5)?$<br>        {<br>                #fastcgi_pass  unix:/tmp/php-cgi.sock;<br>                fastcgi_pass 127.0.0.1:9000;<br>                fastcgi_index index.php;<br>                include fastcgi.conf;<br>                add_header Content-Type text/html;<br>        }<br>}</p> <p>然后我们代理两个域名指向同一个端口:</p> <p>server {<br>    listen  80;<br>    server_name   <a href="https://www.helloworld.net/redirect?target=http://www.test1.com" rel="nofollow noopener noreferrer" target="_blank">www.test1.com</a>  test1.com; </p> <p>    location / {<br>        proxy_pass         <a href="https://www.helloworld.net/redirect?target=http://127.0.0.1:8081" rel="nofollow noopener noreferrer" target="_blank">http://127.0.0.1:8081</a>;<br>        proxy_set_header   Host             $host;<br>        proxy_set_header   X-Real-IP        $remote_addr;<br>        proxy_set_header   X-Forward-For    $proxy_add_x_forwarded_for;<br>        proxy_set_header Access-Control-Allow-Origin *;<br>        proxy_next_upstream http_502 http_504 error timeout invalid_header;<br>    }<br>}<br>server {<br>    listen  80;<br>    server_name   <a href="https://www.helloworld.net/redirect?target=http://www.test2.com" rel="nofollow noopener noreferrer" target="_blank">www.test2.com</a>  test2.com;<br>    location / {<br>        proxy_pass         <a href="https://www.helloworld.net/redirect?target=http://127.0.0.1:8081" rel="nofollow noopener noreferrer" target="_blank">http://127.0.0.1:8081</a>;<br>        proxy_set_header   Host             $host;<br>        proxy_set_header   X-Real-IP        $remote_addr;<br>        proxy_set_header   X-Forward-For    $proxy_add_x_forwarded_for;<br>        proxy_set_header Access-Control-Allow-Origin *;<br>        proxy_next_upstream http_502 http_504 error timeout invalid_header;<br>    }<br>}</p> <p>我们访问<a href="https://www.helloworld.net/redirect?target=http://www.test2.com,直接指向www.test1.com,http是304响应。" rel="nofollow noopener noreferrer" target="_blank">www.test2.com,直接指向www.test1.com,http是304响应。</a></p> <p>当我们把8081端口的配置去掉</p> <p>        if ($host != '<a href="https://www.helloworld.net/redirect?target=http://www.test1.com'" rel="nofollow noopener noreferrer" target="_blank">www.test1.com'</a> ) {<br>            #rewrite ^/(.*)$ <a href="https://www.helloworld.net/redirect?target=http://www.test1.com/$1" rel="nofollow noopener noreferrer" target="_blank">http://www.test1.com/$1</a> permanent;<br>        }<br>   重启nginx,同一个访问<a href="https://www.helloworld.net/redirect?target=http://www.test2.com,发现还是直接跳转到www.test1.com。" rel="nofollow noopener noreferrer" target="_blank">www.test2.com,发现还是直接跳转到www.test1.com。</a></p> <p>这是因为浏览器304缓存的问题。我们直接使用新浏览器访问,就直接访问就不会跳转啦。</p> <h3 id="2、关于图片,css,js,flash的缓存">2、关于图片,css,js,flash的缓存</h3> <p>这个主要通过服务器的配置来实现这个技术,如果使用apache服务器的话,可以使用mod_expires模块来实现:</p> <p>编译mod_expires模块:</p> <p>Cd  /root/httpd-2.2.3/modules/metadata</p> <p>/usr/local/apache/bin/apxs -i -a -c mod_expires.c //编译</p> <p>编辑httpd.conf配置:添加下面内容</p> <p><IfModule mod_expires.c></p> <p>ExpiresActive on</p> <p>ExpiresDefault "access plus 1 month"</p> <p>ExpiresByType text/html "access plus 1 months"</p> <p>ExpiresByType text/css "access plus 1 months"</p> <p>ExpiresByType image/gif "access plus 1 months"</p> <p>ExpiresByType image/jpeg "access plus 1 months"</p> <p>ExpiresByType image/jpg "access plus 1 months"</p> <p>ExpiresByType image/png "access plus 1 months"</p> <p>EXpiresByType application/x-shockwave-flash "access plus 1 months"</p> <p>EXpiresByType application/x-javascript      "access plus 1 months"</p> <p>#ExpiresByType video/x-flv "access plus 1 months"</p> </IfModule> <p>解释:第一句--开启服务</p> <p>第二句--默认时间是一个月</p> <p>在下面是关于各种类型的资源的缓存时间设置</p> </div> </article> <div class="tags-box" data-v-1bdff09d><a href="/tag/tcp.html" target="_blank" class="item" data-v-1bdff09d>tcp</a><a href="/tag/%E7%BC%93%E5%AD%98%E6%9C%8D%E5%8A%A1%E5%99%A8.html" target="_blank" class="item" data-v-1bdff09d>缓存服务器</a><a href="/tag/%E6%9C%8D%E5%8A%A1%E5%99%A8%E7%B1%BB%E5%9E%8B.html" target="_blank" class="item" data-v-1bdff09d>服务器类型</a><a href="/tag/%E7%94%B5%E8%84%91%E6%9C%8D%E5%8A%A1%E5%99%A8.html" target="_blank" class="item" data-v-1bdff09d>电脑服务器</a><a href="/tag/post%E8%AF%B7%E6%B1%82.html" target="_blank" class="item" data-v-1bdff09d>post请求</a><a href="/tag/%E6%B5%8F%E8%A7%88%E5%99%A8%E7%BC%93%E5%AD%98.html" target="_blank" class="item" data-v-1bdff09d>浏览器缓存</a><a href="/tag/html%E8%AF%AD%E8%A8%80.html" target="_blank" class="item" data-v-1bdff09d>html语言</a><a href="/tag/cookie.html" target="_blank" class="item" data-v-1bdff09d>cookie</a><a href="/tag/%E4%B8%89%E6%AC%A1%E6%8F%A1%E6%89%8B.html" target="_blank" class="item" data-v-1bdff09d>三次握手</a><a href="/tag/%E9%80%9A%E4%BF%A1.html" target="_blank" class="item" data-v-1bdff09d>通信</a><a href="/tag/keep-alive.html" target="_blank" class="item" data-v-1bdff09d>keep-alive</a><a href="/tag/http%E5%8D%8F%E8%AE%AE.html" target="_blank" class="item" data-v-1bdff09d>http协议</a><a href="/tag/http%E8%AF%B7%E6%B1%82.html" target="_blank" class="item" data-v-1bdff09d>http请求</a><a href="/tag/cache-control.html" target="_blank" class="item" data-v-1bdff09d>cache-control</a><a href="/tag/%E5%89%8D%E7%AB%AF.html" target="_blank" class="item" data-v-1bdff09d>前端</a><a href="/tag/%E5%89%8D%E7%AB%AF.html" target="_blank" class="item" data-v-1bdff09d>前端</a></div> <div class="blog-btns-box" data-v-7d5edd21><div class="btn-item" data-v-7d5edd21><div class="circle zan" data-v-7d5edd21><IconFont type="icon-Dianzan" class="iconfont" data-v-7d5edd21></IconFont></div> <div class="text" data-v-7d5edd21>点赞</div></div> <div class="btn-item" data-v-7d5edd21><div class="circle favorite" data-v-7d5edd21><IconFont type="icon-Like1" class="iconfont" data-v-7d5edd21></IconFont></div> <div class="text" data-v-7d5edd21>收藏</div></div></div></div> <div id="recommend-lesson"><div class="recommend-lesson-title">推荐课程</div> <div class="horizontal" data-v-ba84c88a><a target="_blank" href="/lesson/detail/1935098869" class="re-course-list" data-v-ba84c88a><img src="https://img-hello-world.oss-cn-beijing.aliyuncs.com/imgs/b198ef1a1d11a9c6e81531134cc3327a.png" alt="avatar" data-v-ba84c88a> <div class="re-info" data-v-ba84c88a><h2 data-v-ba84c88a>Java synchronized同步关键字背后的原理与源码实现 </h2> <div class="des" data-v-ba84c88a><div style="display: flex; align-items: center" data-v-ba84c88a><div class="price-icon" data-v-ba84c88a>¥</div> <div class="price" data-v-ba84c88a> 109.00 </div></div> <span data-v-ba84c88a>56人学习</span></div></div></a><a target="_blank" href="/lesson/detail/6955961602" class="re-course-list" data-v-ba84c88a><img src="https://img-hello-world.oss-cn-beijing.aliyuncs.com/imgs/2847450d82190c8a7d0ae4ba8a8e5629.png" alt="avatar" data-v-ba84c88a> <div class="re-info" data-v-ba84c88a><h2 data-v-ba84c88a>Android进阶之旅-(Framework源码分析)</h2> <div class="des" data-v-ba84c88a><div class="price" data-v-ba84c88a>免费</div> <span data-v-ba84c88a>26人学习</span></div></div></a></div></div> <div id="anchor" class="comment-container"><div id="comment-panel" class="comment-panel" data-v-25426b80><div class="panel-title" data-v-25426b80>评论区</div> <div class="comment-input-box" data-v-25426b80><img src="/_nuxt/img/default-avatar.38df358.png" alt class="user-avatar" data-v-25426b80> <!----></div> <!----></div></div> <div class="recommend-blog-list"><div class="recommend-title">推荐文章</div> <div class="art-list" data-v-6293c55f><div class="blog-item" data-v-6293c55f><div class="blog-header" data-v-6293c55f><img src="https://img-hello-world.oss-cn-beijing.aliyuncs.com/imgs/cd34cdaab69ede1e2bf28de235151c34.webp" alt="blmius" class="img" data-v-6293c55f> <a href="/blmius" target="_blank" class="name" data-v-6293c55f> blmius </a> <div class="dot" data-v-6293c55f>•</div> <div class="time" data-v-6293c55f> 2年前 </div></div> <div class="blog-content" data-v-6293c55f><div class="item-left" data-v-6293c55f><a href="/p/2802547579" target="_blank" title="MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1" class="title single-ellipsis" data-v-6293c55f> MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1 </a> <div class="intro multi-ellipsis-2" data-v-6293c55f> 文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s </div></div> <img src="https://img-hello-world.oss-cn-beijing.aliyuncs.com/ed6c6174f1775f65a3fbe98488391419.png" class="item-right" data-v-6293c55f></div> <!----> <div class="blog-footer flex" data-v-6293c55f><div class="iconfont footer-item icon-Show1" data-v-6293c55f><span class="num" data-v-6293c55f>3498</span></div><div class="iconfont footer-item icon-Guanbi1-copy" data-v-6293c55f><span class="num" data-v-6293c55f>0</span></div><div class="iconfont footer-item icon-Pinglun1" data-v-6293c55f><span class="num" data-v-6293c55f>0</span></div></div></div><div class="blog-item" data-v-6293c55f><div class="blog-header" data-v-6293c55f><img src="https://img-hello-world.oss-cn-beijing.aliyuncs.com/imgs/d4566ad9edfb956dba92fc21f5e1561f.webp" alt="Jacquelyn38" class="img" data-v-6293c55f> <a href="/Jacquelyn38" target="_blank" class="name" data-v-6293c55f> Jacquelyn38 </a> <div class="dot" data-v-6293c55f>•</div> <div class="time" data-v-6293c55f> 2年前 </div></div> <div class="blog-content" data-v-6293c55f><div class="item-left" data-v-6293c55f><a href="/p/3468005401" target="_blank" title="2020年前端实用代码段,为你的工作保驾护航" class="title single-ellipsis" data-v-6293c55f> 2020年前端实用代码段,为你的工作保驾护航 </a> <div class="intro multi-ellipsis-2" data-v-6293c55f> 有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number ) </div></div> <img src="https://img-hello-world.oss-cn-beijing.aliyuncs.com/e7130dfd1edf85ccee4a9e73aa0b77dd.jpeg" class="item-right" data-v-6293c55f></div> <!----> <div class="blog-footer flex" data-v-6293c55f><div class="iconfont footer-item icon-Show1" data-v-6293c55f><span class="num" data-v-6293c55f>1984</span></div><div class="iconfont footer-item icon-Guanbi1-copy" data-v-6293c55f><span class="num" data-v-6293c55f>0</span></div><div class="iconfont footer-item icon-Pinglun1" data-v-6293c55f><span class="num" data-v-6293c55f>0</span></div></div></div><div class="blog-item" data-v-6293c55f><div class="blog-header" data-v-6293c55f><img src="https://img-hello-world.oss-cn-beijing.aliyuncs.com/imgs/0d250ec5492da88592013bbd302402ae.jfif" alt="helloworld_34035044" class="img" data-v-6293c55f> <a href="/34035044" target="_blank" class="name" data-v-6293c55f> helloworld_34035044 </a> <div class="dot" data-v-6293c55f>•</div> <div class="time" data-v-6293c55f> 1年前 </div></div> <div class="blog-content" data-v-6293c55f><div class="item-left" data-v-6293c55f><a href="/p/9382788506" target="_blank" title="皕杰报表之UUID" class="title single-ellipsis" data-v-6293c55f> 皕杰报表之UUID </a> <div class="intro multi-ellipsis-2" data-v-6293c55f> ​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为 </div></div> <!----></div> <!----> <div class="blog-footer flex" data-v-6293c55f><div class="iconfont footer-item icon-Show1" data-v-6293c55f><span class="num" data-v-6293c55f>777</span></div><div class="iconfont footer-item icon-Guanbi1-copy" data-v-6293c55f><span class="num" data-v-6293c55f>0</span></div><div class="iconfont footer-item icon-Pinglun1" data-v-6293c55f><span class="num" data-v-6293c55f>0</span></div></div></div><div class="blog-item" data-v-6293c55f><div class="blog-header" data-v-6293c55f><img src="https://img-hello-world.oss-cn-beijing.aliyuncs.com/imgs/1bad3e5246214111b0d7a482fc5beec5.jfif" alt="Stella981" class="img" data-v-6293c55f> <a href="/Stella981" target="_blank" class="name" data-v-6293c55f> Stella981 </a> <div class="dot" data-v-6293c55f>•</div> <div class="time" data-v-6293c55f> 2年前 </div></div> <div class="blog-content" data-v-6293c55f><div class="item-left" data-v-6293c55f><a href="/p/1127166003" target="_blank" title="AndroidStudio封装SDK的那些事 " class="title single-ellipsis" data-v-6293c55f> AndroidStudio封装SDK的那些事 </a> <div class="intro multi-ellipsis-2" data-v-6293c55f> <divclass"markdown\_views"<!flowchart箭头图标勿删<svgxmlns"http://www.w3.org/2000/svg"style"display:none;"<pathstrokelinecap"round"d"M5,00,2.55,5z"id"raphael </div></div> <!----></div> <!----> <div class="blog-footer flex" data-v-6293c55f><div class="iconfont footer-item icon-Show1" data-v-6293c55f><span class="num" data-v-6293c55f>897</span></div><div class="iconfont footer-item icon-Guanbi1-copy" data-v-6293c55f><span class="num" data-v-6293c55f>0</span></div><div class="iconfont footer-item icon-Pinglun1" data-v-6293c55f><span class="num" data-v-6293c55f>0</span></div></div></div><div class="blog-item" data-v-6293c55f><div class="blog-header" data-v-6293c55f><img src="https://img-hello-world.oss-cn-beijing.aliyuncs.com/imgs/46847d754406b0102dee7a1f54d14f92.jfif" alt="Wesley13" class="img" data-v-6293c55f> <a href="/Wesley13" target="_blank" class="name" data-v-6293c55f> Wesley13 </a> <div class="dot" data-v-6293c55f>•</div> <div class="time" data-v-6293c55f> 2年前 </div></div> <div class="blog-content" data-v-6293c55f><div class="item-left" data-v-6293c55f><a href="/p/4738427618" target="_blank" title="Java获得今日零时零分零秒的时间(Date型) " class="title single-ellipsis" data-v-6293c55f> Java获得今日零时零分零秒的时间(Date型) </a> <div class="intro multi-ellipsis-2" data-v-6293c55f> publicDatezeroTime()throwsParseException{    DatetimenewDate();    SimpleDateFormatsimpnewSimpleDateFormat("yyyyMMdd00:00:00");    SimpleDateFormatsimp2newS </div></div> <!----></div> <!----> <div class="blog-footer flex" data-v-6293c55f><div class="iconfont footer-item icon-Show1" data-v-6293c55f><span class="num" data-v-6293c55f>938</span></div><div class="iconfont footer-item icon-Guanbi1-copy" data-v-6293c55f><span class="num" data-v-6293c55f>0</span></div><div class="iconfont footer-item icon-Pinglun1" data-v-6293c55f><span class="num" data-v-6293c55f>0</span></div></div></div><div class="blog-item" data-v-6293c55f><div class="blog-header" data-v-6293c55f><img src="https://img-hello-world.oss-cn-beijing.aliyuncs.com/imgs/46847d754406b0102dee7a1f54d14f92.jfif" alt="Wesley13" class="img" data-v-6293c55f> <a href="/Wesley13" target="_blank" class="name" data-v-6293c55f> Wesley13 </a> <div class="dot" data-v-6293c55f>•</div> <div class="time" data-v-6293c55f> 2年前 </div></div> <div class="blog-content" data-v-6293c55f><div class="item-left" data-v-6293c55f><a href="/p/6029686498" target="_blank" title="mysql设置时区 " class="title single-ellipsis" data-v-6293c55f> mysql设置时区 </a> <div class="intro multi-ellipsis-2" data-v-6293c55f> mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0 </div></div> <!----></div> <!----> <div class="blog-footer flex" data-v-6293c55f><div class="iconfont footer-item icon-Show1" data-v-6293c55f><span class="num" data-v-6293c55f>920</span></div><div class="iconfont footer-item icon-Guanbi1-copy" data-v-6293c55f><span class="num" data-v-6293c55f>0</span></div><div class="iconfont footer-item icon-Pinglun1" data-v-6293c55f><span class="num" data-v-6293c55f>0</span></div></div></div><div class="blog-item" data-v-6293c55f><div class="blog-header" data-v-6293c55f><img src="https://img-hello-world.oss-cn-beijing.aliyuncs.com/imgs/46847d754406b0102dee7a1f54d14f92.jfif" alt="Wesley13" class="img" data-v-6293c55f> <a href="/Wesley13" target="_blank" class="name" data-v-6293c55f> Wesley13 </a> <div class="dot" data-v-6293c55f>•</div> <div class="time" data-v-6293c55f> 2年前 </div></div> <div class="blog-content" data-v-6293c55f><div class="item-left" data-v-6293c55f><a href="/p/4384340365" target="_blank" title="00:Java简单了解 " class="title single-ellipsis" data-v-6293c55f> 00:Java简单了解 </a> <div class="intro multi-ellipsis-2" data-v-6293c55f> 浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。 </div></div> <!----></div> <!----> <div class="blog-footer flex" data-v-6293c55f><div class="iconfont footer-item icon-Show1" data-v-6293c55f><span class="num" data-v-6293c55f>903</span></div><div class="iconfont footer-item icon-Guanbi1-copy" data-v-6293c55f><span class="num" data-v-6293c55f>0</span></div><div class="iconfont footer-item icon-Pinglun1" data-v-6293c55f><span class="num" data-v-6293c55f>0</span></div></div></div><div class="blog-item" data-v-6293c55f><div class="blog-header" data-v-6293c55f><img src="https://img-hello-world.oss-cn-beijing.aliyuncs.com/imgs/1bad3e5246214111b0d7a482fc5beec5.jfif" alt="Stella981" class="img" data-v-6293c55f> <a href="/Stella981" target="_blank" class="name" data-v-6293c55f> Stella981 </a> <div class="dot" data-v-6293c55f>•</div> <div class="time" data-v-6293c55f> 2年前 </div></div> <div class="blog-content" data-v-6293c55f><div class="item-left" data-v-6293c55f><a href="/p/3395108718" target="_blank" title="Django中Admin中的一些参数配置 " class="title single-ellipsis" data-v-6293c55f> Django中Admin中的一些参数配置 </a> <div class="intro multi-ellipsis-2" data-v-6293c55f> 设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable </div></div> <!----></div> <!----> <div class="blog-footer flex" data-v-6293c55f><div class="iconfont footer-item icon-Show1" data-v-6293c55f><span class="num" data-v-6293c55f>849</span></div><div class="iconfont footer-item icon-Guanbi1-copy" data-v-6293c55f><span class="num" data-v-6293c55f>0</span></div><div class="iconfont footer-item icon-Pinglun1" data-v-6293c55f><span class="num" data-v-6293c55f>0</span></div></div></div><div class="blog-item" data-v-6293c55f><div class="blog-header" data-v-6293c55f><img src="https://img-hello-world.oss-cn-beijing.aliyuncs.com/imgs/46847d754406b0102dee7a1f54d14f92.jfif" alt="Wesley13" class="img" data-v-6293c55f> <a href="/Wesley13" target="_blank" class="name" data-v-6293c55f> Wesley13 </a> <div class="dot" data-v-6293c55f>•</div> <div class="time" data-v-6293c55f> 2年前 </div></div> <div class="blog-content" data-v-6293c55f><div class="item-left" data-v-6293c55f><a href="/p/2102334911" target="_blank" title="MySQL部分从库上面因为大量的临时表tmp_table造成慢查询 " class="title single-ellipsis" data-v-6293c55f> MySQL部分从库上面因为大量的临时表tmp_table造成慢查询 </a> <div class="intro multi-ellipsis-2" data-v-6293c55f> 背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_ </div></div> <!----></div> <!----> <div class="blog-footer flex" data-v-6293c55f><div class="iconfont footer-item icon-Show1" data-v-6293c55f><span class="num" data-v-6293c55f>1113</span></div><div class="iconfont footer-item icon-Guanbi1-copy" data-v-6293c55f><span class="num" data-v-6293c55f>0</span></div><div class="iconfont footer-item icon-Pinglun1" data-v-6293c55f><span class="num" data-v-6293c55f>0</span></div></div></div><div class="blog-item" data-v-6293c55f><div class="blog-header" data-v-6293c55f><img src="https://img-hello-world.oss-cn-beijing.aliyuncs.com/imgs/ff45645a048833b06e967323e7411c91.webp" alt="Python进阶者" class="img" data-v-6293c55f> <a href="/pdcfighting" target="_blank" class="name" data-v-6293c55f> Python进阶者 </a> <div class="dot" data-v-6293c55f>•</div> <div class="time" data-v-6293c55f> 3个月前 </div></div> <div class="blog-content" data-v-6293c55f><div class="item-left" data-v-6293c55f><a href="/p/7920817787" target="_blank" title="Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除" class="title single-ellipsis" data-v-6293c55f> Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除 </a> <div class="intro multi-ellipsis-2" data-v-6293c55f> 大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这 </div></div> <img src="https://img-hello-world.oss-cn-beijing.aliyuncs.com/imgs/aeaded5a375b9d90ad54a2731b017114.png" class="item-right" data-v-6293c55f></div> <!----> <div class="blog-footer flex" data-v-6293c55f><div class="iconfont footer-item icon-Show1" data-v-6293c55f><span class="num" data-v-6293c55f>128</span></div><div class="iconfont footer-item icon-Guanbi1-copy" data-v-6293c55f><span class="num" data-v-6293c55f>0</span></div><div class="iconfont footer-item icon-Pinglun1" data-v-6293c55f><span class="num" data-v-6293c55f>0</span></div></div></div> </div></div></div> <div class="blog-right-container"><div class="personal-info" data-v-af95cca0><div class="base-info" data-v-af95cca0><img src="https://img-hello-world.oss-cn-beijing.aliyuncs.com/imgs/1bad3e5246214111b0d7a482fc5beec5.jfif" alt="Stella981" class="avatar" data-v-af95cca0> <div class="info-content" data-v-af95cca0><div onc class="name-level" data-v-af95cca0><div class="name single-ellipsis" data-v-af95cca0> Stella981 </div> <div class="level-icon level-1" data-v-429e45df data-v-af95cca0> Lv1 </div></div> <!----></div></div> <button type="button" class="follow-btn ant-btn ant-btn-primary ant-btn-background-ghost" data-v-af95cca0><span>关 注</span></button> <div class="signature" data-v-af95cca0>接天莲叶无穷碧,映日荷花别样红。</div> <div class="article-fans-stars" data-v-af95cca0><div class="item" data-v-af95cca0><div class="label" data-v-af95cca0>文章</div> <div class="value" data-v-af95cca0> 1.7w </div></div><div class="item" data-v-af95cca0><div class="label" data-v-af95cca0>粉丝</div> <div class="value" data-v-af95cca0> 37 </div></div><div class="item" data-v-af95cca0><div class="label" data-v-af95cca0>获赞</div> <div class="value" data-v-af95cca0> 28 </div></div></div> <div class="author-social-info" data-v-af95cca0><!----> <!----> <!----></div></div> <div class="sider-box" data-v-377f20d6><h5 class="common-title" data-v-377f20d6>热门文章</h5> <div class="content-box" data-v-377f20d6><div class="hot-article-list" data-v-5fa70b3e><div class="item" data-v-5fa70b3e><a href="/p/6917592658" title="OpenVPN下载、安装、配置及使用详解 " class="abstract multi-ellipsis-2" data-v-5fa70b3e> OpenVPN下载、安装、配置及使用详解 </a></div><div class="item" data-v-5fa70b3e><a href="/p/0907804122" title="GitHub神器,一个可以白嫖全网无损音乐的神器 " class="abstract multi-ellipsis-2" data-v-5fa70b3e> GitHub神器,一个可以白嫖全网无损音乐的神器 </a></div><div class="item" data-v-5fa70b3e><a href="/p/9665141123" title="OpenWrt 路由器过滤广告的N种方法 " class="abstract multi-ellipsis-2" data-v-5fa70b3e> OpenWrt 路由器过滤广告的N种方法 </a></div><div class="item" data-v-5fa70b3e><a href="/p/0868920465" title="Python—执行系统命令的四种方法(os.system、os.popen、commands、subprocess) " class="abstract multi-ellipsis-2" data-v-5fa70b3e> Python—执行系统命令的四种方法(os.system、os.popen、commands、subprocess) </a></div><div class="item" data-v-5fa70b3e><a href="/p/8340561847" title="SS端加密以及obfs混淆 " class="abstract multi-ellipsis-2" data-v-5fa70b3e> SS端加密以及obfs混淆 </a></div></div></div></div></div></div></div> <!----></div></div></div><script>window.__NUXT__=(function(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z){return {layout:"default",data:[{}],fetch:{},error:f,state:{showSlideAuth:c,showLogin:c,fromIndex:c,urlConfig:{GET_BLOG_COLLECTION_LIST_URL:j,getAllTag:"\u002Ftag\u002FgetAllTag",CREATE_BLOG_URL:"\u002Fmanage\u002FcreateBlog",PUBLISH_BLOG_URL:"\u002Fmanage\u002FpublishBlog",UPDATE_BLOG_DETAIL:"\u002Fmanage\u002FupdateBlog",GET_BLOG_DETAIL:"\u002Fblog\u002FgetBlogDetail",GET_BLOG_NEWEST_DRAFT:k,UPDATE_CHAPTER_URL:l,GET_CHAPTER_NEWEST_DRAFT:m,PUBLISH_CHAPTER:l,CREATE_BLOG_CATE:"\u002Fcollection\u002Fadd",RENAME_COLLECTION:"\u002Fcollection\u002FrenameCollection",DELETE_COLLECTION:"\u002Fcollection\u002FdeleteCollection",GET_MY_BLOG_LIST_URL:"\u002Fadmin\u002FblogList",FOLLOW_AUTHOR:"\u002Fuser\u002Ffollow",UNFOLLOW_AUTHOR:"\u002Fuser\u002Funfollow",GET_RECOMMEND_BLOG:"\u002Fhome\u002FgetHomeBlogByAction",GET_RECOMMEND_BLOG_BY_CATE:"\u002Fhome\u002FgetHomeBlogListByTag",GET_RECOMMEND_BLOG_BY_TAG:"\u002Fhome\u002FgetBlogListByTag",GET_TAG_LIST:"\u002Fuser\u002FhotWords",GET_CATE_LIST:"\u002Ftag\u002FgetHomeTag",GET_RECOMMEND_AUTHOR:"\u002Fhome\u002FgetRecommendAuthorList",GET_DAILY_ALGORITHM:"\u002Fhome\u002Fdailyalgorithm",LOG_IN:"\u002Faccess\u002Flogin",LOG_OUT:"\u002Faccess\u002FsignOut",CHECK_USER_INFO:"\u002Faccess\u002FcheckUserInfo",REGISTER:"\u002Faccess\u002Fregister",CHANGE_PWD:"\u002Faccess\u002FchangePassword",SEND_CODE:"\u002Faccess\u002FsendCode",ACTION_AUTH:"\u002Faccess\u002FactionAuth",ACTION_AUTH2:"\u002Faccess\u002FactionAuth2",CHECK_USER_AND_BLOG:"\u002Faccess\u002FcheckUserAndBlog",CHECK_TOKEN:"\u002Faccess\u002FcheckToken",SIGN_IN:"\u002Faccess\u002FsignIn",GET_PERSONAL_INFO:"\u002Fuser\u002Fdetail\u002Finfo",GET_PERSONAL_BLOG_LIST:"\u002Fuser\u002Fdetail\u002Fbloglist",FILE_UPLOAD:"\u002Ffile\u002Fupload",DL_AND_UPLOAD:"\u002Ffile\u002FdownloadAndUploadOss",GET_MY_FOLLOW_USER_LIST:"\u002Fadmin\u002FgetMyFollowUserList",GET_MY_FANS_USER_LIST:"\u002Fadmin\u002FgetMyFansUserList",GET_MY_FOLLOW_QUESTION_LIST:"\u002Fadmin\u002FgetMyFollowQuestion",GET_MY_SUBSCIBE_SPECIAL_LIST:"\u002Fadmin\u002FgetMySubscribeSpecialList",TAKE_OFF_BLOG:"\u002Fadmin\u002FtakeOffBlog",TAKE_ON_BLOG:"\u002Fadmin\u002FtakeOnBlog",GET_HOME_RECOMMEND_SPECIAL_LIST:"\u002Fhome\u002FgetRecommendSpecialList",GET_MOST_SPECIAL_COUNT_USER_LIST:"\u002Fspecial\u002FgetSpecialMostUserList",GET_SPECIAL_CATE_LIST_URL:"\u002Fspecial\u002FgetSpecialCateList",GET_SPECIAL_LIST_URL:"\u002Fspecial\u002FgetSpecialList",GET_SPECIAL_LIST_PER_CATEGORY_URL:"\u002Fspecial\u002FgetSpecialListPerCategory",GET_CATEGORY_INFO_BY_ID_URL:"\u002Fhome\u002FgetCategoryInfoById",GET_SPECIAL_COUNT_PER_CATEGORY_URL:"\u002Fspecial\u002FgetSpecialTotalCountPerCategory",GET_SPECIAL_BANNER:"\u002Fspecial\u002FgetBannerList",GET_SPECIAL_DETAIL_CHAPTER_LIST:"\u002Fspecial\u002FgetSpecialSectionList",GET_SPECIAL_DETAIL:"\u002Fspecial\u002FgetMySpecialChapterInfo",GetChapterInfo:"\u002Fspecial\u002FgetSectionDetail",GET_SPECIAL_DETAIL_INFO:"\u002Fadmin\u002FgetSpecialDetail",ADD_CHAPTER_URL:"\u002Fadmin\u002FaddChapter",UPDATE_CHAPTER_INFO:"\u002Fadmin\u002FupdateChapterInfo",UPDATE_CHAPTER_SEQUENCE:"\u002Fadmin\u002FupdateChapterSequence",DELETE_CHAPTER_URL:"\u002Fadmin\u002FdeleteChapter",TAKE_ON_SPECIAL:"\u002Fspecial\u002FpublishSection",TAKE_OFF_SPECIAL:"\u002Fadmin\u002FtakeOffSpecial",RENAME_SPECIAL:"\u002Fadmin\u002FrenameSpecial",GET_SPECIAL_CATE_LIST:"\u002Fadmin\u002FgetSpecialCateList",UPDATE_SPECIAL_INTRO:"\u002Fadmin\u002FupdateSpecialIntro",UPDATE_SPECIAL_INFO:"\u002Fadmin\u002FupdateSpecialCateId",UPDATE_SPECIAL_TITLE:"\u002Fadmin\u002FupdateSpecialTitle",DELETE_SPECIAL:"\u002Fadmin\u002FdeleteSpecial",GET_CHAPTER_COMMENT:"\u002Fcomment\u002FgetChapterCommentList",UPDATE_SPECIALINFO:"\u002Fadmin\u002FupdateSpecialBaseInfo",SUBSCRIBE_SPECIAL:n,UN_SUBSCRIBE_SPECIAL:o,MODIFY_SPECIAL:p,GET_TUTORIAL_BIG_CATEGORY:"\u002Ftutorial\u002FgetTutorialBigCategories",GET_ALL_TUTORIALS:q,GET_CHAPTER_AND_SECTION_BY_PATH:"\u002Ftutorial\u002FgetChapterAndSectionByPath",GET_CONTENT_BY_SECTION_PATH:"\u002Ftutorial\u002FgetSectionContent",GET_TUTORIAL_OVERVIEW:r,GET_UID_BY_PROFILE_PATH:"\u002Fuser\u002FgetUidByProfilePath",GET_USER_DETAIL_USER_INFO:"\u002Fuser\u002Fdetail\u002FuserInfo",GET_SPECIAL_CATEGORY:"\u002Fuser\u002Fdetail\u002FspecialCategory",CREATE_SPECIAL_URL:"\u002Fspecial\u002FcreateSpecial",GET_MY_SPECIAL_LIST_URL:"\u002Fadmin\u002FgetMySpecialList",GET_CHAPTER_LIST_PER_SPECIAL_URL:"\u002Fadmin\u002FgetSpecialChapterList",GET_USER_RELATED_QUESTION_LIST:"\u002Fuser\u002Fdetail\u002FgetUserRelatedQuestionList",Get_BLOG_COLLECT_LIST:"\u002Fuser\u002Fdetail\u002FgetUserBlogCollectList",GET_BLOG_LIST_URL:"\u002Fuc\u002FgetUserBlogList",GET_BLOG_LIST_BY_COLLECT_ID:"\u002Fuser\u002Fdetail\u002FgetCollectBlogList",GET_SPECIAL_LIST_BY_SORT_TYPE:"\u002Fuc\u002FgetUserPublishedSpecialList",GET_USER_BASE_INFO:"\u002Fuc\u002FgetUserInfo",GET_NEWEST_BLOG_LIST:"\u002Fuser\u002Fdetail\u002FgetNewestBlogList",GET_NEWEST_COMMENT_LIST:"\u002Fuser\u002Fdetail\u002FgetNewestCommentList",GET_FAVORITE_BLOG_LIST:"\u002Fuc\u002FgetUserFavoriteBlogList",GET_FOLLOW_USER_LIST:"\u002Fuc\u002FgetFollowList",GET_FOLLOW_USER_FANS:"\u002Fuc\u002FgetFanList",GET_HOT_COMMENTS:"\u002Fuc\u002FgetHotComments",IS_USER_BLOG:"\u002Fuc\u002FisUserBlog",GET_SEARCH_WORD:"\u002Fsearch\u002FsearchWord",GET_QUESTION_COMMON_TAG:"\u002Fquestion\u002FgetHotTagList",GET_QUESTION_LIST:"\u002Fquestion\u002FgetQuestionList",GET_QUESTION_DETAIL:"\u002Fquestion\u002FgetQuestionDetail",UPDATE_QUESTION_INFO:"\u002Fquestion\u002FupdateQuestion",GET_QUESTION_BASE_INFO:"\u002Fquestion\u002FgetQuestionBaseInfo",GET_BLOG_COMMENT_LIST:"\u002Fcomment\u002FgetBlogCommentList",ADD_COMMENT:"\u002Fcomment\u002FaddComment",ADD_REPLY:"\u002Fcomment\u002FaddReply",LIKE_BLOG:"\u002Fblog\u002FzanBlog",FAVORITE_BLOG:"\u002Fblog\u002FfavoriteBlog",GET_USER_LIKE_FAVORITE_INFO:"\u002Fadmin\u002FgetUserAndBlogActionInfo",DAMIT_CHANGE_PWD:"\u002Fadmin\u002FchangePassword",UPDATE_PERSONAL:"\u002Fadmin\u002FmodifyPersonalInfo",SUBMIT_SUGGESTION:"\u002Fsuggestion\u002FsubmitSuggestion",GETALLBLOGID:"\u002Faccess\u002FgetAllBlogId",GETCONTENTBYID:"\u002Faccess\u002FgetContentById",UPDATEHTMLBYID:"\u002Faccess\u002FupdateHtmlById",CHANGE_USER_PWD:s,SEND_USER_SMS:"\u002Faccess\u002FsendSmsCode",GET_WIN_USERS:"\u002Fwin\u002FgetWinUsers",GET_FRIEND_LINKS:"\u002Fhome\u002FgetFriendLinks",GET_SITE_MAP:"\u002Fspider\u002FgetSiteMap",GET_BLOG_BY_TAG_NAME:"\u002Fblog\u002FgetBlogByTagName",GET_BLOG_BY_TAG_ID:"\u002Fsearch\u002FsearchTag",GET_RANDOM_TAGS:"\u002Fblog\u002FgetRandomTags",GET_UPLOAD_SIGNATURE:"\u002Fvod\u002FgetUploadSignature",UPLOAD_MEDIA_INFO:"\u002Fvod\u002FuploadMediaInfo",GET_BLOG_INFO:"\u002Fadmin\u002FgetBlogInfo",GET_HOME_RECOMMEND_TAGS:"\u002Ftag\u002FgetHomeRecommendTags",GET_USER_HOT_BLOG_LIST:"\u002Fuc\u002FgetUserHotBlogList",COMMENT_BLOG:"\u002Fcomment\u002Fcomment",GET_COMMENT_LIST:"\u002Fcomment\u002FgetCommentList",REPLY_COMMENT:"\u002Fcomment\u002FreplyComment",GET_COMMENT_REPLIES:"\u002Fcomment\u002FgetCommentReplies",GET_BACK_IMAGE_LIST:"\u002Fuc\u002FgetBackImageList",UPDATE_BACK_IMAGE:"\u002Fuc\u002FupdateBackImage",GET_MY_SPECIAL_LIST:"\u002Fmanage\u002FgetMySpecialList",GET_SUBCRIBED_SPECLIAL_LIST:"\u002Fmanage\u002FgetMySubscribedSpecialList",GET_MY_SPECIAL_DETAIL:"\u002Fmanage\u002FgetMySpecialDetail",SUBCRIBE_SPECLIAL:n,UNSUBCRIBED_SPECLIAL:o,CREATE_COLLECTION:"\u002Fmanage\u002FcreateCollection",GET_COLLECTION_LIST:j,UPDATE_COLLECTION:"\u002Fmanage\u002FupdateCollection",REMOVE_COLLECTION:"\u002Fmanage\u002FremoveCollection",GET_MY_BLOG_LIST:"\u002Fmanage\u002FgetMyBlogList",GET_FOLLOW_LIST:"\u002Fmanage\u002FgetFollowList",UPDATE_FOLLOW:"\u002Fmanage\u002FupdateFollow",GET_MY_INFO:"\u002Fmanage\u002FgetMyInfo",UPDATE_MY_INFO:"\u002Fmanage\u002FupdateMyInfo",GET_MY_FAVORITE_BLOG_LIST:"\u002Fmanage\u002FgetMyFavoriteBlogList",GET_MY_FAVORITE_LESSON_LIST:"\u002Flesson\u002FfavoriteList",UPDATE_FAVORITE_LESSON:"\u002Flesson\u002Ffavorite",UPDATE_CANCEL_FAVORITE_LESSON:"\u002Flesson\u002FremoveFavorite",GET_RECOMMEND_LESSON_BY_BLOG:"\u002Flesson\u002FrecommendLesson",MODIFY_PASSWORD:s,GET_MY_BLOG_DETAIL:k,GET_NEW_NOTIFICATION_COUNT:"\u002Fmanage\u002FgetNewNotificationCount",GET_NOTIFICATION_LIST:"\u002Fmanage\u002FgetNotificationList",READ_NOTIFICATION:"\u002Fmanage\u002FreadNotification",CREATE_SECTION:"\u002Fspecial\u002FcreateSection",MODIFIY_SECTION_TITLE:"\u002Fspecial\u002FmodifySectionTitle",MODIFIY_SPECIAL_TITLE:p,MODIFIY_SECTION_STATUS:"\u002Fspecial\u002FmodifySectionStatus",PUBLISH_SPECIAL:"\u002Fspecial\u002FpublishSpecial",OFFLINE_SPECIAL:"\u002Fspecial\u002FofflineSpecial",UNPUBLISHED_SPECIAL_DETAIL:"manage\u002FgetMySpecialDetail",UNPUBLISHED_SPECIAL_CHAPTER_DETAIL:m,UPDATE_BLOG_TITLE:"\u002Fmanage\u002FupdateTitle",UPDATE_BLOG_STATUS_PUBLISHED:"\u002Fmanage\u002FupdateBlogStatusPublished",DELETE_BLOG:"\u002Fmanage\u002FdeleteBlog",GET_CATELIST_TUTORIAL:"\u002Ftutorial\u002FgetCateList",GET_TUTORIAL_LIST:q,GET_TUTORIAL_DETAIL:r,GET_CHAPTER_INFO:"\u002Ftutorial\u002FgetChapterInfo",FAVORITE_SECTION:"\u002Fmanage\u002FfavoriteSection",ZAN_SECTION:"\u002Fmanage\u002FzanSection",LESSON_LIST_ALL:"\u002Flesson\u002Flist\u002Fall",LESSON_LIST_MY:"\u002Flesson\u002Flist\u002Fmy",LESSON_LIST_BUY:"\u002Flesson\u002Flist\u002Fbuy",LESSON_LIST_REC:"\u002Flesson\u002Flist\u002Frec",LESSON_CREATE:"\u002Flesson\u002Fcreate",LESSON_DETAIL_EDIT:"\u002Flesson\u002Fdetail\u002Fedit",LESSON_DETAIL:"\u002Flesson\u002Fdetail",LESSON_DELETE:"\u002Flesson\u002Fdelete",LESSON_CATEGORIES:"\u002Flesson\u002Fcategories",LESSON_DIRECTIONS:"\u002Flesson\u002Fdirections",LESSON_STORE:"\u002Flesson\u002Fstore",LESSON_CREATE_CHAPTER:"\u002Flesson\u002Fchapter",LESSON_CHAPTER_VIDEO:"\u002Flesson\u002Fchapter\u002Fvideo",LESSON_CHAPTERS:"\u002Flesson\u002Fchapters",LESSON_CHAPTERS_EDIT:"\u002Flesson\u002Fchapters\u002Fedit",LESSON_VIDEO_ENCRYPT:"\u002Flesson\u002Fvideo\u002Fencrypt",LESSON_VIDEO:"\u002Flesson\u002Fvideo",LESSON_VIDEO_M3U8:"\u002Flesson\u002Fvideo\u002Fm3u8",LESSON_COS_TOKEN:"\u002Flesson\u002Fcos\u002Ftoken",LESSON_NOTE:"\u002Flesson\u002Fnote",LESSON_RESOURCE:"\u002Flesson\u002Fresource",LESSON_LEARN_REPORT:"\u002Flesson\u002Flearn\u002Freport",ADD_STUDY_COUNT:"\u002Flesson\u002FaddStudyCount",WXPAY_NATIVE_PAY:"\u002Fwxpay\u002FnativePay",WXPAY_QUERY_ORDER_STATUS:"\u002Fwxpay\u002FqueryOrderStatus",WXPAY_ORDER:"\u002Fwxpay\u002Forder",WXPAY_ORDERS:"\u002Fwxpay\u002Forders",WXPAY_CANCELORDER:"\u002Fwxpay\u002FcancelOrder"},isLoading:c,authPhone:b,friendLink:[],showSpecial:c,specialData:f,navFixedVisible:c,deviceId:623234632259724400,blackList:[],access:{token:b,userInfo:{}},admin:{collectionList:[],specialList:[],notifyCount:{},curTab:"blog",blogDetail:{}},backstage:{blogList:{},typeCount:{collectCount:a,commentCount:a,count:a,followCount:a,subscribeCount:a,zanCount:a},isShow:c},course:{isCollapase:t},personal:{errorMsg:b,handling:c,visible:c,success:c,isSmsCoding:c,sendCodeSuccess:c,uid:f,userDetailInfo:{},personalBlogList:[],blogCount:a,personalSpecialList:[],specialCount:a,newestBlog:[],newestComment:[],personalFavoriteList:[],favoriteCount:a,personalFollowList:[],followCount:a,personalFansList:[],fansCount:a,hotComment:[],routeParams:{profile:b,pageType:b}},question:{commonTags:[],questionList:[],questionDetail:{}},recommend:{recommendBlog:{data:[]},tagList:[],categoryList:{data:[]},recommendAuthorList:{data:[]},todayAlgorithm:b,blogDetail:{blogInfo:{uuid:"3794736797",title:"Http工作原理(转) ",intro:"  HTTP协议(HyperTextTransferProtocol,超文本传输协议)是用于从WWW服务器传输超文本到本地浏览器的传送协议。它可以使浏览器更加高效,使网络传输减少。它不仅保证计算机正确快速地传输超文本文档,还确定传输文档中的哪一部分,以及哪部分内容首先显示(如文本先于图形)等。         在了解HTTP如何工作之前,我们先了解计",content:"  HTTP协议(HyperText Transfer Protocol,超文本传输协议)是用于从WWW服务器传输超文本到本地浏览器的传送协议。它可以使浏览器更加高效,使网络传输减少。它不仅保证计算机正确快速地传输超文本文档,还确定传输文档中的哪一部分,以及哪部分内容首先显示(如文本先于图形)等。\n\n         在了解HTTP如何工作之前,我们先了解计算机之间的通信。\n\n2\\. 计算机相互之间的通信\n--------------\n\n        互联网的关键技术就是TCP\u002FIP协议。两台计算机之间的通信是通过TCP\u002FIP协议在因特网上进行的。实际上这个是两个协议:\n\n        TCP : Transmission Control Protocol 传输控制协议和IP: Internet Protocol  网际协议。\n\n        IP:计算机之间的通信\n\n        IP协议是计算机用来相互识别的通信的一种机制,每台计算机都有一个IP.用来在internet上标识这台计算机。  IP 负责在因特网上发送和接收数据包。通过 IP,消息(或者其他数据)被分割为小的独立的包,并通过因特网在计算机之间传送。IP 负责将每个包路由至它的目的地。\n\n        IP协议仅仅是允许计算机相互发消息,但它并不检查消息是否以发送的次序到达而且没有损坏(只检查关键的头数据)。为了提供消息检验功能,直接在IP协议上设计了传输控制协议TCP.\n\n       TCP : 应用程序之间的通信\n\n       TCP确保数据包以正确的次序到达,并且尝试确认数据包的内容没有改变。TCP在IP地址之上引端口(port),它允许计算机通过网络提供各种服务。一些端口号为不同的服务保留,而且这些端口号是众所周知。\n\n       服务或者守护进程:在提供服务的机器上,有程序监听特定端口上的通信流。例如大多数电子邮件通信流出现在端口25上,用于wwww的HTTP通信流出现在80端口上。\n\n       当应用程序希望通过 TCP 与另一个应用程序通信时,它会发送一个通信请求。这个请求必须被送到一个确切的地址。在双方“握手”之后,TCP 将在两个应用程序之间建立一个全双工 (full-duplex) 的通信,占用两个计算机之间整个的通信线路。TCP 用于从应用程序到网络的数据传输控制。TCP 负责在数据传送之前将它们分割为 IP 包,然后在它们到达的时候将它们重组。\n\n       TCP\u002FIP 就是TCP 和 IP 两个协议在一起协同工作,有上下层次的关系。\n\n       TCP 负责应用软件(比如你的浏览器)和网络软件之间的通信。IP 负责计算机之间的通信。TCP 负责将数据分割并装入 IP 包,IP 负责将包发送至接收者,传输过程要经IP路由器负责根据通信量、网络中的错误或者其他参数来进行正确地寻址,然后在它们到达的时候重新组合它们。\n\n3\\. HTTP协议所在的协议层\n----------------\n\n      HTTP是基于TCP协议之上的。在[TCP\u002FIP协议参考模型](https:\u002F\u002Fwww.oschina.net\u002Faction\u002FGoToLink?url=http%3A%2F%2Fblog.csdn.net%2Fhguisu%2Farticle%2Fdetails%2F7249611)的各层对应的协议如下图,其中HTTP是应用层的协议。\n\n      ![](https:\u002F\u002Foscimg.oschina.net\u002Foscnet\u002Fd2fc72ac01ef5396782f9b9f7abe8deb805.jpg)\n\n4\\. HTTP请求响应模型   \n-----------------\n\n       HTTP由请求和响应构成,是一个标准的客户端服务器模型(B\u002FS)。HTTP协议永远都是客户端发起请求,服务器回送响应。见下图:\n\n    ![](http:\u002F\u002Fimg.my.csdn.net\u002Fuploads\u002F201303\u002F16\u002F1363438271_3285.jpg)\n\n       HTTP是一个无状态的协议。无状态是指客户机(Web浏览器)和服务器之间不需要建立持久的连接,这意味着当一个客户端向服务器端发出请求,然后服务器返回响应(response),连接就被关闭了,在服务器端不保留连接的有关信息.HTTP遵循请求(Request)\u002F应答(Response)模型。客户机(浏览器)向服务器发送请求,服务器处理请求并返回适当的应答。所有HTTP连接都被构造成一套请求和应答。\n\n5\\. HTTP工作过程      \n------------------\n\n     一次HTTP操作称为一个事务,其工作整个过程如下:\n\n     1 ) 、地址解析,\n\n     如用客户端浏览器请求这个页面:[http:\u002F\u002Flocalhost.com:8080\u002Findex.htm](https:\u002F\u002Fwww.oschina.net\u002Faction\u002FGoToLink?url=http%3A%2F%2Flocalhost%3A8080%2Fsimple.htm)\n\n     从中分解出协议名、主机名、端口、对象路径等部分,对于我们的这个地址,解析得到的结果如下: \n     协议名:http \n     主机名:localhost.com \n     端口:8080 \n     对象路径:\u002Findex.htm\n\n      在这一步,需要域名系统DNS解析域名localhost.com,得主机的IP地址。\n\n    2)、封装HTTP请求数据包\n\n     把以上部分结合本机自己的信息,封装成一个HTTP请求数据包\n\n     3)封装成TCP包,建立TCP连接(TCP的三次握手)\n\n       在HTTP工作开始之前,客户机(Web浏览器)首先要通过网络与服务器建立连接,该连接是通过TCP来完成的,该协议与IP协议共同构建Internet,即著名的TCP\u002FIP协议族,因此Internet又被称作是TCP\u002FIP网络。HTTP是比TCP更高层次的应用层协议,根据规则,只有低层协议建立之后才能进行更高层协议的连接,因此,首先要建立TCP连接,一般TCP连接的端口号是80。这里是8080端口\n\n     4)客户机发送请求命令\n\n       建立连接后,客户机发送一个请求给服务器,请求方式的格式为:统一资源标识符(URI:Uniform Resource Identifier)、协议版本号,后边是MIME信息包括请求修饰符、客户机信息和可能的内容。\n\n     5)服务器响应\n\n     服务器接到请求后,给予相应的响应信息,其格式为一个状态行,包括信息的协议版本号、一个成功或错误的代码,后边是MIME信息包括服务器信息、实体信息和可能的内容。\n\n        实体消息是服务器向浏览器发送头信息后,它会发送一个空白行来表示头信息的发送到此结束,接着,它就以Content-Type应答头信息所描述的格式发送用户所请求的实际数据\n\n     6)服务器关闭TCP连接\n\n     一般情况下,一旦Web服务器向浏览器发送了请求数据,它就要关闭TCP连接,然后如果浏览器或者服务器在其头信息加入了这行代码\n\n    Connection:keep-alive\n\n   TCP连接在发送后将仍然保持打开状态,于是,浏览器可以继续通过相同的连接发送请求。保持连接节省了为每个请求建立新连接所需的时间,还节约了网络带宽。\n\n6\\. HTTP协议栈中各层数据流 \n\n 首先我们看看客户端请求的时候,数据在各层协议的数据组织如下图:\n\n         ![](https:\u002F\u002Foscimg.oschina.net\u002Foscnet\u002F57e06790690d39bceeab32e75919869ba76.jpg)\n\n            而服务器解析客户机请求就是反向操作的过程,如下图:\n\n           ![](https:\u002F\u002Foscimg.oschina.net\u002Foscnet\u002Fe5a0c0533ac66a3ac58caabda1fc67ea396.jpg)\n\n       客户机发起一次请求的时候:\n\n       客户机会将请求封装成http数据包--\u003E封装成Tcp数据包--\u003E封装成Ip数据包---\u003E封装成数据帧---\u003E硬件将帧数据转换成bit流(二进制数据)--\u003E最后通过物理硬件(网卡芯片)发送到指定地点。\n\n       服务器硬件首先收到bit流....... 然后转换成ip数据包。于是通过ip协议解析Ip数据包,然后又发现里面是tcp数据包,就通过tcp协议解析Tcp数据包,接着发现是http数据包通过http协议再解析http数据包得到数据。\n\n6\\. HTTPS实现原理    \n-----------------\n\n      HTTPS(全称:Hypertext Transfer Protocol over Secure Socket Layer),是以安全为目标的HTTP通道,简单讲是HTTP的安全版。即HTTP下加入SSL层,HTTPS的安全基础是SSL。其所用的端口号是443。\n\n      SSL:安全套接层,是netscape公司设计的主要用于web的安全传输协议。这种协议在WEB上获得了广泛的应用。通过证书认证来确保客户端和网站服务器之间的通信数据是加密安全的。\n\n      有两种基本的加解密[算法](https:\u002F\u002Fwww.oschina.net\u002Faction\u002FGoToLink?url=http%3A%2F%2Flib.csdn.net%2Fbase%2Fdatastructure)类型:\n\n      1)对称加密(symmetric encryption):密钥只有一个,加密解密为同一个密码,且加解密速度快,典型的对称加密[算法](https:\u002F\u002Fwww.oschina.net\u002Faction\u002FGoToLink?url=http%3A%2F%2Flib.csdn.net%2Fbase%2Fdatastructure)有DES、AES,RC5,3DES等;\n\n       对称加密主要问题是共享秘钥,除你的计算机(客户端)知道另外一台计算机(服务器)的私钥秘钥,否则无法对通信流进行加密解密。解决这个问题的方案非对称秘钥。\n\n      2)非对称加密:使用两个秘钥:公共秘钥和私有秘钥。私有秘钥由一方密码保存(一般是服务器保存),另一方任何人都可以获得公共秘钥。\n\n      这种密钥成对出现(且根据公钥无法推知私钥,根据私钥也无法推知公钥),加密解密使用不同密钥(公钥加密需要私钥解密),相对对称加密速度较慢,典型的非对称加密算法有RSA、DSA等。\n\n  下面看一下https的通信过程:\n\n        过程大致如下:\n\n        1) SSL客户端通过TCP和服务器建立连接之后(443端口),并且在一般的tcp连接协商(握手)过程中请求证书。\n\n              即客户端发出一个消息给服务器,这个消息里面包含了自己可实现的算法列表和其它一些需要的消息,SSL的服务器端会回应一个数据包,这里面确定了这次通信所需要的算法,然后服务器向客户端返回证书。(证书里面包含了服务器信息:域名。申请证书的公司,公共秘钥)。                 \n\n       2)Client在收到服务器返回的证书后,判断签发这个证书的公共签发机构,并使用这个机构的公共秘钥确认签名是否有效,客户端还会确保证书中列出的域名就是它正在连接的域名。\n\n       3)  如果确认证书有效,那么生成对称秘钥并使用服务器的公共秘钥进行加密。然后发送给服务器,服务器使用它的私钥对它进行解密,这样两台计算机可以开始进行对称加密进行通信。\n\n  https通信的优点:\n\n  1)客户端产生的密钥只有客户端和服务器端能得到;\n\n  2)加密的数据只有客户端和服务器端才能得到明文;\n\n  3)客户端到服务端的通信是安全的。\n\n7\\. HTTP各种长度限制   \n-----------------\n\n### 1\\. URI长度限制\n\n  在Http1.1协议中并没有提出针对URI的长度进行限制,RFC协议里面是这样描述的,HTTP协议并不对URI的长度做任何的限制,服务器端必须能够处理任何它们所提供服务多能接受的URI,并且能够处理无限长度的URI,如果服务器不能处理过长的URI,那么应该返回414状态码。\n\n  虽然Http协议规定了,但是Web服务器和浏览器对URI都有自己的长度限制。\n\n  服务器的限制:我接触的最多的服务器类型就是Nginx和Tomcat,对于url的长度限制,它们都是通过控制http请求头的长度来进行限制的,nginx的配置参数为large\\_client\\_header\\_buffers,tomcat的请求配置参数为maxHttpHeaderSize,都是可以自己去进行设置。\n\n  浏览器的限制:每种浏览器也会对url的长度有所限制,下面是几种常见浏览器的url长度限制:(单位:字符)\n\n  IE : 2803\n\n  Firefox:65536\n\n  Chrome:8182\n\n  Safari:80000\n\n  Opera:190000\n\n  对于get请求,在url的长度限制范围之内,请求的参数个数没有限制。\n\n### 2\\. Post数据的长度限制\n\n  Post数据的长度限制与url长度限制类似,也是在Http协议中没有规定长度限制,长度限制可以在服务器端配置最大http请求头长度的方式来实现。\n\n### 3\\. Cookie的长度限制\n\n  Cookie的长度限制分这么几个方面来总结。\n\n  (1) 浏览器所允许的每个域下的最大cookie数目,没有去自己测试,从网上找到的资料大概是这么个情况\n\n  IE :原先为20个,后来升级为50个\n\n  Firefox: 50个\n\n  Opera:30个\n\n  Chrome:180个\n\n  Safari:无限制\n\n  当Cookie数超过限制数时浏览器的行为:IE和Opera会采用LRU算法将老的不常使用的Cookie清除掉,Firefox的行为是随机踢出某些Cookie的值。当然无论怎样的策略,还是尽量不要让Cookie数目超过浏览器所允许的范围。\n\n(2) 浏览器所允许的每个Cookie的最大长度\n\n  Firefox和Safari:4079字节\n\n  Opera:4096字节\n\n  IE:4095字节\n\n(3) 服务器中Http请求头长度的限制。Cookie会被附在每次http请求头中传递给服务器,因此还会受到服务器请求头长度的影响。\n\n### 4\\. Html5 LocalStorage\n\nHtml5提供了本地存储机制来供Web应用在客户端存储数据,尽管这个并不属于Http协议的一部分,但是随着Html5的流行,我们可能需要越来越多使用LocalStorage,甚至当它普及的时候跟它打交道就会同今天我们跟Cookie打交道一样多。\n\n对于LocalStorage的长度限制,同Cookie的限制类似,也是浏览器针对域来限制,只不过cookie限制的是个数,LocalStorage限制的是长度:\n\nFirefox\\\\Chrome\\\\Opera都是允许每个域的最大长度为5MB\n\n但是这次IE比较大方,允许的最大长度是10MB\n\n客户端通过发送 HTTP 请求向服务器请求对资源的访问。 它向服务器传递了一个数据块,也就是请求信息,HTTP 请求由三部分组成:请求行、  请求头和请求正文。\n\n 请求行:请求方法 URI 协议\u002F版本\n\n  请求头(Request Header)\n\n 请求正文\n\n下面是一个HTTP请求的数据:\n\n POST \u002Findex.php HTTP\u002F1.1\n Host: localhost\n User-Agent: Mozilla\u002F5.0 (Windows NT 5.1; rv:10.0.2) Gecko\u002F20100101 Firefox\u002F10.0.2\n Accept: text\u002Fhtml,application\u002Fxhtml+xml,application\u002Fxml;q=0.9,*\u002F*;q=0.8\n Accept-Language: zh-cn,zh;q=0.5\n Accept-Encoding: gzip, deflate\n Connection: keep-alive\n Referer: http:\u002F\u002Flocalhost\u002F\n Content-Length:25\n Content-Type:application\u002Fx-www-form-urlencoded\n username=aa&password=1234\n\n### 1、请求行:请求方法URI协议\u002F版本\n\n 请求的第一行是“方法 URL  协议\u002F版本”,并以 回车换行作为结尾。请求行以空格分隔。格式如下:\n\nPOST \u002Findex.php HTTP\u002F1.1\n\n以上代码中“GET”代表请求方法,“\u002F\u002Fndex.php”表示URI,“HTTP\u002F1.1代表协议和协议的版本。\n\n        根据HTTP标准,HTTP请求可以使用多种请求方法。例如:HTTP1.1支持7种请求方法:GET、POST、HEAD、OPTIONS、PUT、DELETE和TARCE。在Internet应用中,最常用的方法是GET和POST。\n\n         URL完整地指定了要访问的网络资源,通常只要给出相对于服务器的根目录的相对目录即可,因此总是以“\u002F”开头,最后,协议版本声明了通信过程中使用HTTP的版本。   \n\n#### 请求方法\n\n在 HTTP 协议中,HTTP 请求可以使用多种请求方法,这些方法指明了要以何种方式来访问 Request-URI 所标识的资源。HTTP1.1 支持的请求方法如下表所示:\n\nHTTP1.1 中的请求方式:\n\n方法\n\n作用\n\nGET\n\n请求获取由 Request-URI 所标识的资源\n\nPOST\n\n请求服务器接收在请求中封装的实体,并将其作为由 Request-Line 中的 Request-URI 所标识的资源的一部分\n\nHEAD\n\n请求获取由 Request-URI 所标识的资源的响应消息报头\n\nPUT\n\n请求服务器存储一个资源,并用 Request-URI 作为其标识符\n\nDELETE\n\n请求服务器删除由 Request-URI 所标识的资源\n\nTRACE\n\n请求服务器回送到的请求信息,主要用于测试或诊断\n\nCONNECT\n\n保留将来使用\n\nOPTIONS\n\n请求查询服务器的性能,或者查询与资源相关的选项和需求\n\n重点介绍 GET、POST 和 HEAD 三个方法:\n\n(1)GET\n\n        GET 方法用于获取由 Request-URI 所标识的资源的信息,常见的形式是:\n\n        GET Request-URI HTTP\u002F1.1 \n        GET方法是默认的HTTP请求方法,例如当我们通过在浏览器的地址栏中直接输入网址的方式去访问网页的时候,浏览器采用的就是 GET 方法向服务器获取资源。\n\n        我们可以使用GET方法来提交表单数据,用GET方法提交的表单数据只经过了简单的编码,同时它将作为URL的一部分向服务器发送,因此,如果使用GET方法来提交表单数据就存在着安全隐患上。例如: \n         [Http:\u002F\u002Flocalhost\u002Flogin.php?username=aa&password=1234](https:\u002F\u002Fwww.oschina.net\u002Faction\u002FGoToLink?url=http%3A%2F%2F127.0.0.1%2Flogin.jsp%3FName%3Dzhangshi%26Age%3D30%26Submit%3D%25CC%2525E%2B%25BD%25BB)\n\n        从上面的URL请求中,很容易就可以辩认出表单提交的内容。(?之后的内容)另外由于GET方法提交的数据是作为URL请求的一部分所以提交的数据量不能太大。这是因为浏览器对url的长度有限制\n\n       各种浏览器也会对url的长度有所限制,下面是几种常见浏览器的url长度限制:(单位:字符)\n\nIE : 2803\n\nFirefox:65536\n\nChrome:8182\n\nSafari:80000\n\nOpera:190000 \n\n(2)POST\n\n          POST方法是GET方法的一个替代方法,它主要是向Web服务器提交表单数据,尤其是大批量的数据。 在请求头信息结束之后的两个回车换行之后(实际是空一行),就是表单提交的数据。如上面提到的post表单数据:\n\n        username=aa&password=1234\n\n        POST方法克服了GET方法的一些缺点。通过POST方法提交表单数据时,数据不是作为URL请求的一部分而是作为标准数据传送给Web服务器,这就克服了GET方法中的信息无法保密和数据量太小的缺点。因此,出于安全的考虑以及对用户隐私的尊重,通常表单提交时采用POST方法。\n\n  从编程的角度来讲,如果用户通过GET方法提交数据,则数据存放在QUERY_STRING环境变量中,而POST方法提交的数据则可以从标准输入流中获取。\n\n GET与POST方法有以下区别:\n\n      1、  在客户端,Get方式在通过URL提交数据,数据在URL中可以看到;POST方式,数据放在HTTP包的body中。\n\n      2、 GET方式提交的数据大小有限制(因为浏览器对URL的长度有限制),而POST则没有此限制。\n\n      3、安全性问题。正如在(1)中提到,使用 Get 的时候,参数会显示在地址栏上,而 Post 不会。所以,如果这些数据是中文数据而且是非敏感数据,那么使用 get;如果用户输入的数据不是中文字符而且包含敏感数据,那么还是使用 post为好。\n\n      4.、服务器取值方式不一样。GET方式取值,如php可以使用$\\_GET来取得变量的值,而POST方式通过$\\_POST来获取变量的值。\n\n(3)HEAD\n\n     HEAD 方法与 GET 方法几乎是相同的,它们的区别在于 HEAD 方法只是请求消息报头,而不是完整的内容。对于 HEAD 请求的回应部分来说,它的 HTTP 头部中包含的信息与通过 GET 请求所得到的信息是相同的。利用这个方法,不必传输整个资源内容,就可以得到 Request-URI 所标识的资源的信息。这个方法通常被用于测试超链接的有效性,是否可以访问,以及最近是否更新。\n\n    要注意的是,在 HTML 文档中,书写 get 和 post,大小写都可以,但在 HTTP 协议中的 GET 和 POST 只能是大写形式。\n\n### 2\\. 请求头\n\n每个头域由一个域名,冒号(:)和域值三部分组成。域名是大小写无关的,域值前可以添加任何数量的空格符,头域可以被扩展为多行,在每行开始处,使用至少一个空格或制表符。\n\nHTTP最常见的请求头如下:\n\n#### Transport 头域\n\n\u003E Connection:\n\u003E \n\u003E 作用:表示是否需要持久连接。\n\u003E \n\u003E 如果服务器看到这里的值为“Keep-Alive”,或者看到请求使用的是HTTP 1.1(HTTP 1.1默认进行持久连接),它就可以利用持久连接的优点,当页面包含多个元素时(例如Applet,图片),显著地减少下载所需要的时间。要实现这一点,服务器需要在应答中发送一个Content-Length头,最简单的实现方法是:先把内容写入 ByteArrayOutputStream,然后在正式写出内容之前计算它的大小;\n\u003E \n\u003E 例如: Connection: keep-alive   当一个网页打开完成后,客户端和服务器之间用于传输HTTP数据的TCP连接不会关闭,如果客户端再次访问这个服务器上的  网页,会继续使用这一条已经建立的连接\n\u003E \n\u003E 例如:  Connection: close  代表一个Request完成后,客户端和服务器之间用于传输HTTP数据的TCP连接会关闭,  当客户端再次发送Request,需要重新建立TCP连接。\n\u003E \n\u003E Host(发送请求时,该报头域是必需的)\n\u003E \n\u003E Host请求报头域主要用于指定被请求资源的Internet主机和端口号,它通常从HTTP URL中提取出来的。\n\u003E \n\u003E eg:[http:\u002F\u002F;localhost\u002Findex.html](https:\u002F\u002Fwww.oschina.net\u002Faction\u002FGoToLink?url=https%3A%2F%2Fblog.csdn.net%2Findex.html) \n\u003E 浏览器发送的请求消息中,就会包含Host请求报头域,如下: \n\u003E Host:[localhos](https:\u002F\u002Fwww.oschina.net\u002Faction\u002FGoToLink?url=http%3A%2F%2Fwww.guet.edu.cn%2F)t\n\u003E \n\u003E 此处使用缺省端口号80,若指定了端口号8080,则变成:Host:localhost:8080\n\n#### Client 头域\n\n\u003E Accept:\n\u003E \n\u003E 作用:浏览器可以接受的媒体类型(MIME类型),\n\u003E \n\u003E 例如:  Accept: text\u002Fhtml  代表浏览器可以接受服务器回发的类型为 text\u002Fhtml  也就是我们常说的html文档, 如果服务器无法返回text\u002Fhtml类型的数据,服务器应该返回一个406错误(non acceptable)。\n\u003E \n\u003E 通配符 \\* 代表任意类型。例如  Accept: \\*\u002F\\*  代表浏览器可以处理所有类型,(一般浏览器发给服务器都是发这个)\n\u003E \n\u003E Accept-Encoding:\n\u003E \n\u003E 作用: 浏览器申明自己接收的编码方法,通常指定压缩方法,是否支持压缩,支持什么压缩方法(gzip,deflate),(注意:这不是只字符编码);\n\u003E \n\u003E 例如: Accept-Encoding: gzip, deflate。Server能够向支持gzip\u002Fdeflate的浏览器返回经gzip或者deflate编码的HTML页面。 许多情形下这可以减少5到10倍的下载时间,也节省带宽。\n\u003E \n\u003E Accept-Language:\n\u003E \n\u003E 作用: 浏览器申明自己接收的语言。 \n\u003E \n\u003E 语言跟字符集的区别:中文是语言,中文有多种字符集,比如big5,gb2312,gbk等等;\n\u003E \n\u003E 例如: Accept-Language:zh-cn 。如果请求消息中没有设置这个报头域,服务器假定客户端对各种语言都可以接受。\n\u003E \n\u003E User-Agent:\n\u003E \n\u003E 作用:告诉HTTP服务器, 客户端使用的操作系统和浏览器的名称和版本.\n\u003E \n\u003E 我们上网登陆论坛的时候,往往会看到一些欢迎信息,其中列出了你的操作系统的名称和版本,你所使用的浏览器的名称和版本,这往往让很多人感到很神奇,实际上, 服务器应用程序就是从User-Agent这个请求报头域中获取到这些信息User-Agent请求报头域允许客户端将它的操作系统、浏览器和其它属性告诉服务器。\n\u003E \n\u003E 例如: User-Agent: Mozilla\u002F4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident\u002F4.0; CIBA; .NET CLR 2.0.50727; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; .NET4.0C; InfoPath.2; .NET4.0E)\n\u003E \n\u003E Accept-Charset:\n\u003E \n\u003E 作用:浏览器申明自己接收的字符集,这就是本文前面介绍的各种字符集和字符编码,如gb2312,utf-8(通常我们说Charset包括了相应的字符编码方案);\n\u003E \n\u003E 例如:Accept-Charset:iso-8859-1,gb2312.如果在请求消息中没有设置这个域,缺省是任何字符集都可以接受。\n\u003E \n\u003E Authorization:授权信息,通常出现在对服务器发送的WWW-Authenticate头的应答中;\n\u003E \n\u003E Authorization请求报头域主要用于证明客户端有权查看某个资源。当浏览器访问一个页面时,如果收到服务器的响应代码为401(未授权),可以发送一个包含Authorization请求报头域的请求,要求服务器对其进行验证。\n\n#### Cookie\u002FLogin 头域\n\n\u003E Cookie:\n\u003E \n\u003E 作用: 最重要的header, 将cookie的值发送给HTTP 服务器\n\n#### Entity头域\n\n\u003E Content-Length\n\u003E \n\u003E 作用:发送给HTTP服务器数据的长度。即请求消息正文的长度;\n\u003E \n\u003E 例如: Content-Length: 38\n\u003E \n\u003E Content-Type:\n\u003E \n\u003E 作用:\n\u003E \n\u003E 例如:Content-Type: application\u002Fx-www-form-urlencoded\n\n#### Miscellaneous 头域\n\n\u003E Referer:\n\u003E \n\u003E 作用: 提供了Request的上下文信息的服务器,告诉服务器我是从哪个链接过来的,比如从我主页上链接到一个朋友那里, 他的服务器就能够从HTTP Referer中统计出每天有多少用户点击我主页上的链接访问    他的网站。\n\u003E \n\u003E 例如: Referer:http:\u002F\u002Ftranslate.google.cn\u002F?hl=zh-cn&tab=wT\n\n#### Cache 头域\n\n\u003E If-Modified-Since:\n\u003E \n\u003E 作用: 把浏览器端缓存页面的最后修改时间发送到服务器去,服务器会把这个时间与服务器上实际文件的最后修改时间进行对比。如果时间一致,那么返回304,客户端就直接使用本地缓存文件。如果时间不一致,就会返回200和新的文件内容。客户端接到之后,会丢弃旧文件,把新文件缓存起来,并显示在浏览器中。\n\u003E \n\u003E 例如:If-Modified-Since: Thu, 09 Feb 2012 09:07:57 GMT。\n\u003E \n\u003E If-None-Match:\n\u003E \n\u003E 作用: If-None-Match和ETag一起工作,工作原理是在HTTP Response中添加ETag信息。 当用户再次请求该资源时,将在HTTP Request 中加入If-None-Match信息(ETag的值)。如果服务器验证资源的ETag没有改变(该资源没有更新),将返回一个304状态告诉客户端使用本地缓存文件。否则将返回200状态和新的资源和Etag.  使用这样的机制将提高网站的性能\n\u003E \n\u003E 例如: If-None-Match: \"03f2b33c0bfcc1:0\"\n\u003E \n\u003E Pragma:\n\u003E \n\u003E 作用: 防止页面被缓存, 在HTTP\u002F1.1版本中,它和Cache-Control:no-cache作用一模一样\n\u003E \n\u003E Pargma只有一个用法, 例如: Pragma: no-cache\n\u003E \n\u003E 注意: 在HTTP\u002F1.0版本中,只实现了Pragema:no-cache, 没有实现Cache-Control\n\u003E \n\u003E Cache-Control:\n\u003E \n\u003E 作用: 这个是非常重要的规则。 这个用来指定Response-Request遵循的缓存机制。各个指令含义如下\n\u003E \n\u003E Cache-Control:Public   可以被任何缓存所缓存()\n\u003E \n\u003E Cache-Control:Private     内容只缓存到私有缓存中\n\u003E \n\u003E Cache-Control:no-cache  所有内容都不会被缓存\n\n2\\. HTTP响应格式      \n------------------\n\n      在接收和解释请求消息后,服务器会返回一个 HTTP 响应消息。与 HTTP 请求类似,HTTP 响应也是由三个部分组成,分别是:状态行、消息报头和响应正文。如:\n\nHTTP\u002F1.1 200 OK Date: Sun, 17 Mar 2013 08:12:54 GMT Server: Apache\u002F2.2.8 (Win32) PHP\u002F5.2.5 X-Powered-By: PHP\u002F5.2.5 Set-Cookie: PHPSESSID=c0huq7pdkmm5gg6osoe3mgjmm3; path=\u002F Expires: Thu, 19 Nov 1981 08:52:00 GMT Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0 Pragma: no-cache Content-Length: 4393 Keep-Alive: timeout=5, max=100 Connection: Keep-Alive Content-Type: text\u002Fhtml; charset=utf-8\n\n\u003Chtml\u003E \u003Chead\u003E \u003Ctitle\u003EHTTP响应示例\u003Ctitle\u003E \u003C\u002Fhead\u003E \u003Cbody\u003E Hello HTTP! \u003C\u002Fbody\u003E \u003C\u002Fhtml\u003E\n\n### 1、状态行\n\n       状态行由协议版本、数字形式的状态代码,及相应的状态描述组成,各元素之间以空格分隔,结尾时回车换行符,格式如下:\n\nHTTP-Version Status-Code Reason-Phrase CRLF\n\nHTTP-Version 表示服务器 HTTP 协议的版本,Status-Code 表示服务器发回的响应代码,Reason-Phrase 表示状态代码的文本描述,CRLF 表示回车换行。例如:\n\nHTTP\u002F1.1 200 OK (CRLF)\n\n      状态代码与状态描述\n\n      状态代码由 3 位数字组成, 表示请求是否被理解或被满足,状态描述给出了关于状态码的简短的文字描述。状态码的第一个数字定义了响应类别,后面两位数字没有具体分类。第一个数字有 5 种取值,如下所示。\n\n* 1xx:指示信息——表示请求已经接受,继续处理\n* 2xx:成功——表示请求已经被成功接收、理解、接受。\n* 3xx:重定向——要完成请求必须进行更进一步的操作\n* 4xx:客户端错误——客户端请求有错误或请求无法实现\n* 5xx:服务器端错误——服务器未能实现合法的请求。\n\n常见状态代码、状态描述、说明: \n200 OK      \u002F\u002F客户端请求成功\n\n303:重定向,即从原url重定向到新的url。 例如php 的hear函数header(\"localtion:\u002Findex.php\")\n\n400 Bad Request  \u002F\u002F客户端请求有语法错误,不能被服务器所理解 \n401 Unauthorized \u002F\u002F请求未经授权,这个状态代码必须和WWW-Authenticate报头域一起使用  \n403 Forbidden  \u002F\u002F服务器收到请求,但是拒绝提供服务,一般是服务器路径没有权限或者是其他权限相关问题 \n404 Not Found  \u002F\u002F请求资源不存在,eg:输入了错误的URL \n500 Internal Server Error \u002F\u002F服务器发生不可预期的错误:一般来说,这个问题都会在服务器端的源代码出现错误时出现,比如出现死循环。\n\n502 Bad Gateway\u002F\u002F作为网关或者代理工作的服务器尝试执行请求时,从上游服务器接收到无效的响应。比如LNMP ,php-fpm没有启动就会报502错误。\n\n503 Server Unavailable  \u002F\u002F服务器当前不能处理客户端的请求,一段时间后可能恢复正常,比如java 容器部署war的时候,就出现503,  \n                                           或者是nginx处理的文件没有权限。\n\n504 Gateway Time-out:作为网关或者代理工作的服务器尝试执行请求时,未能及时从上游服务器(URI标识出的服务器,例如HTTP、FTP、LDAP)或者辅助服务器(例如DNS)收到响应,比如nginx和php-fpm, php设置sleep(200),就会收到504 Gateway Time-out。注意:某些代理服务器在DNS查询超时时会返回400或者500错误\n\n### 2、响应正文\n\n响应正文就是服务器返回的资源的内容,响应头和正文之间也必须用空行分隔。如:\n\n**\\[html\\]**  [view plain](https:\u002F\u002Fwww.oschina.net\u002Faction\u002FGoToLink?url=https%3A%2F%2Fblog.csdn.net%2Fhguisu%2Farticle%2Fdetails%2F8683290%23) [copy](https:\u002F\u002Fwww.oschina.net\u002Faction\u002FGoToLink?url=https%3A%2F%2Fblog.csdn.net%2Fhguisu%2Farticle%2Fdetails%2F8683290%23)\n\n1. \u003Chtml\\\u003E \n2. \u003Chead\\\u003E \n3. \u003Ctitle\\\u003EHTTP响应示例\u003Ctitle\\\u003E \n4. \u003C\u002Fhead\\\u003E \n5. \u003Cbody\\\u003E \n6. Hello HTTP!  \n7. \u003C\u002Fbody\\\u003E \n8. \u003C\u002Fhtml\\\u003E \n\n### 3 、响应头信息\n\nHTTP最常见的响应头如下所示:\n\n#### Cache头域\n\n\u003E Date:\n\u003E \n\u003E 作用:生成消息的具体时间和日期,即当前的GMT时间。\n\u003E \n\u003E 例如: Date: Sun, 17 Mar 2013 08:12:54 GMT\n\u003E \n\u003E Expires:\n\u003E \n\u003E 作用: 浏览器会在指定过期时间内使用本地缓存,指明应该在什么时候认为文档已经过期,从而不再缓存它。\n\u003E \n\u003E 例如: Expires: Thu, 19 Nov 1981 08:52:00 GMT  \n\u003E \n\u003E Vary\n\u003E \n\u003E 作用:\n\u003E \n\u003E 例如: Vary: Accept-Encoding\n\n#### Cookie\u002FLogin 头域\n\n\u003E P3P\n\u003E \n\u003E 作用: 用于跨域设置Cookie, 这样可以解决iframe跨域访问cookie的问题\n\u003E \n\u003E 例如: P3P: CP=CURa ADMa DEVa PSAo PSDo OUR BUS UNI PUR INT DEM STA PRE COM NAV OTC NOI DSP COR\n\u003E \n\u003E Set-Cookie\n\u003E \n\u003E 作用: 非常重要的header, 用于把cookie 发送到客户端浏览器, 每一个写入cookie都会生成一个Set-Cookie.\n\u003E \n\u003E 例如: Set-Cookie: PHPSESSID=c0huq7pdkmm5gg6osoe3mgjmm3; path=\u002F\n\n#### Entity实体头域:\n\n            实体内容的属性,包括实体信息类型,长度,压缩方法,最后一次修改时间,数据有效性等。\n\n\u003E ETag:\n\u003E \n\u003E 作用:  和If-None-Match 配合使用。 (实例请看上节中If-None-Match的实例)\n\u003E \n\u003E 例如: ETag: \"03f2b33c0bfcc1:0\"\n\u003E \n\u003E Last-Modified:\n\u003E \n\u003E 作用: 用于指示资源的最后修改日期和时间。(实例请看上节的If-Modified-Since的实例)\n\u003E \n\u003E 例如: Last-Modified: Wed, 21 Dec 2011 09:09:10 GMT\n\u003E \n\u003E Content-Type:\n\u003E \n\u003E 作用:WEB服务器告诉浏览器自己响应的对象的类型和字符集,\n\u003E \n\u003E 例如:\n\u003E \n\u003E         Content-Type: text\u002Fhtml; charset=utf-8\n\u003E \n\u003E   Content-Type:text\u002Fhtml;charset=GB2312\n\u003E \n\u003E   Content-Type: image\u002Fjpeg\n\u003E \n\u003E Content-Length:\n\u003E \n\u003E 指明实体正文的长度,以字节方式存储的十进制数字来表示。在数据下行的过程中,Content-Length的方式要预先在服务器中缓存所有数据,然后所有数据再一股脑儿地发给客户端。\n\u003E \n\u003E   例如: Content-Length: 19847\n\u003E \n\u003E Content-Encoding:\n\u003E \n\u003E 作用:文档的编码(Encode)方法。一般是压缩方式。\n\u003E \n\u003E WEB服务器表明自己使用了什么压缩方法(gzip,deflate)压缩响应中的对象。利用gzip压缩文档能够显著地减少HTML文档的下载时间。\n\u003E \n\u003E 例如:Content-Encoding:gzip\n\u003E \n\u003E Content-Language:\n\u003E \n\u003E 作用: WEB服务器告诉浏览器自己响应的对象的语言者\n\u003E \n\u003E 例如: Content-Language:da\n\n#### Miscellaneous 头域\n\n\u003E Server:\n\u003E \n\u003E 作用:指明HTTP服务器的软件信息\n\u003E \n\u003E 例如:Apache\u002F2.2.8 (Win32) PHP\u002F5.2.5\n\u003E \n\u003E X-Powered-By:\n\u003E \n\u003E 作用:表示网站是用什么技术开发的\n\u003E \n\u003E 例如: X-Powered-By: PHP\u002F5.2.5\n\n#### Transport头域\n\n\u003E Connection:\n\u003E \n\u003E 例如: Connection: keep-alive   当一个网页打开完成后,客户端和服务器之间用于传输HTTP数据的TCP连接不会关闭,如果客户端再次访问这个服务器上的网页,会继续使用这一条已经建立的连接\n\u003E \n\u003E 例如:  Connection: close  代表一个Request完成后,客户端和服务器之间用于传输HTTP数据的TCP连接会关闭, 当客户端再次发送Request,需要重新建立TCP连接。\n\n#### Location头域\n\n\u003E Location:\n\u003E \n\u003E 作用: 用于重定向一个新的位置, 包含新的URL地址\n\u003E \n\u003E 实例请看304状态实例\n\n### HTTP协议是无状态的和Connection: keep-alive的区别\n\n  无状态是指协议对于事务处理没有记忆能力,服务器不知道客户端是什么状态。从另一方面讲,打开一个服务器上的网页和你之前打开这个服务器上的网页之间没有任何联系。\n\n  HTTP是一个无状态的面向连接的协议,无状态不代表HTTP不能保持TCP连接,更不能代表HTTP使用的是UDP协议(无连接)。\n\n  从HTTP\u002F1.1起,默认都开启了Keep-Alive,保持连接特性,简单地说,当一个网页打开完成后,客户端和服务器之间用于传输HTTP数据的TCP连接不会关闭,如果客户端再次访问这个服务器上的网页,会继续使用这一条已经建立的连接。\n\n  Keep-Alive不会永久保持连接,它有一个保持时间,可以在不同的服务器软件(如Apache)中设定这个时间。\n\n3. 浏览器缓存      \n--------------\n\n       浏览器缓存:包括页面html缓存和图片js,css等资源的缓存。如下图,浏览器缓存是基于把页面信息保存到用户本地电脑硬盘里。\n\n### 1、缓存的优点:\n\n     1)服务器响应更快:因为请求从缓存服务器(离客户端更近)而不是源服务器被相应,这个过程耗时更少,让服务器看上去响应更快。\n\n     2)减少网络带宽消耗:当副本被重用时会减低客户端的带宽消耗;客户可以节省带宽费用,控制带宽的需求的增长并更易于管理。\n\n### 1、缓存工作原理\n\n       页面缓存状态是由http header决定的,一个浏览器请求信息,一个是服务器响应信息。主要包括Pragma: no-cache、Cache-Control、 Expires、 Last-Modified、If-Modified-Since。其中Pragma: no-cache由HTTP\u002F1.0规定,Cache-Control由HTTP\u002F1.1规定。\n\n       工作原理图:\n\n![](http:\u002F\u002Fimg.my.csdn.net\u002Fuploads\u002F201303\u002F17\u002F1363512757_1013.png)\n\n从图中我们可以看到原理主要分三步:\n\n1. 第一次请求:浏览器通过http的header报头,附带Expires,Cache-Control,Last-Modified\u002FEtag向服务器请求,此时服务器记录第一次请求的Last-Modified\u002FEtag                  \n2. 再次请求:当浏览器再次请求的时候,请求头附带Expires,Cache-Control,If-Modified-Since\u002FEtag向服务器请求\n3. 服务器根据第一次记录的Last-Modified\u002FEtag和再次请求的If-Modified-Since\u002FEtag做对比,判断是否需要更新,服务器通过这两个头判断本地资源未发生变化,客 户端不需要重新下载,返回304响应。常见流程如下图所示:\n\n![](http:\u002F\u002Fimg.my.csdn.net\u002Fuploads\u002F201303\u002F19\u002F1363670410_3844.jpg)\n\n### 与缓存相关的HTTP扩展消息头\n\n    Expires:设置页面过期时间,格林威治时间GMT\n\n    Cache-Control:更细致的控制缓存的内容\n\n    Last-Modified:请求对象最后一次的修改时间 用来判断缓存是否过期 通常由文件的时间信息产生 \n\n    ETag:响应中资源的校验值,在服务器上某个时段是唯一标识的。ETag是一个可以 与Web资源关联的记号(token),和Last-Modified功能才不多,也是一个标识符,一般和Last-Modified一起使用,加强服务器判断的准确度。\n\n    Date:服务器的时间\n\n    If-Modified-Since:客户端存取的该资源最后一次修改的时间,用来和服务器端的Last-Modified做比较\n\n    If-None-Match:客户端存取的该资源的检验值,同ETag。\n\nCache-Control的主要参数  \n      Cache-Control: private\u002Fpublic Public 响应会被缓存,并且在多用户间共享。 Private 响应只能够作为私有的缓存,不能再用户间共享。 \n      Cache-Control: no-cache:不进行缓存  \n      Cache-Control: max-age=x:缓存时间 以秒为单位  \n      Cache-Control: must-revalidate:如果页面是过期的 则去服务器进行获取。\n\n我们nginx测试:\n\nserver { \n        listen       8081; \n        server\\_name  10.163.1.175; \n        if ($host != 'www.test1.com' ) { \n            #rewrite ^\u002F(.\\*)$ http:\u002F\u002Fwww.test1.com\u002F$1 permanent; \n        } \n        index index.html index.htm index.php; \n        root  \u002Fhome\u002Fwww\u002Fapp\u002F; \n        access\\_log  \u002Fmnt\u002Fapp\u002Fnginx\u002Flogs\u002Ftest1.home.log  main; \n        location ~ .\\*\\\\.zip?$ \n        { \n               access\\_log off; \n        } \n        location ~ .\\*\\\\.txt?$ { \n                access\\_log off; \n        } \n        location ~ .\\*\\\\.(gif|jpg|jpeg|png|bmp|swf)$ \n        { \n                expires      30d; \n        } \n        location ~ .\\*\\\\.(js|css|zip)?$ \n        { \n                expires      12h; \n        } \n        if (!-e $request\\_filename) { \n            rewrite ^\u002F(.+)$ \u002Findex.php?url=$1 last; \n            break; \n        } \n \n \n        location ~ .\\*\\\\.(php|php5)?$ \n        { \n                #fastcgi\\_pass  unix:\u002Ftmp\u002Fphp-cgi.sock; \n                fastcgi\\_pass 127.0.0.1:9000; \n                fastcgi\\_index index.php; \n                include fastcgi.conf; \n                add\\_header Content-Type text\u002Fhtml; \n        } \n}\n\n然后我们代理两个域名指向同一个端口:\n\nserver { \n    listen  80; \n    server\\_name   www.test1.com  test1.com; \n \n \n    location \u002F { \n        proxy\\_pass         http:\u002F\u002F127.0.0.1:8081; \n        proxy\\_set\\_header   Host             $host; \n        proxy\\_set\\_header   X-Real-IP        $remote\\_addr; \n        proxy\\_set\\_header   X-Forward-For    $proxy\\_add\\_x\\_forwarded\\_for; \n        proxy\\_set\\_header Access-Control-Allow-Origin \\*; \n        proxy\\_next\\_upstream http\\_502 http\\_504 error timeout invalid\\_header; \n    } \n} \nserver { \n    listen  80; \n    server\\_name   www.test2.com  test2.com; \n    location \u002F { \n        proxy\\_pass         http:\u002F\u002F127.0.0.1:8081; \n        proxy\\_set\\_header   Host             $host; \n        proxy\\_set\\_header   X-Real-IP        $remote\\_addr; \n        proxy\\_set\\_header   X-Forward-For    $proxy\\_add\\_x\\_forwarded\\_for; \n        proxy\\_set\\_header Access-Control-Allow-Origin \\*; \n        proxy\\_next\\_upstream http\\_502 http\\_504 error timeout invalid\\_header; \n    } \n}\n\n我们访问www.test2.com,直接指向www.test1.com,http是304响应。\n\n当我们把8081端口的配置去掉\n\n        if ($host != 'www.test1.com' ) { \n            #rewrite ^\u002F(.\\*)$ http:\u002F\u002Fwww.test1.com\u002F$1 permanent; \n        } \n   重启nginx,同一个访问www.test2.com,发现还是直接跳转到www.test1.com。\n\n这是因为浏览器304缓存的问题。我们直接使用新浏览器访问,就直接访问就不会跳转啦。\n\n### 2、关于图片,css,js,flash的缓存\n\n这个主要通过服务器的配置来实现这个技术,如果使用apache服务器的话,可以使用mod\\_expires模块来实现:\n\n编译mod\\_expires模块:\n\nCd  \u002Froot\u002Fhttpd-2.2.3\u002Fmodules\u002Fmetadata\n\n\u002Fusr\u002Flocal\u002Fapache\u002Fbin\u002Fapxs -i -a -c mod\\_expires.c \u002F\u002F编译\n\n编辑httpd.conf配置:添加下面内容\n\n\u003CIfModule mod\\_expires.c\u003E\n\nExpiresActive on\n\nExpiresDefault \"access plus 1 month\"\n\nExpiresByType text\u002Fhtml \"access plus 1 months\"\n\nExpiresByType text\u002Fcss \"access plus 1 months\"\n\nExpiresByType image\u002Fgif \"access plus 1 months\"\n\nExpiresByType image\u002Fjpeg \"access plus 1 months\"\n\nExpiresByType image\u002Fjpg \"access plus 1 months\"\n\nExpiresByType image\u002Fpng \"access plus 1 months\"\n\nEXpiresByType application\u002Fx-shockwave-flash \"access plus 1 months\"\n\nEXpiresByType application\u002Fx-javascript      \"access plus 1 months\"\n\n#ExpiresByType video\u002Fx-flv \"access plus 1 months\"\n\n\u003C\u002FIfModule\u003E\n\n解释:第一句--开启服务\n\n第二句--默认时间是一个月\n\n在下面是关于各种类型的资源的缓存时间设置",html:"\u003Cp\u003E  HTTP协议(HyperText Transfer Protocol,超文本传输协议)是用于从WWW服务器传输超文本到本地浏览器的传送协议。它可以使浏览器更加高效,使网络传输减少。它不仅保证计算机正确快速地传输超文本文档,还确定传输文档中的哪一部分,以及哪部分内容首先显示(如文本先于图形)等。\u003C\u002Fp\u003E\n\u003Cp\u003E         在了解HTTP如何工作之前,我们先了解计算机之间的通信。\u003C\u002Fp\u003E\n\u003Ch2 id=\"2-计算机相互之间的通信\"\u003E2. 计算机相互之间的通信\u003C\u002Fh2\u003E\n\u003Cp\u003E        互联网的关键技术就是TCP\u002FIP协议。两台计算机之间的通信是通过TCP\u002FIP协议在因特网上进行的。实际上这个是两个协议:\u003C\u002Fp\u003E\n\u003Cp\u003E        TCP : Transmission Control Protocol 传输控制协议和IP: Internet Protocol  网际协议。\u003C\u002Fp\u003E\n\u003Cp\u003E        IP:计算机之间的通信\u003C\u002Fp\u003E\n\u003Cp\u003E        IP协议是计算机用来相互识别的通信的一种机制,每台计算机都有一个IP.用来在internet上标识这台计算机。  IP 负责在因特网上发送和接收数据包。通过 IP,消息(或者其他数据)被分割为小的独立的包,并通过因特网在计算机之间传送。IP 负责将每个包路由至它的目的地。\u003C\u002Fp\u003E\n\u003Cp\u003E        IP协议仅仅是允许计算机相互发消息,但它并不检查消息是否以发送的次序到达而且没有损坏(只检查关键的头数据)。为了提供消息检验功能,直接在IP协议上设计了传输控制协议TCP.\u003C\u002Fp\u003E\n\u003Cp\u003E       TCP : 应用程序之间的通信\u003C\u002Fp\u003E\n\u003Cp\u003E       TCP确保数据包以正确的次序到达,并且尝试确认数据包的内容没有改变。TCP在IP地址之上引端口(port),它允许计算机通过网络提供各种服务。一些端口号为不同的服务保留,而且这些端口号是众所周知。\u003C\u002Fp\u003E\n\u003Cp\u003E       服务或者守护进程:在提供服务的机器上,有程序监听特定端口上的通信流。例如大多数电子邮件通信流出现在端口25上,用于wwww的HTTP通信流出现在80端口上。\u003C\u002Fp\u003E\n\u003Cp\u003E       当应用程序希望通过 TCP 与另一个应用程序通信时,它会发送一个通信请求。这个请求必须被送到一个确切的地址。在双方“握手”之后,TCP 将在两个应用程序之间建立一个全双工 (full-duplex) 的通信,占用两个计算机之间整个的通信线路。TCP 用于从应用程序到网络的数据传输控制。TCP 负责在数据传送之前将它们分割为 IP 包,然后在它们到达的时候将它们重组。\u003C\u002Fp\u003E\n\u003Cp\u003E       TCP\u002FIP 就是TCP 和 IP 两个协议在一起协同工作,有上下层次的关系。\u003C\u002Fp\u003E\n\u003Cp\u003E       TCP 负责应用软件(比如你的浏览器)和网络软件之间的通信。IP 负责计算机之间的通信。TCP 负责将数据分割并装入 IP 包,IP 负责将包发送至接收者,传输过程要经IP路由器负责根据通信量、网络中的错误或者其他参数来进行正确地寻址,然后在它们到达的时候重新组合它们。\u003C\u002Fp\u003E\n\u003Ch2 id=\"3-http协议所在的协议层\"\u003E3. HTTP协议所在的协议层\u003C\u002Fh2\u003E\n\u003Cp\u003E      HTTP是基于TCP协议之上的。在\u003Ca href=\"https:\u002F\u002Fwww.oschina.net\u002Faction\u002FGoToLink?url=http%3A%2F%2Fblog.csdn.net%2Fhguisu%2Farticle%2Fdetails%2F7249611\"\u003ETCP\u002FIP协议参考模型\u003C\u002Fa\u003E的各层对应的协议如下图,其中HTTP是应用层的协议。\u003C\u002Fp\u003E\n\u003Cp\u003E      \u003Cimg src=\"https:\u002F\u002Foscimg.oschina.net\u002Foscnet\u002Fd2fc72ac01ef5396782f9b9f7abe8deb805.jpg\" alt=\"\"\u003E\u003C\u002Fp\u003E\n\u003Ch2 id=\"4-http请求响应模型\"\u003E4. HTTP请求响应模型   \u003C\u002Fh2\u003E\n\u003Cp\u003E       HTTP由请求和响应构成,是一个标准的客户端服务器模型(B\u002FS)。HTTP协议永远都是客户端发起请求,服务器回送响应。见下图:\u003C\u002Fp\u003E\n\u003Cp\u003E    \u003Cimg src=\"http:\u002F\u002Fimg.my.csdn.net\u002Fuploads\u002F201303\u002F16\u002F1363438271_3285.jpg\" alt=\"\"\u003E\u003C\u002Fp\u003E\n\u003Cp\u003E       HTTP是一个无状态的协议。无状态是指客户机(Web浏览器)和服务器之间不需要建立持久的连接,这意味着当一个客户端向服务器端发出请求,然后服务器返回响应(response),连接就被关闭了,在服务器端不保留连接的有关信息.HTTP遵循请求(Request)\u002F应答(Response)模型。客户机(浏览器)向服务器发送请求,服务器处理请求并返回适当的应答。所有HTTP连接都被构造成一套请求和应答。\u003C\u002Fp\u003E\n\u003Ch2 id=\"5-http工作过程\"\u003E5. HTTP工作过程      \u003C\u002Fh2\u003E\n\u003Cp\u003E     一次HTTP操作称为一个事务,其工作整个过程如下:\u003C\u002Fp\u003E\n\u003Cp\u003E     1 ) 、地址解析,\u003C\u002Fp\u003E\n\u003Cp\u003E     如用客户端浏览器请求这个页面:\u003Ca href=\"https:\u002F\u002Fwww.oschina.net\u002Faction\u002FGoToLink?url=http%3A%2F%2Flocalhost%3A8080%2Fsimple.htm\"\u003Ehttp:\u002F\u002Flocalhost.com:8080\u002Findex.htm\u003C\u002Fa\u003E\u003C\u002Fp\u003E\n\u003Cp\u003E     从中分解出协议名、主机名、端口、对象路径等部分,对于我们的这个地址,解析得到的结果如下:\u003Cbr\u003E     协议名:http\u003Cbr\u003E     主机名:localhost.com\u003Cbr\u003E     端口:8080\u003Cbr\u003E     对象路径:\u002Findex.htm\u003C\u002Fp\u003E\n\u003Cp\u003E      在这一步,需要域名系统DNS解析域名localhost.com,得主机的IP地址。\u003C\u002Fp\u003E\n\u003Cp\u003E    2)、封装HTTP请求数据包\u003C\u002Fp\u003E\n\u003Cp\u003E     把以上部分结合本机自己的信息,封装成一个HTTP请求数据包\u003C\u002Fp\u003E\n\u003Cp\u003E     3)封装成TCP包,建立TCP连接(TCP的三次握手)\u003C\u002Fp\u003E\n\u003Cp\u003E       在HTTP工作开始之前,客户机(Web浏览器)首先要通过网络与服务器建立连接,该连接是通过TCP来完成的,该协议与IP协议共同构建Internet,即著名的TCP\u002FIP协议族,因此Internet又被称作是TCP\u002FIP网络。HTTP是比TCP更高层次的应用层协议,根据规则,只有低层协议建立之后才能进行更高层协议的连接,因此,首先要建立TCP连接,一般TCP连接的端口号是80。这里是8080端口\u003C\u002Fp\u003E\n\u003Cp\u003E     4)客户机发送请求命令\u003C\u002Fp\u003E\n\u003Cp\u003E       建立连接后,客户机发送一个请求给服务器,请求方式的格式为:统一资源标识符(URI:Uniform Resource Identifier)、协议版本号,后边是MIME信息包括请求修饰符、客户机信息和可能的内容。\u003C\u002Fp\u003E\n\u003Cp\u003E     5)服务器响应\u003C\u002Fp\u003E\n\u003Cp\u003E     服务器接到请求后,给予相应的响应信息,其格式为一个状态行,包括信息的协议版本号、一个成功或错误的代码,后边是MIME信息包括服务器信息、实体信息和可能的内容。\u003C\u002Fp\u003E\n\u003Cp\u003E        实体消息是服务器向浏览器发送头信息后,它会发送一个空白行来表示头信息的发送到此结束,接着,它就以Content-Type应答头信息所描述的格式发送用户所请求的实际数据\u003C\u002Fp\u003E\n\u003Cp\u003E     6)服务器关闭TCP连接\u003C\u002Fp\u003E\n\u003Cp\u003E     一般情况下,一旦Web服务器向浏览器发送了请求数据,它就要关闭TCP连接,然后如果浏览器或者服务器在其头信息加入了这行代码\u003C\u002Fp\u003E\n\u003Cp\u003E    Connection:keep-alive\u003C\u002Fp\u003E\n\u003Cp\u003E   TCP连接在发送后将仍然保持打开状态,于是,浏览器可以继续通过相同的连接发送请求。保持连接节省了为每个请求建立新连接所需的时间,还节约了网络带宽。\u003C\u002Fp\u003E\n\u003Cp\u003E6. HTTP协议栈中各层数据流 \u003C\u002Fp\u003E\n\u003Cp\u003E 首先我们看看客户端请求的时候,数据在各层协议的数据组织如下图:\u003C\u002Fp\u003E\n\u003Cp\u003E         \u003Cimg src=\"https:\u002F\u002Foscimg.oschina.net\u002Foscnet\u002F57e06790690d39bceeab32e75919869ba76.jpg\" alt=\"\"\u003E\u003C\u002Fp\u003E\n\u003Cp\u003E            而服务器解析客户机请求就是反向操作的过程,如下图:\u003C\u002Fp\u003E\n\u003Cp\u003E           \u003Cimg src=\"https:\u002F\u002Foscimg.oschina.net\u002Foscnet\u002Fe5a0c0533ac66a3ac58caabda1fc67ea396.jpg\" alt=\"\"\u003E\u003C\u002Fp\u003E\n\u003Cp\u003E       客户机发起一次请求的时候:\u003C\u002Fp\u003E\n\u003Cp\u003E       客户机会将请求封装成http数据包-->封装成Tcp数据包-->封装成Ip数据包--->封装成数据帧--->硬件将帧数据转换成bit流(二进制数据)-->最后通过物理硬件(网卡芯片)发送到指定地点。\u003C\u002Fp\u003E\n\u003Cp\u003E       服务器硬件首先收到bit流....... 然后转换成ip数据包。于是通过ip协议解析Ip数据包,然后又发现里面是tcp数据包,就通过tcp协议解析Tcp数据包,接着发现是http数据包通过http协议再解析http数据包得到数据。\u003C\u002Fp\u003E\n\u003Ch2 id=\"6-https实现原理\"\u003E6. HTTPS实现原理    \u003C\u002Fh2\u003E\n\u003Cp\u003E      HTTPS(全称:Hypertext Transfer Protocol over Secure Socket Layer),是以安全为目标的HTTP通道,简单讲是HTTP的安全版。即HTTP下加入SSL层,HTTPS的安全基础是SSL。其所用的端口号是443。\u003C\u002Fp\u003E\n\u003Cp\u003E      SSL:安全套接层,是netscape公司设计的主要用于web的安全传输协议。这种协议在WEB上获得了广泛的应用。通过证书认证来确保客户端和网站服务器之间的通信数据是加密安全的。\u003C\u002Fp\u003E\n\u003Cp\u003E      有两种基本的加解密\u003Ca href=\"https:\u002F\u002Fwww.oschina.net\u002Faction\u002FGoToLink?url=http%3A%2F%2Flib.csdn.net%2Fbase%2Fdatastructure\"\u003E算法\u003C\u002Fa\u003E类型:\u003C\u002Fp\u003E\n\u003Cp\u003E      1)对称加密(symmetric encryption):密钥只有一个,加密解密为同一个密码,且加解密速度快,典型的对称加密\u003Ca href=\"https:\u002F\u002Fwww.oschina.net\u002Faction\u002FGoToLink?url=http%3A%2F%2Flib.csdn.net%2Fbase%2Fdatastructure\"\u003E算法\u003C\u002Fa\u003E有DES、AES,RC5,3DES等;\u003C\u002Fp\u003E\n\u003Cp\u003E       对称加密主要问题是共享秘钥,除你的计算机(客户端)知道另外一台计算机(服务器)的私钥秘钥,否则无法对通信流进行加密解密。解决这个问题的方案非对称秘钥。\u003C\u002Fp\u003E\n\u003Cp\u003E      2)非对称加密:使用两个秘钥:公共秘钥和私有秘钥。私有秘钥由一方密码保存(一般是服务器保存),另一方任何人都可以获得公共秘钥。\u003C\u002Fp\u003E\n\u003Cp\u003E      这种密钥成对出现(且根据公钥无法推知私钥,根据私钥也无法推知公钥),加密解密使用不同密钥(公钥加密需要私钥解密),相对对称加密速度较慢,典型的非对称加密算法有RSA、DSA等。\u003C\u002Fp\u003E\n\u003Cp\u003E  下面看一下https的通信过程:\u003C\u002Fp\u003E\n\u003Cp\u003E        过程大致如下:\u003C\u002Fp\u003E\n\u003Cp\u003E        1) SSL客户端通过TCP和服务器建立连接之后(443端口),并且在一般的tcp连接协商(握手)过程中请求证书。\u003C\u002Fp\u003E\n\u003Cp\u003E              即客户端发出一个消息给服务器,这个消息里面包含了自己可实现的算法列表和其它一些需要的消息,SSL的服务器端会回应一个数据包,这里面确定了这次通信所需要的算法,然后服务器向客户端返回证书。(证书里面包含了服务器信息:域名。申请证书的公司,公共秘钥)。                 \u003C\u002Fp\u003E\n\u003Cp\u003E       2)Client在收到服务器返回的证书后,判断签发这个证书的公共签发机构,并使用这个机构的公共秘钥确认签名是否有效,客户端还会确保证书中列出的域名就是它正在连接的域名。\u003C\u002Fp\u003E\n\u003Cp\u003E       3)  如果确认证书有效,那么生成对称秘钥并使用服务器的公共秘钥进行加密。然后发送给服务器,服务器使用它的私钥对它进行解密,这样两台计算机可以开始进行对称加密进行通信。\u003C\u002Fp\u003E\n\u003Cp\u003E  https通信的优点:\u003C\u002Fp\u003E\n\u003Cp\u003E  1)客户端产生的密钥只有客户端和服务器端能得到;\u003C\u002Fp\u003E\n\u003Cp\u003E  2)加密的数据只有客户端和服务器端才能得到明文;\u003C\u002Fp\u003E\n\u003Cp\u003E  3)客户端到服务端的通信是安全的。\u003C\u002Fp\u003E\n\u003Ch2 id=\"7-http各种长度限制\"\u003E7. HTTP各种长度限制   \u003C\u002Fh2\u003E\n\u003Ch3 id=\"1-uri长度限制\"\u003E1. URI长度限制\u003C\u002Fh3\u003E\n\u003Cp\u003E  在Http1.1协议中并没有提出针对URI的长度进行限制,RFC协议里面是这样描述的,HTTP协议并不对URI的长度做任何的限制,服务器端必须能够处理任何它们所提供服务多能接受的URI,并且能够处理无限长度的URI,如果服务器不能处理过长的URI,那么应该返回414状态码。\u003C\u002Fp\u003E\n\u003Cp\u003E  虽然Http协议规定了,但是Web服务器和浏览器对URI都有自己的长度限制。\u003C\u002Fp\u003E\n\u003Cp\u003E  服务器的限制:我接触的最多的服务器类型就是Nginx和Tomcat,对于url的长度限制,它们都是通过控制http请求头的长度来进行限制的,nginx的配置参数为large_client_header_buffers,tomcat的请求配置参数为maxHttpHeaderSize,都是可以自己去进行设置。\u003C\u002Fp\u003E\n\u003Cp\u003E  浏览器的限制:每种浏览器也会对url的长度有所限制,下面是几种常见浏览器的url长度限制:(单位:字符)\u003C\u002Fp\u003E\n\u003Cp\u003E  IE : 2803\u003C\u002Fp\u003E\n\u003Cp\u003E  Firefox:65536\u003C\u002Fp\u003E\n\u003Cp\u003E  Chrome:8182\u003C\u002Fp\u003E\n\u003Cp\u003E  Safari:80000\u003C\u002Fp\u003E\n\u003Cp\u003E  Opera:190000\u003C\u002Fp\u003E\n\u003Cp\u003E  对于get请求,在url的长度限制范围之内,请求的参数个数没有限制。\u003C\u002Fp\u003E\n\u003Ch3 id=\"2-post数据的长度限制\"\u003E2. Post数据的长度限制\u003C\u002Fh3\u003E\n\u003Cp\u003E  Post数据的长度限制与url长度限制类似,也是在Http协议中没有规定长度限制,长度限制可以在服务器端配置最大http请求头长度的方式来实现。\u003C\u002Fp\u003E\n\u003Ch3 id=\"3-cookie的长度限制\"\u003E3. Cookie的长度限制\u003C\u002Fh3\u003E\n\u003Cp\u003E  Cookie的长度限制分这么几个方面来总结。\u003C\u002Fp\u003E\n\u003Cp\u003E  (1) 浏览器所允许的每个域下的最大cookie数目,没有去自己测试,从网上找到的资料大概是这么个情况\u003C\u002Fp\u003E\n\u003Cp\u003E  IE :原先为20个,后来升级为50个\u003C\u002Fp\u003E\n\u003Cp\u003E  Firefox: 50个\u003C\u002Fp\u003E\n\u003Cp\u003E  Opera:30个\u003C\u002Fp\u003E\n\u003Cp\u003E  Chrome:180个\u003C\u002Fp\u003E\n\u003Cp\u003E  Safari:无限制\u003C\u002Fp\u003E\n\u003Cp\u003E  当Cookie数超过限制数时浏览器的行为:IE和Opera会采用LRU算法将老的不常使用的Cookie清除掉,Firefox的行为是随机踢出某些Cookie的值。当然无论怎样的策略,还是尽量不要让Cookie数目超过浏览器所允许的范围。\u003C\u002Fp\u003E\n\u003Cp\u003E(2) 浏览器所允许的每个Cookie的最大长度\u003C\u002Fp\u003E\n\u003Cp\u003E  Firefox和Safari:4079字节\u003C\u002Fp\u003E\n\u003Cp\u003E  Opera:4096字节\u003C\u002Fp\u003E\n\u003Cp\u003E  IE:4095字节\u003C\u002Fp\u003E\n\u003Cp\u003E(3) 服务器中Http请求头长度的限制。Cookie会被附在每次http请求头中传递给服务器,因此还会受到服务器请求头长度的影响。\u003C\u002Fp\u003E\n\u003Ch3 id=\"4-html5-localstorage\"\u003E4. Html5 LocalStorage\u003C\u002Fh3\u003E\n\u003Cp\u003EHtml5提供了本地存储机制来供Web应用在客户端存储数据,尽管这个并不属于Http协议的一部分,但是随着Html5的流行,我们可能需要越来越多使用LocalStorage,甚至当它普及的时候跟它打交道就会同今天我们跟Cookie打交道一样多。\u003C\u002Fp\u003E\n\u003Cp\u003E对于LocalStorage的长度限制,同Cookie的限制类似,也是浏览器针对域来限制,只不过cookie限制的是个数,LocalStorage限制的是长度:\u003C\u002Fp\u003E\n\u003Cp\u003EFirefox\\Chrome\\Opera都是允许每个域的最大长度为5MB\u003C\u002Fp\u003E\n\u003Cp\u003E但是这次IE比较大方,允许的最大长度是10MB\u003C\u002Fp\u003E\n\u003Cp\u003E客户端通过发送 HTTP 请求向服务器请求对资源的访问。 它向服务器传递了一个数据块,也就是请求信息,HTTP 请求由三部分组成:请求行、  请求头和请求正文。\u003C\u002Fp\u003E\n\u003Cp\u003E 请求行:请求方法 URI 协议\u002F版本\u003C\u002Fp\u003E\n\u003Cp\u003E  请求头(Request Header)\u003C\u002Fp\u003E\n\u003Cp\u003E 请求正文\u003C\u002Fp\u003E\n\u003Cp\u003E下面是一个HTTP请求的数据:\u003C\u002Fp\u003E\n\u003Cpre\u003E\u003Ccode\u003EPOST \u002Findex.php HTTP\u002F1.1\nHost: localhost\nUser-Agent: Mozilla\u002F5.0 (Windows NT 5.1; rv:10.0.2) Gecko\u002F20100101 Firefox\u002F10.0.2\nAccept: text\u002Fhtml,application\u002Fxhtml+xml,application\u002Fxml;q=0.9,*\u002F*;q=0.8\nAccept-Language: zh-cn,zh;q=0.5\nAccept-Encoding: gzip, deflate\nConnection: keep-alive\nReferer: http:\u002F\u002Flocalhost\u002F\nContent-Length:25\nContent-Type:application\u002Fx-www-form-urlencoded\nusername=aa&password=1234\n\u003C\u002Fcode\u003E\u003C\u002Fpre\u003E\n\u003Ch3 id=\"1、请求行:请求方法uri协议版本\"\u003E1、请求行:请求方法URI协议\u002F版本\u003C\u002Fh3\u003E\n\u003Cp\u003E 请求的第一行是“方法 URL  协议\u002F版本”,并以 回车换行作为结尾。请求行以空格分隔。格式如下:\u003C\u002Fp\u003E\n\u003Cp\u003EPOST \u002Findex.php HTTP\u002F1.1\u003C\u002Fp\u003E\n\u003Cp\u003E以上代码中“GET”代表请求方法,“\u002F\u002Fndex.php”表示URI,“HTTP\u002F1.1代表协议和协议的版本。\u003C\u002Fp\u003E\n\u003Cp\u003E        根据HTTP标准,HTTP请求可以使用多种请求方法。例如:HTTP1.1支持7种请求方法:GET、POST、HEAD、OPTIONS、PUT、DELETE和TARCE。在Internet应用中,最常用的方法是GET和POST。\u003C\u002Fp\u003E\n\u003Cp\u003E         URL完整地指定了要访问的网络资源,通常只要给出相对于服务器的根目录的相对目录即可,因此总是以“\u002F”开头,最后,协议版本声明了通信过程中使用HTTP的版本。   \u003C\u002Fp\u003E\n\u003Ch4 id=\"请求方法\"\u003E请求方法\u003C\u002Fh4\u003E\n\u003Cp\u003E在 HTTP 协议中,HTTP 请求可以使用多种请求方法,这些方法指明了要以何种方式来访问 Request-URI 所标识的资源。HTTP1.1 支持的请求方法如下表所示:\u003C\u002Fp\u003E\n\u003Cp\u003EHTTP1.1 中的请求方式:\u003C\u002Fp\u003E\n\u003Cp\u003E方法\u003C\u002Fp\u003E\n\u003Cp\u003E作用\u003C\u002Fp\u003E\n\u003Cp\u003EGET\u003C\u002Fp\u003E\n\u003Cp\u003E请求获取由 Request-URI 所标识的资源\u003C\u002Fp\u003E\n\u003Cp\u003EPOST\u003C\u002Fp\u003E\n\u003Cp\u003E请求服务器接收在请求中封装的实体,并将其作为由 Request-Line 中的 Request-URI 所标识的资源的一部分\u003C\u002Fp\u003E\n\u003Cp\u003EHEAD\u003C\u002Fp\u003E\n\u003Cp\u003E请求获取由 Request-URI 所标识的资源的响应消息报头\u003C\u002Fp\u003E\n\u003Cp\u003EPUT\u003C\u002Fp\u003E\n\u003Cp\u003E请求服务器存储一个资源,并用 Request-URI 作为其标识符\u003C\u002Fp\u003E\n\u003Cp\u003EDELETE\u003C\u002Fp\u003E\n\u003Cp\u003E请求服务器删除由 Request-URI 所标识的资源\u003C\u002Fp\u003E\n\u003Cp\u003ETRACE\u003C\u002Fp\u003E\n\u003Cp\u003E请求服务器回送到的请求信息,主要用于测试或诊断\u003C\u002Fp\u003E\n\u003Cp\u003ECONNECT\u003C\u002Fp\u003E\n\u003Cp\u003E保留将来使用\u003C\u002Fp\u003E\n\u003Cp\u003EOPTIONS\u003C\u002Fp\u003E\n\u003Cp\u003E请求查询服务器的性能,或者查询与资源相关的选项和需求\u003C\u002Fp\u003E\n\u003Cp\u003E重点介绍 GET、POST 和 HEAD 三个方法:\u003C\u002Fp\u003E\n\u003Cp\u003E(1)GET\u003C\u002Fp\u003E\n\u003Cp\u003E        GET 方法用于获取由 Request-URI 所标识的资源的信息,常见的形式是:\u003C\u002Fp\u003E\n\u003Cp\u003E        GET Request-URI HTTP\u002F1.1\u003Cbr\u003E        GET方法是默认的HTTP请求方法,例如当我们通过在浏览器的地址栏中直接输入网址的方式去访问网页的时候,浏览器采用的就是 GET 方法向服务器获取资源。\u003C\u002Fp\u003E\n\u003Cp\u003E        我们可以使用GET方法来提交表单数据,用GET方法提交的表单数据只经过了简单的编码,同时它将作为URL的一部分向服务器发送,因此,如果使用GET方法来提交表单数据就存在着安全隐患上。例如:\u003Cbr\u003E         \u003Ca href=\"https:\u002F\u002Fwww.oschina.net\u002Faction\u002FGoToLink?url=http%3A%2F%2F127.0.0.1%2Flogin.jsp%3FName%3Dzhangshi%26Age%3D30%26Submit%3D%25CC%2525E%2B%25BD%25BB\"\u003EHttp:\u002F\u002Flocalhost\u002Flogin.php?username=aa&password=1234\u003C\u002Fa\u003E\u003C\u002Fp\u003E\n\u003Cp\u003E        从上面的URL请求中,很容易就可以辩认出表单提交的内容。(?之后的内容)另外由于GET方法提交的数据是作为URL请求的一部分所以提交的数据量不能太大。这是因为浏览器对url的长度有限制\u003C\u002Fp\u003E\n\u003Cp\u003E       各种浏览器也会对url的长度有所限制,下面是几种常见浏览器的url长度限制:(单位:字符)\u003C\u002Fp\u003E\n\u003Cp\u003EIE : 2803\u003C\u002Fp\u003E\n\u003Cp\u003EFirefox:65536\u003C\u002Fp\u003E\n\u003Cp\u003EChrome:8182\u003C\u002Fp\u003E\n\u003Cp\u003ESafari:80000\u003C\u002Fp\u003E\n\u003Cp\u003EOpera:190000 \u003C\u002Fp\u003E\n\u003Cp\u003E(2)POST\u003C\u002Fp\u003E\n\u003Cp\u003E          POST方法是GET方法的一个替代方法,它主要是向Web服务器提交表单数据,尤其是大批量的数据。 在请求头信息结束之后的两个回车换行之后(实际是空一行),就是表单提交的数据。如上面提到的post表单数据:\u003C\u002Fp\u003E\n\u003Cp\u003E        username=aa&password=1234\u003C\u002Fp\u003E\n\u003Cp\u003E        POST方法克服了GET方法的一些缺点。通过POST方法提交表单数据时,数据不是作为URL请求的一部分而是作为标准数据传送给Web服务器,这就克服了GET方法中的信息无法保密和数据量太小的缺点。因此,出于安全的考虑以及对用户隐私的尊重,通常表单提交时采用POST方法。\u003C\u002Fp\u003E\n\u003Cp\u003E  从编程的角度来讲,如果用户通过GET方法提交数据,则数据存放在QUERY_STRING环境变量中,而POST方法提交的数据则可以从标准输入流中获取。\u003C\u002Fp\u003E\n\u003Cp\u003E GET与POST方法有以下区别:\u003C\u002Fp\u003E\n\u003Cp\u003E      1、  在客户端,Get方式在通过URL提交数据,数据在URL中可以看到;POST方式,数据放在HTTP包的body中。\u003C\u002Fp\u003E\n\u003Cp\u003E      2、 GET方式提交的数据大小有限制(因为浏览器对URL的长度有限制),而POST则没有此限制。\u003C\u002Fp\u003E\n\u003Cp\u003E      3、安全性问题。正如在(1)中提到,使用 Get 的时候,参数会显示在地址栏上,而 Post 不会。所以,如果这些数据是中文数据而且是非敏感数据,那么使用 get;如果用户输入的数据不是中文字符而且包含敏感数据,那么还是使用 post为好。\u003C\u002Fp\u003E\n\u003Cp\u003E      4.、服务器取值方式不一样。GET方式取值,如php可以使用$_GET来取得变量的值,而POST方式通过$_POST来获取变量的值。\u003C\u002Fp\u003E\n\u003Cp\u003E(3)HEAD\u003C\u002Fp\u003E\n\u003Cp\u003E     HEAD 方法与 GET 方法几乎是相同的,它们的区别在于 HEAD 方法只是请求消息报头,而不是完整的内容。对于 HEAD 请求的回应部分来说,它的 HTTP 头部中包含的信息与通过 GET 请求所得到的信息是相同的。利用这个方法,不必传输整个资源内容,就可以得到 Request-URI 所标识的资源的信息。这个方法通常被用于测试超链接的有效性,是否可以访问,以及最近是否更新。\u003C\u002Fp\u003E\n\u003Cp\u003E    要注意的是,在 HTML 文档中,书写 get 和 post,大小写都可以,但在 HTTP 协议中的 GET 和 POST 只能是大写形式。\u003C\u002Fp\u003E\n\u003Ch3 id=\"2-请求头\"\u003E2. 请求头\u003C\u002Fh3\u003E\n\u003Cp\u003E每个头域由一个域名,冒号(:)和域值三部分组成。域名是大小写无关的,域值前可以添加任何数量的空格符,头域可以被扩展为多行,在每行开始处,使用至少一个空格或制表符。\u003C\u002Fp\u003E\n\u003Cp\u003EHTTP最常见的请求头如下:\u003C\u002Fp\u003E\n\u003Ch4 id=\"transport-头域\"\u003ETransport 头域\u003C\u002Fh4\u003E\n\u003Cblockquote\u003E\n\u003Cp\u003EConnection:\u003C\u002Fp\u003E\n\u003Cp\u003E作用:表示是否需要持久连接。\u003C\u002Fp\u003E\n\u003Cp\u003E如果服务器看到这里的值为“Keep-Alive”,或者看到请求使用的是HTTP 1.1(HTTP 1.1默认进行持久连接),它就可以利用持久连接的优点,当页面包含多个元素时(例如Applet,图片),显著地减少下载所需要的时间。要实现这一点,服务器需要在应答中发送一个Content-Length头,最简单的实现方法是:先把内容写入 ByteArrayOutputStream,然后在正式写出内容之前计算它的大小;\u003C\u002Fp\u003E\n\u003Cp\u003E例如: Connection: keep-alive   当一个网页打开完成后,客户端和服务器之间用于传输HTTP数据的TCP连接不会关闭,如果客户端再次访问这个服务器上的  网页,会继续使用这一条已经建立的连接\u003C\u002Fp\u003E\n\u003Cp\u003E例如:  Connection: close  代表一个Request完成后,客户端和服务器之间用于传输HTTP数据的TCP连接会关闭,  当客户端再次发送Request,需要重新建立TCP连接。\u003C\u002Fp\u003E\n\u003Cp\u003EHost(发送请求时,该报头域是必需的)\u003C\u002Fp\u003E\n\u003Cp\u003EHost请求报头域主要用于指定被请求资源的Internet主机和端口号,它通常从HTTP URL中提取出来的。\u003C\u002Fp\u003E\n\u003Cp\u003Eeg:\u003Ca href=\"https:\u002F\u002Fwww.oschina.net\u002Faction\u002FGoToLink?url=https%3A%2F%2Fblog.csdn.net%2Findex.html\"\u003Ehttp:\u002F\u002F;localhost\u002Findex.html\u003C\u002Fa\u003E\u003Cbr\u003E浏览器发送的请求消息中,就会包含Host请求报头域,如下:\u003Cbr\u003EHost:\u003Ca href=\"https:\u002F\u002Fwww.oschina.net\u002Faction\u002FGoToLink?url=http%3A%2F%2Fwww.guet.edu.cn%2F\"\u003Elocalhos\u003C\u002Fa\u003Et\u003C\u002Fp\u003E\n\u003Cp\u003E此处使用缺省端口号80,若指定了端口号8080,则变成:Host:localhost:8080\u003C\u002Fp\u003E\n\u003C\u002Fblockquote\u003E\n\u003Ch4 id=\"client-头域\"\u003EClient 头域\u003C\u002Fh4\u003E\n\u003Cblockquote\u003E\n\u003Cp\u003EAccept:\u003C\u002Fp\u003E\n\u003Cp\u003E作用:浏览器可以接受的媒体类型(MIME类型),\u003C\u002Fp\u003E\n\u003Cp\u003E例如:  Accept: text\u002Fhtml  代表浏览器可以接受服务器回发的类型为 text\u002Fhtml  也就是我们常说的html文档, 如果服务器无法返回text\u002Fhtml类型的数据,服务器应该返回一个406错误(non acceptable)。\u003C\u002Fp\u003E\n\u003Cp\u003E通配符 * 代表任意类型。例如  Accept: *\u002F*  代表浏览器可以处理所有类型,(一般浏览器发给服务器都是发这个)\u003C\u002Fp\u003E\n\u003Cp\u003EAccept-Encoding:\u003C\u002Fp\u003E\n\u003Cp\u003E作用: 浏览器申明自己接收的编码方法,通常指定压缩方法,是否支持压缩,支持什么压缩方法(gzip,deflate),(注意:这不是只字符编码);\u003C\u002Fp\u003E\n\u003Cp\u003E例如: Accept-Encoding: gzip, deflate。Server能够向支持gzip\u002Fdeflate的浏览器返回经gzip或者deflate编码的HTML页面。 许多情形下这可以减少5到10倍的下载时间,也节省带宽。\u003C\u002Fp\u003E\n\u003Cp\u003EAccept-Language:\u003C\u002Fp\u003E\n\u003Cp\u003E作用: 浏览器申明自己接收的语言。 \u003C\u002Fp\u003E\n\u003Cp\u003E语言跟字符集的区别:中文是语言,中文有多种字符集,比如big5,gb2312,gbk等等;\u003C\u002Fp\u003E\n\u003Cp\u003E例如: Accept-Language:zh-cn 。如果请求消息中没有设置这个报头域,服务器假定客户端对各种语言都可以接受。\u003C\u002Fp\u003E\n\u003Cp\u003EUser-Agent:\u003C\u002Fp\u003E\n\u003Cp\u003E作用:告诉HTTP服务器, 客户端使用的操作系统和浏览器的名称和版本.\u003C\u002Fp\u003E\n\u003Cp\u003E我们上网登陆论坛的时候,往往会看到一些欢迎信息,其中列出了你的操作系统的名称和版本,你所使用的浏览器的名称和版本,这往往让很多人感到很神奇,实际上, 服务器应用程序就是从User-Agent这个请求报头域中获取到这些信息User-Agent请求报头域允许客户端将它的操作系统、浏览器和其它属性告诉服务器。\u003C\u002Fp\u003E\n\u003Cp\u003E例如: User-Agent: Mozilla\u002F4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident\u002F4.0; CIBA; .NET CLR 2.0.50727; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; .NET4.0C; InfoPath.2; .NET4.0E)\u003C\u002Fp\u003E\n\u003Cp\u003EAccept-Charset:\u003C\u002Fp\u003E\n\u003Cp\u003E作用:浏览器申明自己接收的字符集,这就是本文前面介绍的各种字符集和字符编码,如gb2312,utf-8(通常我们说Charset包括了相应的字符编码方案);\u003C\u002Fp\u003E\n\u003Cp\u003E例如:Accept-Charset:iso-8859-1,gb2312.如果在请求消息中没有设置这个域,缺省是任何字符集都可以接受。\u003C\u002Fp\u003E\n\u003Cp\u003EAuthorization:授权信息,通常出现在对服务器发送的WWW-Authenticate头的应答中;\u003C\u002Fp\u003E\n\u003Cp\u003EAuthorization请求报头域主要用于证明客户端有权查看某个资源。当浏览器访问一个页面时,如果收到服务器的响应代码为401(未授权),可以发送一个包含Authorization请求报头域的请求,要求服务器对其进行验证。\u003C\u002Fp\u003E\n\u003C\u002Fblockquote\u003E\n\u003Ch4 id=\"cookielogin-头域\"\u003ECookie\u002FLogin 头域\u003C\u002Fh4\u003E\n\u003Cblockquote\u003E\n\u003Cp\u003ECookie:\u003C\u002Fp\u003E\n\u003Cp\u003E作用: 最重要的header, 将cookie的值发送给HTTP 服务器\u003C\u002Fp\u003E\n\u003C\u002Fblockquote\u003E\n\u003Ch4 id=\"entity头域\"\u003EEntity头域\u003C\u002Fh4\u003E\n\u003Cblockquote\u003E\n\u003Cp\u003EContent-Length\u003C\u002Fp\u003E\n\u003Cp\u003E作用:发送给HTTP服务器数据的长度。即请求消息正文的长度;\u003C\u002Fp\u003E\n\u003Cp\u003E例如: Content-Length: 38\u003C\u002Fp\u003E\n\u003Cp\u003EContent-Type:\u003C\u002Fp\u003E\n\u003Cp\u003E作用:\u003C\u002Fp\u003E\n\u003Cp\u003E例如:Content-Type: application\u002Fx-www-form-urlencoded\u003C\u002Fp\u003E\n\u003C\u002Fblockquote\u003E\n\u003Ch4 id=\"miscellaneous-头域\"\u003EMiscellaneous 头域\u003C\u002Fh4\u003E\n\u003Cblockquote\u003E\n\u003Cp\u003EReferer:\u003C\u002Fp\u003E\n\u003Cp\u003E作用: 提供了Request的上下文信息的服务器,告诉服务器我是从哪个链接过来的,比如从我主页上链接到一个朋友那里, 他的服务器就能够从HTTP Referer中统计出每天有多少用户点击我主页上的链接访问    他的网站。\u003C\u002Fp\u003E\n\u003Cp\u003E例如: Referer:\u003Ca href=\"http:\u002F\u002Ftranslate.google.cn\u002F?hl=zh-cn&tab=wT\"\u003Ehttp:\u002F\u002Ftranslate.google.cn\u002F?hl=zh-cn&tab=wT\u003C\u002Fa\u003E\u003C\u002Fp\u003E\n\u003C\u002Fblockquote\u003E\n\u003Ch4 id=\"cache-头域\"\u003ECache 头域\u003C\u002Fh4\u003E\n\u003Cblockquote\u003E\n\u003Cp\u003EIf-Modified-Since:\u003C\u002Fp\u003E\n\u003Cp\u003E作用: 把浏览器端缓存页面的最后修改时间发送到服务器去,服务器会把这个时间与服务器上实际文件的最后修改时间进行对比。如果时间一致,那么返回304,客户端就直接使用本地缓存文件。如果时间不一致,就会返回200和新的文件内容。客户端接到之后,会丢弃旧文件,把新文件缓存起来,并显示在浏览器中。\u003C\u002Fp\u003E\n\u003Cp\u003E例如:If-Modified-Since: Thu, 09 Feb 2012 09:07:57 GMT。\u003C\u002Fp\u003E\n\u003Cp\u003EIf-None-Match:\u003C\u002Fp\u003E\n\u003Cp\u003E作用: If-None-Match和ETag一起工作,工作原理是在HTTP Response中添加ETag信息。 当用户再次请求该资源时,将在HTTP Request 中加入If-None-Match信息(ETag的值)。如果服务器验证资源的ETag没有改变(该资源没有更新),将返回一个304状态告诉客户端使用本地缓存文件。否则将返回200状态和新的资源和Etag.  使用这样的机制将提高网站的性能\u003C\u002Fp\u003E\n\u003Cp\u003E例如: If-None-Match: "03f2b33c0bfcc1:0"\u003C\u002Fp\u003E\n\u003Cp\u003EPragma:\u003C\u002Fp\u003E\n\u003Cp\u003E作用: 防止页面被缓存, 在HTTP\u002F1.1版本中,它和Cache-Control:no-cache作用一模一样\u003C\u002Fp\u003E\n\u003Cp\u003EPargma只有一个用法, 例如: Pragma: no-cache\u003C\u002Fp\u003E\n\u003Cp\u003E注意: 在HTTP\u002F1.0版本中,只实现了Pragema:no-cache, 没有实现Cache-Control\u003C\u002Fp\u003E\n\u003Cp\u003ECache-Control:\u003C\u002Fp\u003E\n\u003Cp\u003E作用: 这个是非常重要的规则。 这个用来指定Response-Request遵循的缓存机制。各个指令含义如下\u003C\u002Fp\u003E\n\u003Cp\u003ECache-Control:Public   可以被任何缓存所缓存()\u003C\u002Fp\u003E\n\u003Cp\u003ECache-Control:Private     内容只缓存到私有缓存中\u003C\u002Fp\u003E\n\u003Cp\u003ECache-Control:no-cache  所有内容都不会被缓存\u003C\u002Fp\u003E\n\u003C\u002Fblockquote\u003E\n\u003Ch2 id=\"2-http响应格式\"\u003E2. HTTP响应格式      \u003C\u002Fh2\u003E\n\u003Cp\u003E      在接收和解释请求消息后,服务器会返回一个 HTTP 响应消息。与 HTTP 请求类似,HTTP 响应也是由三个部分组成,分别是:状态行、消息报头和响应正文。如:\u003C\u002Fp\u003E\n\u003Cp\u003EHTTP\u002F1.1 200 OK Date: Sun, 17 Mar 2013 08:12:54 GMT Server: Apache\u002F2.2.8 (Win32) PHP\u002F5.2.5 X-Powered-By: PHP\u002F5.2.5 Set-Cookie: PHPSESSID=c0huq7pdkmm5gg6osoe3mgjmm3; path=\u002F Expires: Thu, 19 Nov 1981 08:52:00 GMT Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0 Pragma: no-cache Content-Length: 4393 Keep-Alive: timeout=5, max=100 Connection: Keep-Alive Content-Type: text\u002Fhtml; charset=utf-8\u003C\u002Fp\u003E\n\u003Chtml\u003E \u003Chead\u003E \u003Ctitle\u003EHTTP响应示例\u003Ctitle\u003E \u003C\u002Fhead\u003E \u003Cbody\u003E Hello HTTP! \u003C\u002Fbody\u003E \u003C\u002Fhtml\u003E\n\n\u003Ch3 id=\"1、状态行\"\u003E1、状态行\u003C\u002Fh3\u003E\n\u003Cp\u003E       状态行由协议版本、数字形式的状态代码,及相应的状态描述组成,各元素之间以空格分隔,结尾时回车换行符,格式如下:\u003C\u002Fp\u003E\n\u003Cp\u003EHTTP-Version Status-Code Reason-Phrase CRLF\u003C\u002Fp\u003E\n\u003Cp\u003EHTTP-Version 表示服务器 HTTP 协议的版本,Status-Code 表示服务器发回的响应代码,Reason-Phrase 表示状态代码的文本描述,CRLF 表示回车换行。例如:\u003C\u002Fp\u003E\n\u003Cp\u003EHTTP\u002F1.1 200 OK (CRLF)\u003C\u002Fp\u003E\n\u003Cp\u003E      状态代码与状态描述\u003C\u002Fp\u003E\n\u003Cp\u003E      状态代码由 3 位数字组成, 表示请求是否被理解或被满足,状态描述给出了关于状态码的简短的文字描述。状态码的第一个数字定义了响应类别,后面两位数字没有具体分类。第一个数字有 5 种取值,如下所示。\u003C\u002Fp\u003E\n\u003Cul\u003E\n\u003Cli\u003E1xx:指示信息——表示请求已经接受,继续处理\u003C\u002Fli\u003E\n\u003Cli\u003E2xx:成功——表示请求已经被成功接收、理解、接受。\u003C\u002Fli\u003E\n\u003Cli\u003E3xx:重定向——要完成请求必须进行更进一步的操作\u003C\u002Fli\u003E\n\u003Cli\u003E4xx:客户端错误——客户端请求有错误或请求无法实现\u003C\u002Fli\u003E\n\u003Cli\u003E5xx:服务器端错误——服务器未能实现合法的请求。\u003C\u002Fli\u003E\n\u003C\u002Ful\u003E\n\u003Cp\u003E常见状态代码、状态描述、说明:\u003Cbr\u003E200 OK      \u002F\u002F客户端请求成功\u003C\u002Fp\u003E\n\u003Cp\u003E303:重定向,即从原url重定向到新的url。 例如php 的hear函数header("localtion:\u002Findex.php")\u003C\u002Fp\u003E\n\u003Cp\u003E400 Bad Request  \u002F\u002F客户端请求有语法错误,不能被服务器所理解\u003Cbr\u003E401 Unauthorized \u002F\u002F请求未经授权,这个状态代码必须和WWW-Authenticate报头域一起使用 \u003Cbr\u003E403 Forbidden  \u002F\u002F服务器收到请求,但是拒绝提供服务,一般是服务器路径没有权限或者是其他权限相关问题\u003Cbr\u003E404 Not Found  \u002F\u002F请求资源不存在,eg:输入了错误的URL\u003Cbr\u003E500 Internal Server Error \u002F\u002F服务器发生不可预期的错误:一般来说,这个问题都会在服务器端的源代码出现错误时出现,比如出现死循环。\u003C\u002Fp\u003E\n\u003Cp\u003E502 Bad Gateway\u002F\u002F作为网关或者代理工作的服务器尝试执行请求时,从上游服务器接收到无效的响应。比如LNMP ,php-fpm没有启动就会报502错误。\u003C\u002Fp\u003E\n\u003Cp\u003E503 Server Unavailable  \u002F\u002F服务器当前不能处理客户端的请求,一段时间后可能恢复正常,比如java 容器部署war的时候,就出现503, \u003Cbr\u003E                                           或者是nginx处理的文件没有权限。\u003C\u002Fp\u003E\n\u003Cp\u003E504 Gateway Time-out:作为网关或者代理工作的服务器尝试执行请求时,未能及时从上游服务器(URI标识出的服务器,例如HTTP、FTP、LDAP)或者辅助服务器(例如DNS)收到响应,比如nginx和php-fpm, php设置sleep(200),就会收到504 Gateway Time-out。注意:某些代理服务器在DNS查询超时时会返回400或者500错误\u003C\u002Fp\u003E\n\u003Ch3 id=\"2、响应正文\"\u003E2、响应正文\u003C\u002Fh3\u003E\n\u003Cp\u003E响应正文就是服务器返回的资源的内容,响应头和正文之间也必须用空行分隔。如:\u003C\u002Fp\u003E\n\u003Cp\u003E\u003Cstrong\u003E[html]\u003C\u002Fstrong\u003E  \u003Ca href=\"https:\u002F\u002Fwww.oschina.net\u002Faction\u002FGoToLink?url=https%3A%2F%2Fblog.csdn.net%2Fhguisu%2Farticle%2Fdetails%2F8683290%23\"\u003Eview plain\u003C\u002Fa\u003E \u003Ca href=\"https:\u002F\u002Fwww.oschina.net\u002Faction\u002FGoToLink?url=https%3A%2F%2Fblog.csdn.net%2Fhguisu%2Farticle%2Fdetails%2F8683290%23\"\u003Ecopy\u003C\u002Fa\u003E\u003C\u002Fp\u003E\n\u003Col\u003E\n\u003Cli\u003E<html> \u003C\u002Fli\u003E\n\u003Cli\u003E<head> \u003C\u002Fli\u003E\n\u003Cli\u003E<title>HTTP响应示例<title> \u003C\u002Fli\u003E\n\u003Cli\u003E<\u002Fhead> \u003C\u002Fli\u003E\n\u003Cli\u003E<body> \u003C\u002Fli\u003E\n\u003Cli\u003EHello HTTP!  \u003C\u002Fli\u003E\n\u003Cli\u003E<\u002Fbody> \u003C\u002Fli\u003E\n\u003Cli\u003E<\u002Fhtml>\u003C\u002Fli\u003E\n\u003C\u002Fol\u003E\n\u003Ch3 id=\"3-、响应头信息\"\u003E3 、响应头信息\u003C\u002Fh3\u003E\n\u003Cp\u003EHTTP最常见的响应头如下所示:\u003C\u002Fp\u003E\n\u003Ch4 id=\"cache头域\"\u003ECache头域\u003C\u002Fh4\u003E\n\u003Cblockquote\u003E\n\u003Cp\u003EDate:\u003C\u002Fp\u003E\n\u003Cp\u003E作用:生成消息的具体时间和日期,即当前的GMT时间。\u003C\u002Fp\u003E\n\u003Cp\u003E例如: Date: Sun, 17 Mar 2013 08:12:54 GMT\u003C\u002Fp\u003E\n\u003Cp\u003EExpires:\u003C\u002Fp\u003E\n\u003Cp\u003E作用: 浏览器会在指定过期时间内使用本地缓存,指明应该在什么时候认为文档已经过期,从而不再缓存它。\u003C\u002Fp\u003E\n\u003Cp\u003E例如: Expires: Thu, 19 Nov 1981 08:52:00 GMT  \u003C\u002Fp\u003E\n\u003Cp\u003EVary\u003C\u002Fp\u003E\n\u003Cp\u003E作用:\u003C\u002Fp\u003E\n\u003Cp\u003E例如: Vary: Accept-Encoding\u003C\u002Fp\u003E\n\u003C\u002Fblockquote\u003E\n\u003Ch4 id=\"cookielogin-头域-1\"\u003ECookie\u002FLogin 头域\u003C\u002Fh4\u003E\n\u003Cblockquote\u003E\n\u003Cp\u003EP3P\u003C\u002Fp\u003E\n\u003Cp\u003E作用: 用于跨域设置Cookie, 这样可以解决iframe跨域访问cookie的问题\u003C\u002Fp\u003E\n\u003Cp\u003E例如: P3P: CP=CURa ADMa DEVa PSAo PSDo OUR BUS UNI PUR INT DEM STA PRE COM NAV OTC NOI DSP COR\u003C\u002Fp\u003E\n\u003Cp\u003ESet-Cookie\u003C\u002Fp\u003E\n\u003Cp\u003E作用: 非常重要的header, 用于把cookie 发送到客户端浏览器, 每一个写入cookie都会生成一个Set-Cookie.\u003C\u002Fp\u003E\n\u003Cp\u003E例如: Set-Cookie: PHPSESSID=c0huq7pdkmm5gg6osoe3mgjmm3; path=\u002F\u003C\u002Fp\u003E\n\u003C\u002Fblockquote\u003E\n\u003Ch4 id=\"entity实体头域:\"\u003EEntity实体头域:\u003C\u002Fh4\u003E\n\u003Cp\u003E            实体内容的属性,包括实体信息类型,长度,压缩方法,最后一次修改时间,数据有效性等。\u003C\u002Fp\u003E\n\u003Cblockquote\u003E\n\u003Cp\u003EETag:\u003C\u002Fp\u003E\n\u003Cp\u003E作用:  和If-None-Match 配合使用。 (实例请看上节中If-None-Match的实例)\u003C\u002Fp\u003E\n\u003Cp\u003E例如: ETag: "03f2b33c0bfcc1:0"\u003C\u002Fp\u003E\n\u003Cp\u003ELast-Modified:\u003C\u002Fp\u003E\n\u003Cp\u003E作用: 用于指示资源的最后修改日期和时间。(实例请看上节的If-Modified-Since的实例)\u003C\u002Fp\u003E\n\u003Cp\u003E例如: Last-Modified: Wed, 21 Dec 2011 09:09:10 GMT\u003C\u002Fp\u003E\n\u003Cp\u003EContent-Type:\u003C\u002Fp\u003E\n\u003Cp\u003E作用:WEB服务器告诉浏览器自己响应的对象的类型和字符集,\u003C\u002Fp\u003E\n\u003Cp\u003E例如:\u003C\u002Fp\u003E\n\u003Cp\u003E        Content-Type: text\u002Fhtml; charset=utf-8\u003C\u002Fp\u003E\n\u003Cp\u003E  Content-Type:text\u002Fhtml;charset=GB2312\u003C\u002Fp\u003E\n\u003Cp\u003E  Content-Type: image\u002Fjpeg\u003C\u002Fp\u003E\n\u003Cp\u003EContent-Length:\u003C\u002Fp\u003E\n\u003Cp\u003E指明实体正文的长度,以字节方式存储的十进制数字来表示。在数据下行的过程中,Content-Length的方式要预先在服务器中缓存所有数据,然后所有数据再一股脑儿地发给客户端。\u003C\u002Fp\u003E\n\u003Cp\u003E  例如: Content-Length: 19847\u003C\u002Fp\u003E\n\u003Cp\u003EContent-Encoding:\u003C\u002Fp\u003E\n\u003Cp\u003E作用:文档的编码(Encode)方法。一般是压缩方式。\u003C\u002Fp\u003E\n\u003Cp\u003EWEB服务器表明自己使用了什么压缩方法(gzip,deflate)压缩响应中的对象。利用gzip压缩文档能够显著地减少HTML文档的下载时间。\u003C\u002Fp\u003E\n\u003Cp\u003E例如:Content-Encoding:gzip\u003C\u002Fp\u003E\n\u003Cp\u003EContent-Language:\u003C\u002Fp\u003E\n\u003Cp\u003E作用: WEB服务器告诉浏览器自己响应的对象的语言者\u003C\u002Fp\u003E\n\u003Cp\u003E例如: Content-Language:da\u003C\u002Fp\u003E\n\u003C\u002Fblockquote\u003E\n\u003Ch4 id=\"miscellaneous-头域-1\"\u003EMiscellaneous 头域\u003C\u002Fh4\u003E\n\u003Cblockquote\u003E\n\u003Cp\u003EServer:\u003C\u002Fp\u003E\n\u003Cp\u003E作用:指明HTTP服务器的软件信息\u003C\u002Fp\u003E\n\u003Cp\u003E例如:Apache\u002F2.2.8 (Win32) PHP\u002F5.2.5\u003C\u002Fp\u003E\n\u003Cp\u003EX-Powered-By:\u003C\u002Fp\u003E\n\u003Cp\u003E作用:表示网站是用什么技术开发的\u003C\u002Fp\u003E\n\u003Cp\u003E例如: X-Powered-By: PHP\u002F5.2.5\u003C\u002Fp\u003E\n\u003C\u002Fblockquote\u003E\n\u003Ch4 id=\"transport头域\"\u003ETransport头域\u003C\u002Fh4\u003E\n\u003Cblockquote\u003E\n\u003Cp\u003EConnection:\u003C\u002Fp\u003E\n\u003Cp\u003E例如: Connection: keep-alive   当一个网页打开完成后,客户端和服务器之间用于传输HTTP数据的TCP连接不会关闭,如果客户端再次访问这个服务器上的网页,会继续使用这一条已经建立的连接\u003C\u002Fp\u003E\n\u003Cp\u003E例如:  Connection: close  代表一个Request完成后,客户端和服务器之间用于传输HTTP数据的TCP连接会关闭, 当客户端再次发送Request,需要重新建立TCP连接。\u003C\u002Fp\u003E\n\u003C\u002Fblockquote\u003E\n\u003Ch4 id=\"location头域\"\u003ELocation头域\u003C\u002Fh4\u003E\n\u003Cblockquote\u003E\n\u003Cp\u003ELocation:\u003C\u002Fp\u003E\n\u003Cp\u003E作用: 用于重定向一个新的位置, 包含新的URL地址\u003C\u002Fp\u003E\n\u003Cp\u003E实例请看304状态实例\u003C\u002Fp\u003E\n\u003C\u002Fblockquote\u003E\n\u003Ch3 id=\"http协议是无状态的和connection-keep-alive的区别\"\u003EHTTP协议是无状态的和Connection: keep-alive的区别\u003C\u002Fh3\u003E\n\u003Cp\u003E  无状态是指协议对于事务处理没有记忆能力,服务器不知道客户端是什么状态。从另一方面讲,打开一个服务器上的网页和你之前打开这个服务器上的网页之间没有任何联系。\u003C\u002Fp\u003E\n\u003Cp\u003E  HTTP是一个无状态的面向连接的协议,无状态不代表HTTP不能保持TCP连接,更不能代表HTTP使用的是UDP协议(无连接)。\u003C\u002Fp\u003E\n\u003Cp\u003E  从HTTP\u002F1.1起,默认都开启了Keep-Alive,保持连接特性,简单地说,当一个网页打开完成后,客户端和服务器之间用于传输HTTP数据的TCP连接不会关闭,如果客户端再次访问这个服务器上的网页,会继续使用这一条已经建立的连接。\u003C\u002Fp\u003E\n\u003Cp\u003E  Keep-Alive不会永久保持连接,它有一个保持时间,可以在不同的服务器软件(如Apache)中设定这个时间。\u003C\u002Fp\u003E\n\u003Ch2 id=\"3-浏览器缓存\"\u003E3. 浏览器缓存      \u003C\u002Fh2\u003E\n\u003Cp\u003E       浏览器缓存:包括页面html缓存和图片js,css等资源的缓存。如下图,浏览器缓存是基于把页面信息保存到用户本地电脑硬盘里。\u003C\u002Fp\u003E\n\u003Ch3 id=\"1、缓存的优点:\"\u003E1、缓存的优点:\u003C\u002Fh3\u003E\n\u003Cp\u003E     1)服务器响应更快:因为请求从缓存服务器(离客户端更近)而不是源服务器被相应,这个过程耗时更少,让服务器看上去响应更快。\u003C\u002Fp\u003E\n\u003Cp\u003E     2)减少网络带宽消耗:当副本被重用时会减低客户端的带宽消耗;客户可以节省带宽费用,控制带宽的需求的增长并更易于管理。\u003C\u002Fp\u003E\n\u003Ch3 id=\"1、缓存工作原理\"\u003E1、缓存工作原理\u003C\u002Fh3\u003E\n\u003Cp\u003E       页面缓存状态是由http header决定的,一个浏览器请求信息,一个是服务器响应信息。主要包括Pragma: no-cache、Cache-Control、 Expires、 Last-Modified、If-Modified-Since。其中Pragma: no-cache由HTTP\u002F1.0规定,Cache-Control由HTTP\u002F1.1规定。\u003C\u002Fp\u003E\n\u003Cp\u003E       工作原理图:\u003C\u002Fp\u003E\n\u003Cp\u003E\u003Cimg src=\"http:\u002F\u002Fimg.my.csdn.net\u002Fuploads\u002F201303\u002F17\u002F1363512757_1013.png\" alt=\"\"\u003E\u003C\u002Fp\u003E\n\u003Cp\u003E从图中我们可以看到原理主要分三步:\u003C\u002Fp\u003E\n\u003Col\u003E\n\u003Cli\u003E第一次请求:浏览器通过http的header报头,附带Expires,Cache-Control,Last-Modified\u002FEtag向服务器请求,此时服务器记录第一次请求的Last-Modified\u002FEtag                  \u003C\u002Fli\u003E\n\u003Cli\u003E再次请求:当浏览器再次请求的时候,请求头附带Expires,Cache-Control,If-Modified-Since\u002FEtag向服务器请求\u003C\u002Fli\u003E\n\u003Cli\u003E服务器根据第一次记录的Last-Modified\u002FEtag和再次请求的If-Modified-Since\u002FEtag做对比,判断是否需要更新,服务器通过这两个头判断本地资源未发生变化,客 户端不需要重新下载,返回304响应。常见流程如下图所示:\u003C\u002Fli\u003E\n\u003C\u002Fol\u003E\n\u003Cp\u003E\u003Cimg src=\"http:\u002F\u002Fimg.my.csdn.net\u002Fuploads\u002F201303\u002F19\u002F1363670410_3844.jpg\" alt=\"\"\u003E\u003C\u002Fp\u003E\n\u003Ch3 id=\"与缓存相关的http扩展消息头\"\u003E与缓存相关的HTTP扩展消息头\u003C\u002Fh3\u003E\n\u003Cp\u003E    Expires:设置页面过期时间,格林威治时间GMT\u003C\u002Fp\u003E\n\u003Cp\u003E    Cache-Control:更细致的控制缓存的内容\u003C\u002Fp\u003E\n\u003Cp\u003E    Last-Modified:请求对象最后一次的修改时间 用来判断缓存是否过期 通常由文件的时间信息产生 \u003C\u002Fp\u003E\n\u003Cp\u003E    ETag:响应中资源的校验值,在服务器上某个时段是唯一标识的。ETag是一个可以 与Web资源关联的记号(token),和Last-Modified功能才不多,也是一个标识符,一般和Last-Modified一起使用,加强服务器判断的准确度。\u003C\u002Fp\u003E\n\u003Cp\u003E    Date:服务器的时间\u003C\u002Fp\u003E\n\u003Cp\u003E    If-Modified-Since:客户端存取的该资源最后一次修改的时间,用来和服务器端的Last-Modified做比较\u003C\u002Fp\u003E\n\u003Cp\u003E    If-None-Match:客户端存取的该资源的检验值,同ETag。\u003C\u002Fp\u003E\n\u003Cp\u003ECache-Control的主要参数 \u003Cbr\u003E      Cache-Control: private\u002Fpublic Public 响应会被缓存,并且在多用户间共享。 Private 响应只能够作为私有的缓存,不能再用户间共享。\u003Cbr\u003E      Cache-Control: no-cache:不进行缓存 \u003Cbr\u003E      Cache-Control: max-age=x:缓存时间 以秒为单位 \u003Cbr\u003E      Cache-Control: must-revalidate:如果页面是过期的 则去服务器进行获取。\u003C\u002Fp\u003E\n\u003Cp\u003E我们nginx测试:\u003C\u002Fp\u003E\n\u003Cp\u003Eserver {\u003Cbr\u003E        listen       8081;\u003Cbr\u003E        server_name  10.163.1.175;\u003Cbr\u003E        if ($host != '\u003Ca href=\"http:\u002F\u002Fwww.test1.com'\"\u003Ewww.test1.com'\u003C\u002Fa\u003E ) {\u003Cbr\u003E            #rewrite ^\u002F(.*)$ \u003Ca href=\"http:\u002F\u002Fwww.test1.com\u002F$1\"\u003Ehttp:\u002F\u002Fwww.test1.com\u002F$1\u003C\u002Fa\u003E permanent;\u003Cbr\u003E        }\u003Cbr\u003E        index index.html index.htm index.php;\u003Cbr\u003E        root  \u002Fhome\u002Fwww\u002Fapp\u002F;\u003Cbr\u003E        access_log  \u002Fmnt\u002Fapp\u002Fnginx\u002Flogs\u002Ftest1.home.log  main;\u003Cbr\u003E        location ~ .*\\.zip?$\u003Cbr\u003E        {\u003Cbr\u003E               access_log off;\u003Cbr\u003E        }\u003Cbr\u003E        location ~ .*\\.txt?$ {\u003Cbr\u003E                access_log off;\u003Cbr\u003E        }\u003Cbr\u003E        location ~ .*\\.(gif|jpg|jpeg|png|bmp|swf)$\u003Cbr\u003E        {\u003Cbr\u003E                expires      30d;\u003Cbr\u003E        }\u003Cbr\u003E        location ~ .*\\.(js|css|zip)?$\u003Cbr\u003E        {\u003Cbr\u003E                expires      12h;\u003Cbr\u003E        }\u003Cbr\u003E        if (!-e $request_filename) {\u003Cbr\u003E            rewrite ^\u002F(.+)$ \u002Findex.php?url=$1 last;\u003Cbr\u003E            break;\u003Cbr\u003E        } \u003C\u002Fp\u003E\n\u003Cp\u003E        location ~ .*\\.(php|php5)?$\u003Cbr\u003E        {\u003Cbr\u003E                #fastcgi_pass  unix:\u002Ftmp\u002Fphp-cgi.sock;\u003Cbr\u003E                fastcgi_pass 127.0.0.1:9000;\u003Cbr\u003E                fastcgi_index index.php;\u003Cbr\u003E                include fastcgi.conf;\u003Cbr\u003E                add_header Content-Type text\u002Fhtml;\u003Cbr\u003E        }\u003Cbr\u003E}\u003C\u002Fp\u003E\n\u003Cp\u003E然后我们代理两个域名指向同一个端口:\u003C\u002Fp\u003E\n\u003Cp\u003Eserver {\u003Cbr\u003E    listen  80;\u003Cbr\u003E    server_name   \u003Ca href=\"http:\u002F\u002Fwww.test1.com\"\u003Ewww.test1.com\u003C\u002Fa\u003E  test1.com; \u003C\u002Fp\u003E\n\u003Cp\u003E    location \u002F {\u003Cbr\u003E        proxy_pass         \u003Ca href=\"http:\u002F\u002F127.0.0.1:8081\"\u003Ehttp:\u002F\u002F127.0.0.1:8081\u003C\u002Fa\u003E;\u003Cbr\u003E        proxy_set_header   Host             $host;\u003Cbr\u003E        proxy_set_header   X-Real-IP        $remote_addr;\u003Cbr\u003E        proxy_set_header   X-Forward-For    $proxy_add_x_forwarded_for;\u003Cbr\u003E        proxy_set_header Access-Control-Allow-Origin *;\u003Cbr\u003E        proxy_next_upstream http_502 http_504 error timeout invalid_header;\u003Cbr\u003E    }\u003Cbr\u003E}\u003Cbr\u003Eserver {\u003Cbr\u003E    listen  80;\u003Cbr\u003E    server_name   \u003Ca href=\"http:\u002F\u002Fwww.test2.com\"\u003Ewww.test2.com\u003C\u002Fa\u003E  test2.com;\u003Cbr\u003E    location \u002F {\u003Cbr\u003E        proxy_pass         \u003Ca href=\"http:\u002F\u002F127.0.0.1:8081\"\u003Ehttp:\u002F\u002F127.0.0.1:8081\u003C\u002Fa\u003E;\u003Cbr\u003E        proxy_set_header   Host             $host;\u003Cbr\u003E        proxy_set_header   X-Real-IP        $remote_addr;\u003Cbr\u003E        proxy_set_header   X-Forward-For    $proxy_add_x_forwarded_for;\u003Cbr\u003E        proxy_set_header Access-Control-Allow-Origin *;\u003Cbr\u003E        proxy_next_upstream http_502 http_504 error timeout invalid_header;\u003Cbr\u003E    }\u003Cbr\u003E}\u003C\u002Fp\u003E\n\u003Cp\u003E我们访问\u003Ca href=\"http:\u002F\u002Fwww.test2.com%EF%BC%8C%E7%9B%B4%E6%8E%A5%E6%8C%87%E5%90%91www.test1.com%EF%BC%8Chttp%E6%98%AF304%E5%93%8D%E5%BA%94%E3%80%82\"\u003Ewww.test2.com,直接指向www.test1.com,http是304响应。\u003C\u002Fa\u003E\u003C\u002Fp\u003E\n\u003Cp\u003E当我们把8081端口的配置去掉\u003C\u002Fp\u003E\n\u003Cp\u003E        if ($host != '\u003Ca href=\"http:\u002F\u002Fwww.test1.com'\"\u003Ewww.test1.com'\u003C\u002Fa\u003E ) {\u003Cbr\u003E            #rewrite ^\u002F(.*)$ \u003Ca href=\"http:\u002F\u002Fwww.test1.com\u002F$1\"\u003Ehttp:\u002F\u002Fwww.test1.com\u002F$1\u003C\u002Fa\u003E permanent;\u003Cbr\u003E        }\u003Cbr\u003E   重启nginx,同一个访问\u003Ca href=\"http:\u002F\u002Fwww.test2.com%EF%BC%8C%E5%8F%91%E7%8E%B0%E8%BF%98%E6%98%AF%E7%9B%B4%E6%8E%A5%E8%B7%B3%E8%BD%AC%E5%88%B0www.test1.com%E3%80%82\"\u003Ewww.test2.com,发现还是直接跳转到www.test1.com。\u003C\u002Fa\u003E\u003C\u002Fp\u003E\n\u003Cp\u003E这是因为浏览器304缓存的问题。我们直接使用新浏览器访问,就直接访问就不会跳转啦。\u003C\u002Fp\u003E\n\u003Ch3 id=\"2、关于图片,css,js,flash的缓存\"\u003E2、关于图片,css,js,flash的缓存\u003C\u002Fh3\u003E\n\u003Cp\u003E这个主要通过服务器的配置来实现这个技术,如果使用apache服务器的话,可以使用mod_expires模块来实现:\u003C\u002Fp\u003E\n\u003Cp\u003E编译mod_expires模块:\u003C\u002Fp\u003E\n\u003Cp\u003ECd  \u002Froot\u002Fhttpd-2.2.3\u002Fmodules\u002Fmetadata\u003C\u002Fp\u003E\n\u003Cp\u003E\u002Fusr\u002Flocal\u002Fapache\u002Fbin\u002Fapxs -i -a -c mod_expires.c \u002F\u002F编译\u003C\u002Fp\u003E\n\u003Cp\u003E编辑httpd.conf配置:添加下面内容\u003C\u002Fp\u003E\n\u003Cp\u003E<IfModule mod_expires.c>\u003C\u002Fp\u003E\n\u003Cp\u003EExpiresActive on\u003C\u002Fp\u003E\n\u003Cp\u003EExpiresDefault "access plus 1 month"\u003C\u002Fp\u003E\n\u003Cp\u003EExpiresByType text\u002Fhtml "access plus 1 months"\u003C\u002Fp\u003E\n\u003Cp\u003EExpiresByType text\u002Fcss "access plus 1 months"\u003C\u002Fp\u003E\n\u003Cp\u003EExpiresByType image\u002Fgif "access plus 1 months"\u003C\u002Fp\u003E\n\u003Cp\u003EExpiresByType image\u002Fjpeg "access plus 1 months"\u003C\u002Fp\u003E\n\u003Cp\u003EExpiresByType image\u002Fjpg "access plus 1 months"\u003C\u002Fp\u003E\n\u003Cp\u003EExpiresByType image\u002Fpng "access plus 1 months"\u003C\u002Fp\u003E\n\u003Cp\u003EEXpiresByType application\u002Fx-shockwave-flash "access plus 1 months"\u003C\u002Fp\u003E\n\u003Cp\u003EEXpiresByType application\u002Fx-javascript      "access plus 1 months"\u003C\u002Fp\u003E\n\u003Cp\u003E#ExpiresByType video\u002Fx-flv "access plus 1 months"\u003C\u002Fp\u003E\n\u003C\u002FIfModule\u003E\n\n\u003Cp\u003E解释:第一句--开启服务\u003C\u002Fp\u003E\n\u003Cp\u003E第二句--默认时间是一个月\u003C\u002Fp\u003E\n\u003Cp\u003E在下面是关于各种类型的资源的缓存时间设置\u003C\u002Fp\u003E\n",tags:"[{\"id\":11138,\"uuid\":\"35509022\",\"name\":\"tcp\",\"icon\":\"\",\"status\":1,\"createTime\":\"2022-09-23T22:35:30.577257+08:00\",\"updateTime\":\"2022-09-23T22:35:30.577257+08:00\"},{\"id\":11157,\"uuid\":\"98856857\",\"name\":\"缓存服务器\",\"icon\":\"\",\"status\":1,\"createTime\":\"2022-09-23T22:35:36.021272+08:00\",\"updateTime\":\"2022-09-23T22:35:36.021272+08:00\"},{\"id\":11571,\"uuid\":\"84098079\",\"name\":\"服务器类型\",\"icon\":\"\",\"status\":1,\"createTime\":\"2022-09-23T22:44:17.381378+08:00\",\"updateTime\":\"2022-09-23T22:44:17.381378+08:00\"},{\"id\":13695,\"uuid\":\"73245914\",\"name\":\"电脑服务器\",\"icon\":\"\",\"status\":1,\"createTime\":\"2022-09-23T23:51:30.921324+08:00\",\"updateTime\":\"2022-09-23T23:51:30.921324+08:00\"},{\"id\":11509,\"uuid\":\"97437520\",\"name\":\"post请求\",\"icon\":\"\",\"status\":1,\"createTime\":\"2022-09-23T22:43:21.730884+08:00\",\"updateTime\":\"2022-09-23T22:43:21.730884+08:00\"},{\"id\":11156,\"uuid\":\"50789742\",\"name\":\"浏览器缓存\",\"icon\":\"\",\"status\":1,\"createTime\":\"2022-09-23T22:35:35.9969+08:00\",\"updateTime\":\"2022-09-23T22:35:35.9969+08:00\"},{\"id\":11389,\"uuid\":\"40551943\",\"name\":\"html语言\",\"icon\":\"\",\"status\":1,\"createTime\":\"2022-09-23T22:41:25.027284+08:00\",\"updateTime\":\"2022-09-23T22:41:25.027284+08:00\"},{\"id\":11341,\"uuid\":\"25617640\",\"name\":\"cookie\",\"icon\":\"\",\"status\":1,\"createTime\":\"2022-09-23T22:40:50.112039+08:00\",\"updateTime\":\"2022-09-23T22:40:50.112039+08:00\"},{\"id\":11142,\"uuid\":\"45491762\",\"name\":\"三次握手\",\"icon\":\"\",\"status\":1,\"createTime\":\"2022-09-23T22:35:30.673414+08:00\",\"updateTime\":\"2022-09-23T22:35:30.673414+08:00\"},{\"id\":11154,\"uuid\":\"26022269\",\"name\":\"通信\",\"icon\":\"\",\"status\":1,\"createTime\":\"2022-09-23T22:35:34.669544+08:00\",\"updateTime\":\"2022-09-23T22:35:34.669544+08:00\"},{\"id\":14631,\"uuid\":\"64180631\",\"name\":\"keep-alive\",\"icon\":\"\",\"status\":1,\"createTime\":\"2022-09-24T01:06:16.1381802+08:00\",\"updateTime\":\"2022-09-24T01:06:16.1381802+08:00\"},{\"id\":11144,\"uuid\":\"01018138\",\"name\":\"http协议\",\"icon\":\"\",\"status\":1,\"createTime\":\"2022-09-23T22:35:30.721362+08:00\",\"updateTime\":\"2022-09-23T22:35:30.721362+08:00\"},{\"id\":11135,\"uuid\":\"12457570\",\"name\":\"http请求\",\"icon\":\"\",\"status\":1,\"createTime\":\"2022-09-23T22:35:28.140341+08:00\",\"updateTime\":\"2022-09-23T22:35:28.140341+08:00\"},{\"id\":11155,\"uuid\":\"36949870\",\"name\":\"cache-control\",\"icon\":\"\",\"status\":1,\"createTime\":\"2022-09-23T22:35:35.968635+08:00\",\"updateTime\":\"2022-09-23T22:35:35.968635+08:00\"},{\"id\":11120,\"uuid\":\"51380297\",\"name\":\"前端\",\"icon\":\"\",\"status\":1,\"createTime\":\"2022-09-23T22:35:22.489653+08:00\",\"updateTime\":\"2022-09-23T22:35:22.489653+08:00\"},{\"id\":11120,\"uuid\":\"51380297\",\"name\":\"前端\",\"icon\":\"\",\"status\":1,\"createTime\":\"2022-09-23T22:35:22.489653+08:00\",\"updateTime\":\"2022-09-23T22:35:22.489653+08:00\"}]",homeImg:b,createTime:u,updateTime:"1970-01-01T08:00:00+08:00",publishTime:u,readCount:349,favoriteCount:a,zanCount:a,isAuthorBlog:c},otherBlogList:[{uuid:"6917592658",title:"OpenVPN下载、安装、配置及使用详解 "},{uuid:"0907804122",title:"GitHub神器,一个可以白嫖全网无损音乐的神器 "},{uuid:"9665141123",title:"OpenWrt 路由器过滤广告的N种方法 "},{uuid:"0868920465",title:"Python—执行系统命令的四种方法(os.system、os.popen、commands、subprocess) "},{uuid:"8340561847",title:"SS端加密以及obfs混淆 "}],recommendBlogList:[{uuid:"2802547579",title:"MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1",title2:b,intro:"文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\\mode:sql\\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s",createTime:d,updateTime:d,publishTime:"2021-08-20T13:55:40+08:00",homeImg:"https:\u002F\u002Fimg-hello-world.oss-cn-beijing.aliyuncs.com\u002Fed6c6174f1775f65a3fbe98488391419.png",readCount:3498,zanCount:a,favoriteCount:a,status:a,commentCount:a,profile:v,nicker:v,avatar:"https:\u002F\u002Fimg-hello-world.oss-cn-beijing.aliyuncs.com\u002Fimgs\u002Fcd34cdaab69ede1e2bf28de235151c34.webp",collectionId:a,recommendStatus:a,userStatus:a,auditReason:b},{uuid:"3468005401",title:"2020年前端实用代码段,为你的工作保驾护航",title2:b,intro:"有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: \"OK\",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )",createTime:d,updateTime:d,publishTime:"2021-06-03T22:46:22+08:00",homeImg:"https:\u002F\u002Fimg-hello-world.oss-cn-beijing.aliyuncs.com\u002Fe7130dfd1edf85ccee4a9e73aa0b77dd.jpeg",readCount:1984,zanCount:a,favoriteCount:a,status:a,commentCount:a,profile:w,nicker:w,avatar:"https:\u002F\u002Fimg-hello-world.oss-cn-beijing.aliyuncs.com\u002Fimgs\u002Fd4566ad9edfb956dba92fc21f5e1561f.webp",collectionId:a,recommendStatus:a,userStatus:a,auditReason:b},{uuid:"9382788506",title:"皕杰报表之UUID",title2:b,intro:"​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为",createTime:d,updateTime:d,publishTime:"2022-07-08T08:32:23+08:00",homeImg:b,readCount:777,zanCount:a,favoriteCount:a,status:a,commentCount:a,profile:"34035044",nicker:"helloworld_34035044",avatar:"https:\u002F\u002Fimg-hello-world.oss-cn-beijing.aliyuncs.com\u002Fimgs\u002F0d250ec5492da88592013bbd302402ae.jfif",collectionId:a,recommendStatus:a,userStatus:a,auditReason:b},{uuid:"1127166003",title:"AndroidStudio封装SDK的那些事 ",title2:b,intro:"\u003Cdivclass\"markdown\\_views\"\u003C!flowchart箭头图标勿删\u003Csvgxmlns\"http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg\"style\"display:none;\"\u003Cpathstrokelinecap\"round\"d\"M5,00,2.55,5z\"id\"raphael",createTime:d,updateTime:d,publishTime:"2021-10-11T15:20:08+08:00",homeImg:b,readCount:897,zanCount:a,favoriteCount:a,status:a,commentCount:a,profile:g,nicker:g,avatar:i,collectionId:a,recommendStatus:a,userStatus:a,auditReason:b},{uuid:"4738427618",title:"Java获得今日零时零分零秒的时间(Date型) ",title2:b,intro:"publicDatezeroTime()throwsParseException{    DatetimenewDate();    SimpleDateFormatsimpnewSimpleDateFormat(\"yyyyMMdd00:00:00\");    SimpleDateFormatsimp2newS",createTime:d,updateTime:d,publishTime:"2021-10-11T09:27:43+08:00",homeImg:b,readCount:938,zanCount:a,favoriteCount:a,status:a,commentCount:a,profile:e,nicker:e,avatar:h,collectionId:a,recommendStatus:a,userStatus:a,auditReason:b},{uuid:"6029686498",title:"mysql设置时区 ",title2:b,intro:"mysql设置时区mysql\\_query(\"SETtime\\_zone'8:00'\")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\\_id)asdevice,CONVERT\\_TZ(FROM\\_UNIXTIME(reg\\_time),'08:00','0",createTime:d,updateTime:d,publishTime:"2021-10-11T12:01:24+08:00",homeImg:b,readCount:920,zanCount:a,favoriteCount:a,status:a,commentCount:a,profile:e,nicker:e,avatar:h,collectionId:a,recommendStatus:a,userStatus:a,auditReason:b},{uuid:"4384340365",title:"00:Java简单了解 ",title2:b,intro:"浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。",createTime:d,updateTime:d,publishTime:"2021-10-11T08:43:43+08:00",homeImg:b,readCount:903,zanCount:a,favoriteCount:a,status:a,commentCount:a,profile:e,nicker:e,avatar:h,collectionId:a,recommendStatus:a,userStatus:a,auditReason:b},{uuid:"3395108718",title:"Django中Admin中的一些参数配置 ",title2:b,intro:"设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable",createTime:d,updateTime:d,publishTime:"2021-10-11T16:54:04+08:00",homeImg:b,readCount:849,zanCount:a,favoriteCount:a,status:a,commentCount:a,profile:g,nicker:g,avatar:i,collectionId:a,recommendStatus:a,userStatus:a,auditReason:b},{uuid:"2102334911",title:"MySQL部分从库上面因为大量的临时表tmp_table造成慢查询 ",title2:b,intro:"背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_",createTime:d,updateTime:d,publishTime:"2021-10-11T11:24:10+08:00",homeImg:b,readCount:1113,zanCount:a,favoriteCount:a,status:a,commentCount:a,profile:e,nicker:e,avatar:h,collectionId:a,recommendStatus:a,userStatus:a,auditReason:b},{uuid:"7920817787",title:"Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除",title2:b,intro:"大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这",createTime:d,updateTime:d,publishTime:"2024-01-18T17:34:27.824977+08:00",homeImg:"https:\u002F\u002Fimg-hello-world.oss-cn-beijing.aliyuncs.com\u002Fimgs\u002Faeaded5a375b9d90ad54a2731b017114.png",readCount:128,zanCount:a,favoriteCount:a,status:a,commentCount:a,profile:"pdcfighting",nicker:"Python进阶者",avatar:"https:\u002F\u002Fimg-hello-world.oss-cn-beijing.aliyuncs.com\u002Fimgs\u002Fff45645a048833b06e967323e7411c91.webp",collectionId:a,recommendStatus:a,userStatus:a,auditReason:b}],userInfo:{profile:g,avatar:i,nicker:g,level:a,job:b,company:b,sex:a,slogan:"接天莲叶无穷碧,映日荷花别样红。",blogCount:16974,fansCount:37,zanCount:28,followed:c,isZaned:c,isFavorited:c,webEnable:a,website:b,websiteDomain:b,wechatQrcode:b,wechatOfficialAccount:b}},currentCateId:b,recommendSpecialList:[],userAndBlogActionInfo:{},isLoading:c,isFinished:c,searchList:[],isLoadingSearch:c,isFinishedSearch:c,recommendLessonList:[],recommendLessonListByBlog:[{id:19,uuid:"1935098869",userId:x,name:"Java synchronized同步关键字背后的原理与源码实现 ",subtitle:"为了完成Java源码版本的 synchronized实现,期间经历了太多的通知与折磨,灵光一现到落实到真正的Java源码,还是很不容易的。写代码过程非常爽,但是测试过程蹦出来的bug差点让我放弃,多线程环境下bug变得非常非常隐蔽。原本计划5天写完的,结果硬生生的被bug折磨了4天。造这个轮子的目的很简单,主要是为了解决大家阅读C++版本的synchronized的屏障。并且手写了一套Java版本的Synchronized实现。",content:b,html:b,price:13900,discountAmount:3000,status:y,reason:b,level:z,type:2,mark:a,canRefund:a,cover:"https:\u002F\u002Fimg-hello-world.oss-cn-beijing.aliyuncs.com\u002Fimgs\u002Fb198ef1a1d11a9c6e81531134cc3327a.png",payCount:56,updatedAt:"2023-07-18T21:38:20.594994+08:00",createdAt:"2023-07-18T07:58:58.633126+08:00",deletedAt:f},{id:75,uuid:"6955961602",userId:x,name:"Android进阶之旅-(Framework源码分析)",subtitle:"详细分析了android Framework底层的源码,包括但不限于 启动,init进程,zygote进程,binder机制,ServiceManger进程,AMS,PMS, Launcher等等",content:b,html:b,price:a,discountAmount:a,status:y,reason:b,level:z,type:1,mark:a,canRefund:a,cover:"https:\u002F\u002Fimg-hello-world.oss-cn-beijing.aliyuncs.com\u002Fimgs\u002F2847450d82190c8a7d0ae4ba8a8e5629.png",payCount:26,updatedAt:"2023-09-08T09:27:27.21739+08:00",createdAt:"2023-09-07T21:50:23.74792+08:00",deletedAt:f}]},special:{mostSpecialCountUserList:[],specialList:[],specialCateList:[],bannerList:[],specialDetail:{},specialDetailList:{},chapterList:[],specialListByCate:[],mySpecialDetail:f,isLoading:c,isFinished:c},tutorial:{bigCateList:[],tutorialData:[],tutorialDetail:{},chapterList:[],tutorialOverview:{}}},serverRendered:t,routePath:"\u002Fp\u002F3794736797",config:{_app:{basePath:"\u002F",assetsPath:"\u002F_nuxt\u002F",cdnURL:f}}}}(0,"",false,"0001-01-01T00:00:00Z","Wesley13",null,"Stella981","https:\u002F\u002Fimg-hello-world.oss-cn-beijing.aliyuncs.com\u002Fimgs\u002F46847d754406b0102dee7a1f54d14f92.jfif","https:\u002F\u002Fimg-hello-world.oss-cn-beijing.aliyuncs.com\u002Fimgs\u002F1bad3e5246214111b0d7a482fc5beec5.jfif","\u002Fmanage\u002FgetCollectionList","\u002Fmanage\u002FgetMyBlogDetail","\u002Fspecial\u002FupdateSection","\u002Fmanage\u002FgetMySectionDetail","\u002Fspecial\u002FsubscribeSpecial","\u002Fspecial\u002FunSubscribeSpecial","\u002Fspecial\u002FmodifySpecial","\u002Ftutorial\u002FgetTutorialList","\u002Ftutorial\u002FgetTutorialDetail","\u002Faccess\u002FmodifyPassword",true,"2021-10-11T18:55:40+08:00","blmius","Jacquelyn38",7689,30,4));</script><script src="/_nuxt/hw.162.js?t=1713671581227" defer></script><script src="/_nuxt/hw.114.js?t=1713671581227" defer></script><script src="/_nuxt/hw.0.js?t=1713671581227" defer></script><script src="/_nuxt/hw.1.js?t=1713671581227" defer></script><script src="/_nuxt/hw.2.js?t=1713671581227" defer></script><script src="/_nuxt/hw.163.js?t=1713671581227" defer></script><script src="/_nuxt/hw.14.js?t=1713671581227" defer></script><script src="/_nuxt/hw.167.js?t=1713671581227" defer></script><script src="/_nuxt/hw.15.js?t=1713671581227" defer></script> </body> </html>