文档章节

Accept 与 Content-Type

o
 osc_w9s1w4o0
发布于 2019/03/30 23:15
字数 2285
阅读 8
收藏 0

精选30+云产品,助力企业轻松上云!>>>

<table class="d-block"> <tbody class="d-block"> <tr class="d-block"> <td class="d-block comment-body markdown-body js-comment-body">

<ul> <li>Accept 表示请求方希望的资源类型,或者能解析识别的类型</li> <li>Content-Type 表示实际发送的资源类型</li> </ul> <p>这里资源类型通过 <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types" rel="nofollow">MIME types</a> 表示。</p> <h3>Accept</h3> <p>Accept 是浏览器发送的请求头,用于表示想要的资源类型。根据请求的上下文不同,所设置的 Accept 请求头会相应变化。服务器根据 <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Content_negotiation" rel="nofollow">content negotiation</a> 规则选择最合适的类型设置 <code>Content-Type</code> 并返回。</p> <p>例如请求路由页面时,Chrome 设置 Accept 为</p> <pre><code>Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8 </code></pre> <p>对于页面中的样式文件 css,其 Accept 为:</p> <pre><code>Accept: text/css,*/*;q=0.1 </code></pre> <p>可用的值有以下几种:</p> <ul> <li><code>&lt;MIME_type&gt;/&lt;MIME_subtype&gt;</code>,精确指定,示例: <code>text/html</code>。</li> <li><code>&lt;MIME_type&gt;/*</code>, 不限制子类型,比如 <code>image/*</code> 会匹配 <code>image/png</code>,&nbsp;<code>image/svg</code>,&nbsp;<code>image/gif</code> 以及其他任何图片类型。</li> <li><code>*/*</code> 任意 MIME 类型。</li> <li><code>;q= (q-factor weighting)</code> 多种类型组合的情况,通过指定权重(<a href="https://developer.mozilla.org/en-US/docs/Glossary/Quality_values" rel="nofollow">quality value</a>)来表明每种类型的优先级。</li> </ul> <h4>Quality value</h4> <p>Header 中逗号分隔的值,每项的权重,或优先级。<br> 比如:</p> <pre><code>text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 </code></pre> <p>表示:</p> <table> <thead> <tr> <th align="left">值</th> <th align="left">优先级</th> </tr> </thead> <tbody> <tr> <td align="left"><code>text/html</code> 和 <code>application/xhtml+xml</code></td> <td align="left"><code>1.0</code></td> </tr> <tr> <td align="left"><code>application/xml</code></td> <td align="left"><code>0.9</code></td> </tr> <tr> <td align="left"><code>*/*</code></td> <td align="left"><code>0.8</code></td> </tr> </tbody> </table> <h3>Content-Type</h3> <p>用来表示资源的类型。某些情况下,浏览器会对资源的类型进行嗅探而忽略掉服务器返回的 <code>Content-Type</code>。如果想强制客户端使用服务器返回的类型,可加上 <code>X-Content-Type-Options:nosniff</code> 响应头。</p> <p>支持的值有:</p> <ul> <li><code>media-type</code>,常见的 Content-Type 可 <a href="https://stackoverflow.com/a/48704300/1553656" rel="nofollow">参考这里</a>。</li> <li><code>charset</code>,指定资源编码类型。</li> <li><code>boundary</code>, 多个资源实例情况下,指定资源的分界符。比如 form 表单提交时分隔多个表单字段,见后面示例。</li> </ul> <p>一般情况下,包含在由服务器发送给客户端的响应头里。但也存在浏览器发送给服务器的情况,比如 POST 请求,表单提交这种由浏览器向服务器发送数据的情况下。</p> <h4>表单的提交类型</h4> <p>form 表单中,提交的内容类型通过表单的 <code>enctype</code> 属性来指定。包含两种:</p> <ul> <li><code>application/x-www-form-urlencoded</code> 较古老的格式,只支持简单文本,不支持文件上传。</li> <li><code>multipart/form-data</code> 较新,支持文件上传,尺寸较大的二进制数据等。</li> </ul> <h4>一个表单提交示例</h4> <p>通过 koa.js 搭建一个简单的表单提交示例,以查看 Content-Type。</p> <p><em>server.js</em></p> <div class="highlight highlight-source-js"><pre><span class="pl-k">const</span> { <span class="pl-c1">createReadStream</span> } <span class="pl-k">=</span> <span class="pl-c1">require</span>(<span class="pl-s"><span class="pl-pds">"</span>fs<span class="pl-pds">"</span></span>); <span class="pl-k">const</span> <span class="pl-c1">Koa</span> <span class="pl-k">=</span> <span class="pl-c1">require</span>(<span class="pl-s"><span class="pl-pds">"</span>koa<span class="pl-pds">"</span></span>); <span class="pl-k">const</span> <span class="pl-c1">app</span> <span class="pl-k">=</span> <span class="pl-k">new</span> <span class="pl-en">Koa</span>(); <span class="pl-k">const</span> <span class="pl-c1">router</span> <span class="pl-k">=</span> <span class="pl-c1">require</span>(<span class="pl-s"><span class="pl-pds">"</span>koa-router<span class="pl-pds">"</span></span>)(); <span class="pl-k">const</span> <span class="pl-c1">koaBody</span> <span class="pl-k">=</span> <span class="pl-c1">require</span>(<span class="pl-s"><span class="pl-pds">"</span>koa-body<span class="pl-pds">"</span></span>);

router .<span class="pl-c1">get</span>(<span class="pl-s"><span class="pl-pds">"</span>/<span class="pl-pds">"</span></span>, <span class="pl-k">async</span> <span class="pl-smi">ctx</span> <span class="pl-k">=></span> { <span class="pl-smi">ctx</span>.<span class="pl-c1">type</span> <span class="pl-k">=</span> <span class="pl-s"><span class="pl-pds">"</span>html<span class="pl-pds">"</span></span>; <span class="pl-smi">ctx</span>.<span class="pl-c1">body</span> <span class="pl-k">=</span> <span class="pl-en">createReadStream</span>(<span class="pl-s"><span class="pl-pds">"</span>form.html<span class="pl-pds">"</span></span>); }) .<span class="pl-en">post</span>( <span class="pl-s"><span class="pl-pds">"</span>/submit<span class="pl-pds">"</span></span>, <span class="pl-en">koaBody</span>({ multipart<span class="pl-k">:</span> <span class="pl-c1">true</span> }), <span class="pl-smi">ctx</span> <span class="pl-k">=></span> { <span class="pl-en">console</span>.<span class="pl-c1">log</span>(<span class="pl-s"><span class="pl-pds">"</span>form data is:<span class="pl-pds">"</span></span>, <span class="pl-smi">ctx</span>.<span class="pl-smi">request</span>.<span class="pl-c1">body</span>); <span class="pl-smi">ctx</span>.<span class="pl-c1">body</span> <span class="pl-k">=</span> <span class="pl-c1">JSON</span>.<span class="pl-c1">stringify</span>(<span class="pl-smi">ctx</span>.<span class="pl-smi">request</span>.<span class="pl-c1">body</span>); } );

<span class="pl-smi">app</span>.<span class="pl-en">use</span>(<span class="pl-smi">router</span>.<span class="pl-en">routes</span>());

<span class="pl-smi">app</span>.<span class="pl-en">listen</span>(<span class="pl-c1">3000</span>);

<span class="pl-en">console</span>.<span class="pl-c1">log</span>(<span class="pl-s"><span class="pl-pds"></span>server started at http://localhost:3000<span class="pl-pds"></span></span>);</pre></div>

<p><em>form.html</em></p> <div class="highlight highlight-text-html-basic"><pre>&lt;<span class="pl-ent">form</span> <span class="pl-e">action</span>=<span class="pl-s"><span class="pl-pds">"</span>/submit<span class="pl-pds">"</span></span> <span class="pl-e">method</span>=<span class="pl-s"><span class="pl-pds">"</span>POST<span class="pl-pds">"</span></span> <span class="pl-e">enctype</span>=<span class="pl-s"><span class="pl-pds">"</span>multipart/form-data<span class="pl-pds">"</span></span>&gt; foo:&lt;<span class="pl-ent">input</span> <span class="pl-e">type</span>=<span class="pl-s"><span class="pl-pds">"</span>text<span class="pl-pds">"</span></span> <span class="pl-e">name</span>=<span class="pl-s"><span class="pl-pds">"</span>foo<span class="pl-pds">"</span></span> /&gt; bar:&lt;<span class="pl-ent">input</span> <span class="pl-e">type</span>=<span class="pl-s"><span class="pl-pds">"</span>text<span class="pl-pds">"</span></span> <span class="pl-e">name</span>=<span class="pl-s"><span class="pl-pds">"</span>bar<span class="pl-pds">"</span></span> /&gt; &lt;<span class="pl-ent">button</span> <span class="pl-e">type</span>=<span class="pl-s"><span class="pl-pds">"</span>submit<span class="pl-pds">"</span></span>&gt;submit&lt;/<span class="pl-ent">button</span>&gt; &lt;/<span class="pl-ent">form</span>&gt;</pre></div> <p>访问页面并提交后,可在 Chrome DevTools 网络面板看到,<code>/submit</code> 这个 POST 请求相关的信息:</p> <p>Request Headers</p> <pre><code>… Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryNgS8sggyuawQSr8W … </code></pre> <p>Form Data</p> <pre><code>------WebKitFormBoundaryNgS8sggyuawQSr8W Content-Disposition: form-data; name="foo"

1 ------WebKitFormBoundaryNgS8sggyuawQSr8W Content-Disposition: form-data; name="bar"

2 ------WebKitFormBoundaryNgS8sggyuawQSr8W-- </code></pre>

<p>这里 <code>------WebKitFormBoundaryNgS8sggyuawQSr8W</code> 便是上面提到的 <code>boundary </code>,用以分隔表单内容字段。</p> <h3>内容协商/Content Negotiation</h3> <p>前面提到客户端通过设置 Accept 请求头设置请求资源的类型,服务器根据 content negotiation 规则返回。</p> <p>Content negotiation 是这么一种机制,同一 URI可响应多种资源,客户端可自行决定请求何种资源(譬如文档的语言,图片格式,文件编码类型)。<br> <br> <a target="_blank" rel="noopener noreferrer" href="https://user-images.githubusercontent.com/3783096/50970937-c2ec1f00-151d-11e9-8c8e-9e98e742a626.png"><img src="https://user-images.githubusercontent.com/3783096/50970937-c2ec1f00-151d-11e9-8c8e-9e98e742a626.png" alt="image" style="max-width:100%;"></a><br> <em>来自 MDN 展示内容协商流程的图片</em></p> <p>内容协商包含两种方式:</p> <ul> <li>客户端通过设置请求头由服务器决定合适的类型进行返回(服务器驱动 )。</li> <li>服务器通过设置响应头中响应代码为 300 (<code>Multiple Choices</code>)或 406 (<code>Not Acceptable</code>)作为备用方案(客户端驱动)。</li> </ul> <p>除了 Accept ,用于主动发起内容协商的请求头还有:</p> <ul> <li><code>Accept-Charset</code>:期望的字符集。</li> <li><code>Accept-Encoding</code>:期望的编码方式。</li> <li><code>Accept-Language</code>:期望的语言。</li> </ul> <h4>服务器驱动的内容协商</h4> <p>由客户端发送一组期望的类型,服务器根据自己的算法决定出最合适的类型进行返回,具体实现因服务器类型而异。服务器驱动是最常见的方式,但其也有一些明显的缺点:</p> <ul> <li>由于不是完全了解客户端的兼容性,服务器的返回有时候存在局限性。相反,客户端驱动的是服务器返回多个选择,客户端根据自己的情况选用最合适的,因为客户端自己最了解自己支持哪些。</li> <li>关于客户端的信息在多次请求中会冗余(当然,请求头冗余的情况在 HTTP/2 中有所缓解),也存在安全隐患(HTTP fingerprinting)。</li> <li>多种类型的资源被返回后,服务端的缓存策略不再那么有效并且实现会变得复杂。</li> </ul> <h4>客户端驱动的内容协商</h4> <p><a target="_blank" rel="noopener noreferrer" href="https://user-images.githubusercontent.com/3783096/50970964-d13a3b00-151d-11e9-9538-d1264cb71f2b.png"><img src="https://user-images.githubusercontent.com/3783096/50970964-d13a3b00-151d-11e9-9538-d1264cb71f2b.png" alt="image" style="max-width:100%;"></a><br> <em>来自 MDN 展示客户端驱动内容协商流程的图片</em></p> <p>得到真实资源前多了一次选择的请求。</p> <h3>参考</h3> <ul> <li><a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept" rel="nofollow">Accept</a></li> <li><a href="https://webmasters.stackexchange.com/questions/31212/difference-between-the-accept-and-content-type-http-headers" rel="nofollow">Difference between the Accept and Content-Type HTTP headers</a></li> <li><a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Content_negotiation" rel="nofollow">Content negotiation</a></li> <li><a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Type" rel="nofollow">Content-Type</a></li> </ul> </td> </tr> </tbody> </table>

o
粉丝 0
博文 500
码字总数 0
作品 0
私信 提问
加载中
请先登录后再评论。
HTTP协议中的Accept与Content-Type的区别

HTTP协议中的Accept与Content-Type的区别 2018.06.07 22:53 19110浏览 在开发REST服务时,不可避免的需要了解HTTP协议的内容,其中,我们经常会用到 Accept 与 Content-Type,那么这两者有什...

GordonDicaprio
01/10
0
0
帮我看看这两段的区别

将网易几个图片域名加入web cache后 等待响应时间比没加入缓存之前要慢很多。 因为我是外行人 有些地方看不懂 还请大家帮忙看看这几个报头的区别。。 是不是说 等待响应时间慢是因为需要从外...

sepyj
2012/06/21
703
1
webkit浏览器常见开发问题

前段时间有人问我一个简单的问题,html如何创建解析的? 我讲了一大堆,什么通过DocumentLoader, CachedResourceLoader, CacheResource, ResourceLoaderScheduler, ResourceHandle这...

yang_danny
2015/04/15
14
0
Spring MVC 使用介绍(七)—— 注解式控制器(三):生产者与消费者模型

一、MIME类型 MIME类型格式:type/subtype(;parameter)? type:主类型,任意的字符串,如text,如果是号代表所有 subtype:子类型,任意的字符串,如html,如果是号代表所有 parameter:可选...

osc_jeoj68q8
2018/06/14
1
0
webkit浏览器常见开发问题

前段时间有人问我一个简单的问题,html如何创建解析的? 我讲了一大堆,什么通过DocumentLoader, CachedResourceLoader, CacheResource, ResourceLoaderScheduler, ResourceHandle这...

Android_Coder
2015/04/16
8
0

没有更多内容

加载失败,请刷新页面

加载更多

“睡服”面试官系列第三篇之变量的结构赋值(建议收藏学习)

目录 变量的解构赋值 1. 数组的解构赋值 2. 对象的解构赋值 3. 字符串的解构赋值 4. 数值和布尔值的解构赋值 5. 函数参数的解构赋值 6. 圆括号问题 7. 用途 变量的解构赋值 1. 数组的解构赋值...

osc_0q9or3wi
26分钟前
17
0
利用Bootstrap框架制作WordPress自适应主题

WordPress主题制作 第一课:511遇见wordpress本地环境搭建以及多站点配置 第二课:511遇见本地安装wordpress和修改Mysql登录密码 第三课:511遇见WordPress主题开发教程基本文件的建立 第四课...

osc_q27elio3
27分钟前
15
0
JavaScript闭包(1):闭包的形成机制梳理

JavaScript闭包的形成机制梳理 闭包前置知识:作用域,作用域链,变量生命周期 1.当我们调用函数的时候,js引擎为我们做了什么? 1.1举例说明 1.2 可能会引起的一些误解 2.JavaScript的垃圾回...

osc_ut5ykgwr
27分钟前
18
0
Less的常用语法

less的语法 1.注释语法 1.1 /**/ (多行注释) 这种注释是css的注释,编译以后,会保留显示在css文件中. 1.2 // (单行注释) // 这种代码注释css并不识别,编译后会隐藏,不会显示在css文件中. 2.变...

osc_ui34lpg3
29分钟前
6
0
利用宝塔面板实现快速搭建WordPress网站

宝塔面板添加WordPress站点 一、建站准备条件 条件1:阿里云服务器一台。原则上有台服务器就好了,不过我一般喜欢用大品牌,稳定和安全。 条件2: 阿里云域名一个。在哪家买的服务器,就用哪...

Arisono
30分钟前
15
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部