美文网首页HTTP
http通信中的内容协商

http通信中的内容协商

作者: 张柳哥 | 来源:发表于2017-03-03 08:54 被阅读0次

    考虑这样的一种情况,服务器对于某个资源有好几个不同的版本,当浏览器发送请求过来的时候,服务器会提供一个最合适的版本给浏览器。

    举个例子来说,对于某个网站的主页,服务器可能有“汉语”、“英语”、“法语”,好几个不同的版本,当浏览器发送请求过来的时候,服务器需要判断,到底给浏览器哪个语言的版本比较合适。

    服务器为了确定这个比较合适的版本,需要和浏览器进行一些沟通,这个沟通的过程,就是内容协商。

    内容协商的过程


    那服务器和浏览器是如何进行沟通的呢?目前主流的方法是通过使用请求中一些头部信息来完成这一沟通的,浏览器在发送请求的请求中放置一些头部信息,告诉服务器我需要什么样的数据,然后服务器返回相应版本的数据。

    主要使用的请求头有:

    1、Accept
    2、Accept-Language
    3、Accept-Encoding

    Accept


    accept主要是告诉服务器,浏览器能够接受什么样的数据类型,比如能够接受图片类型的数据,或者能够接受一个xml文件,当然了,浏览器一般可以接受的数据类型是有很多种的,因此一个accept头信息可能是:

    accept: text/html, image/jpeg, image/gif, application/pdf
    

    他表示浏览器可以接受htmljpeg图片、pdf三种文件类型,根据这个头部,服务器在发送数据的时候,就要充分考虑浏览器能不能接受。

    有的同学可能会问了,如果服务器发送了一份数据,浏览器怎么知道它是什么类型的数据呢?
    服务器在给浏览器发送响应数据的时候,也会有头部信息,其中的一个头叫做Content-Type,它会告诉浏览器,我发给你的是什么类型的数据。

    那假如对于一份数据,服务器有不同数据类型的版本,即有html类型的,也有jpeg类型的,那么发送哪个版本比较合适呢?
    浏览器在accept中可以使用一个叫q的参数,告诉服务器哪些数据类型比较推荐发送。

    accept: text/html, image/jpeg; q=0.3, image/gif; q=0.5, application/pdf
    

    如上,浏览器可以接受jpeg、和gif两种类型的图片,但是gif类型的q值是0.5,比较高,q值越高,表示这种数据类型越合适。

    那对于text/html并没有制定q值,那这时候表会取q的默认值1,也就是说,text/html等同于text/html; q=1

    Accept-Charset


    Accept-Charset表示浏览器支持的字符集编码,比如支持utf-8或者gb2312

    Accept-Charset: ISO-8859-1,gb2312,utf-8;q=0.7,*;q=0.3
    

    上面表示,浏览器支持ISO-8859-1gb2312utf-8*等字符集,*表示其他任意的字符集,其中的q值表示,浏览器优先支持ISO-8859-1gb2312字符集(默认的q值为1),但是对于utf-8字符集,它的支持权重为0.7,其他字符集的权重为0.3

    如果服务器那边有多个字符集版本的资源,那么发送的时候应该优选发送ISO-8859-1gb2312这两个版本,假如服务器那边没有这两个版本那么就推荐发送utf-8版本,实在不行,在发送其他的版本。

    Accept-Encoding


    在服务器发送数据给浏览器的时候,为了减少数据量,加快发送速度,服务器可以对数据进行压缩,由于服务器给浏览器发送的数据一般是html文本,对于这种文本数据,gzipdeflate这两种压缩算法都有比较好的压缩效果,可以达到原内容的40%。

    Accept-Encoding头就是用于浏览器告诉服务器,我希望你发送的数据是压缩过的,并且使用的压缩算法是我指定的:

    Accept-Encoding: gzip; q=0.9, deflate; q=0.7
    

    上面表示,浏览器支持gzipdeflate两种压缩算法,但是推荐服务器使用gzip来压缩,因为它的q值比较高,如果服务器发送过来的数据用的压缩算法浏览器不支持,那么就会出错。

    还有一个问题是,浏览器怎么知道服务器用了何种压缩算法呢?
    同样,服务器发送的响应中,有一个对应的头部:Content-Encoding,会告诉浏览器,使用了什么样的压缩算法。

    Accept-Language


    如果一个网站支持多语言,一般会用到这个头信息,Accept-Language主要是告诉服务器,当前用户比较擅长某种语言(中文、英文等),建议服务器发送这种语言的页面过来:

    Accept-Language: zh-CN,fr-FR;q=0.5
    

    zh-CN表示中文,fr-FR表示法语,上面表示,浏览器希望服务器发送zh-CN中文版本的页面,因为它的q值是1,如果没有中文的,那就发送法语版本的。

    那浏览器根据什么来判断,什么语言比较合适用户呢?

    浏览器一般会根据用户的操作系统(比如中国一般用的是中文版的操作系统)来给予语言方面的建议,有的浏览器本身就有各种语言的版本,也可以根据自己的版本信息来进行判断。

    Vary


    在网络当中,浏览器和服务器并不是直接进行通信的,在他们中间往往有很多的代理服务器:

    浏览器=>代理服务器1=>代理服务器2=>...=>服务器

    其中的代理服务器一般具有缓存的功能,现在假设,一个浏览器发送了请求,要求服务器提供压缩版本的数据,这个数据返回后,会被缓存在代理服务器中,然后,另外一个浏览器发送了请求同样数据的请求,但是不是压缩版本的,这个时候就容易发生问题。

    当第二个请求到达代理服务器的时候,代理服务器发现请求的资源已经缓存起来了,就会把的压缩版本资源返回,这样就会导致错误。

    Vary头是服务器返回响应的时候,放置在响应头当中的,用来告诉这些代理服务器,当你缓存我的时候,需要补上对应的请求中的一些头信息作为我的版本信息,这样下个请求过来的时候,除了判断是不是相同的url,还需要判断版本信息是不是一样的,最后来决定是不是使用缓存:

    Vary: Accept-Encoding, Accept
    

    上面的头信息是告诉代理服务器,缓存我(响应)的时候,你需要加上对应请求当中的Accept-EncodingAccept信息,这样,如果下个请求当中的Accept-EncodingAccept信息和缓存中的不一致,就会认为缓存不可用。

    为什么代理服务器在检测版本的时候,不使用响应头Content-*头呢?
    原因是有些代理服务器会自动忽略掉响应当中的一些头,比如响应中的Content-Encoding头,这样代理服务器就根本不知道这个响应数据是不是经过压缩的了。

    参考链接:


    相关文章

      网友评论

        本文标题:http通信中的内容协商

        本文链接:https://www.haomeiwen.com/subject/wowgwttx.html