Rodrick

vuePress-theme-reco Rodrick    2022
Rodrick Rodrick

Choose mode

  • dark
  • auto
  • light
Home
Category
  • CS基础
  • 数据库
  • 前端
  • 其他
Tag
About
Timeline
D&T
  • 官方文档

    • Vue
    • Vue3
    • Webpack
    • MDN
    • Node中文网
    • React
    • 小程序
    • FineReport
  • 学习面试

    • 现代JavaScript教程
    • ES6
    • 阿西河
    • LeetCode
    • 牛客网
  • 工具

    • bejson
Contact
  • Github
  • Gitee
author-avatar

Rodrick

62

Article

18

Tag

Home
Category
  • CS基础
  • 数据库
  • 前端
  • 其他
Tag
About
Timeline
D&T
  • 官方文档

    • Vue
    • Vue3
    • Webpack
    • MDN
    • Node中文网
    • React
    • 小程序
    • FineReport
  • 学习面试

    • 现代JavaScript教程
    • ES6
    • 阿西河
    • LeetCode
    • 牛客网
  • 工具

    • bejson
Contact
  • Github
  • Gitee
  • JS

    • ES6核心语法
    • 模块化&Webpack
    • Promise&异步函数async
    • WebSocket原理浅析
    • axios的使用
    • ES5的变量提升和ES6的暂时性死区
    • call、apply、bind的用法
    • 对象的原始值转换
    • 可选链"?."
    • 随机数方法
    • 深浅拷贝实现
    • Array常用处理
    • 防抖与节流
    • postMessage窗口间通讯
    • 解构赋值
    • Map&Set
    • 日期和时间
    • 对象属性
    • Toast组件简单封装
    • 原型链
    • 类 Class
    • Generator与异步迭代
    • 偏函数Partial和柯里化Currying
    • DOM操作
    • 事件处理
    • 事件循环EventLoop
    • 网络请求
    • 浏览器中存储数据
    • 正则表达式
  • CSS

  • 其他

网络请求

vuePress-theme-reco Rodrick    2022

网络请求

Rodrick 2020-12-12 js

# Fetch 基本使用

fetch 返回一个 promise ,常用方式:

let response = await fetch(url, options); // 解析 response header
let result = await response.json(); // 将 body 读取为 json
  • options :
    • method :HTTP 方法,如 get、post……

    • headers :请求头,但是有一些 header 是不被允许的,详见规范

    • body :request body,要以 string , FormData , BufferSource , Blob  或 UrlSearchParams  对象的形式发送的数据

接收到的 response 属性如下:

  • response.status —— response 的 HTTP 状态码,
  • response.ok —— HTTP 状态码为 200-299,则为 true。
  • response.headers —— 类似于 Map 的带有 HTTP header 的对象。

注意 ,只有在无法建立一个 HTTP 请求的时候, fetch 才会 reject 。而异常的 404、500 等状态不会导致异常

获取 response body :

  • response.text() —— 读取 response,并以文本形式返回 response,
  • response.json() —— 将 response 解析为 JSON 对象形式,
  • response.formData() —— 以 FormData 对象(form/multipart 编码,参见下一章)的形式返回 response,
  • response.blob() —— 以 Blob (具有类型的二进制数据)形式返回 response,
  • response.arrayBuffer() —— 以 ArrayBuffer (低级别的二进制数据)形式返回 response。

# FormData

# 发送表单

FormData 对象可以发送表单对象内容,比如:

<form id="formElem">
  <input type="text" name="name" value="John">
  <input type="text" name="surname" value="Smith">
  <input type="submit">
</form>

<script>
  formElem.onsubmit = async (e) => {
    e.preventDefault();

    let response = await fetch('/article/formdata/post/user', {
      method: 'POST',
      body: new FormData(formElem)
    });

    let result = await response.json();

    alert(result.message);
  };
</script>

这样可以把整个表单对象发送出去。

我们也可以通过以下方法去修改添加表单对象到 FormData  :

  • formData.append(name, value)  —— 添加具有给定 name 和 value 的表单字段,
  • formData.append(name, blob, fileName)  —— 添加一个字段,就像它是 <input type='file'>  ,第三个参数 fileName 设置文件名(而不是表单字段名),因为它是用户文件系统中文件的名称
  • formData.set(name,value) —— set 方法会清楚当前 formData 中所有此 name 的字段,然后插入新的 value
  • formData.set(name,blob,value) —— 原理同上
  • formData.delete(name)  —— 移除带有给定 name 的字段,
  • formData.get(name)  —— 获取带有给定 name 的字段值,
  • formData.has(name)  —— 如果存在带有给定 name 的字段,则返回 true,否则返回 false。

FormData 对象是可以循环的 : for(let[key,value] of formData){}

# 发送文件

<input type="file"> 允许我们发送一个文件:

<input type="file" id="pic">
  
<script>
  let formData = new FormData()
  pic.onchange = function(e){
		formData.append("fileIn",this.value)
	}
  let response = await fetch('/xxx', {
    method: 'POST',
    body: formData
  });

  let result = await response.json();
  
  
</script>

# 下载进度

可以通过 response.body ,它是 ReadableStream —— 一个特殊的对象,它可以逐块(chunk)提供 body。在 Streams API  规范中有对 ReadableStream 的详细描述。 然后可以通过他的 getReader() 来获取一个流读取器(stream reader):

// Step 1:启动 fetch,并获得一个 reader
let response = await fetch('https://api.github.com/repos/javascript-tutorial/en.javascript.info/commits?per_page=100');

const reader = response.body.getReader();

// Step 2:获得总长度(length)
const contentLength = +response.headers.get('Content-Length');

// Step 3:读取数据
let receivedLength = 0; // 当前接收到了这么多字节
let chunks = []; // 接收到的二进制块的数组(包括 body)
while(true) {
  // read() 会返回done —— 读取完成时是 true,否则 false
  //还有 value —— 字节的类型化数组:Uint8Array。
  const {done, value} = await reader.read();

  if (done) {
    break;
  }
	// 每拿到一块 就放入二进制数组
  chunks.push(value);
  receivedLength += value.length;

  console.log(`Received ${receivedLength} of ${contentLength}`)
}
// 接收已完成,以下是处理过程。
// Step 4:将块连接到单个 Uint8Array
let chunksAll = new Uint8Array(receivedLength); // (4.1)
let position = 0;
for(let chunk of chunks) {
  chunksAll.set(chunk, position); // (4.2)
  position += chunk.length;
}

// Step 5:解码成字符串
let result = new TextDecoder("utf-8").decode(chunksAll);

// 我们完成啦!
let commits = JSON.parse(result);

# Fetch 中止

我们有一个 AbortController 对象,他的用法很简单:

let aContro = new AbortController()
// 属性 signal,我们可以在这个属性上设置事件监听器。
let singal = aContro.signal
// 方法 abort()
aContro.abort()
// 事件触发后,signal.aborted 变为 true
alert(signal.aborted); // true

结合 fetch:

// 1 秒后中止
let controller = new AbortController();
setTimeout(() => controller.abort(), 1000);

try {
  let response = await fetch('/article/fetch-abort/demo/hang', {
    signal: controller.signal
  });
} catch(err) {
  if (err.name == 'AbortError') { // handle abort()
    alert("Aborted!");
  } else {
    throw err;
  }
}

# Fetch Api

fetch 还有很多 api,详见 现代教程

# CORS 跨域

"CORS" :跨源资源共享(Cross-Origin Resource Sharing)。

# JSONP

JSONP 的原理很简单,就是利用一个 script 标签,然后我们的信息作为回调函数传过去来实现跨域:

function gotWeather({ temperature, humidity }) {
  alert(`temperature: ${temperature}, humidity: ${humidity}`);
}

let script = document.createElement('script');
script.src = `http://another.com/weather.json?callback=gotWeather`;
document.body.append(script);

# 简单跨域请求

首先,简单跨域请求需要满足如下条件:

  • method —— GET,POST 或 HEAD
  • headers —— 仅允许自定义下列 header:
    • Accept,
    • Accept-Language,
    • Content-Language,
    • Content-Type 的值为 application/x-www-form-urlencoded,multipart/form-data 或 text/plain。

如果我们的跨域请求是一个简单请求,在发送 request 的时候,浏览器会自动添加 Origin header,服务器需要进行对 Origin 的检查,如果同意这个源的 request ,那么在 response 里就会添加一个 Access-Control-Allow-Origin 的响应头,这个响应头的内容可以是我们刚才的 Origin ,或者是一个 * 号 : image.png

而且在这种简单请求中,我们只能访问简单的 response header :

  • Cache-Control
  • Content-Language
  • Content-Type
  • Expires
  • Last-Modified
  • Pragma

其他的都不可访问

# 非简单跨域请求

不满足我们上面说的 request 条件的请求视为非简单请求,比如 method 是 PUT ,发送这样的请求的时候,浏览器会在发送正式请求前 **加一个预检(preflight) **的请求

预检请求使用 OPTIONS method,它没有 body ,但是有两个关键 header :

  • Access-Control-Request-Method —— 正式请求中带有的非简单请求的 method
  • Access-Control-Request-Headers —— 正式请求中带有的非简单的 HTTP-Header 列表,用 , 分隔

而服务器端同意处理也会返回一个状态码为 200 ,没有 body 但是有一些特殊 header 的 response:

  • Access-Control-Allow-Origin 必须为 * 或进行请求的源(例如 [https://javascript.info](https://javascript.info))才能允许此请求。
  • Access-Control-Allow-Methods 必须具有允许的方法。
  • Access-Control-Allow-Headers 必须具有一个允许的 header 列表。
  • 另外,header Access-Control-Max-Age 可以指定缓存此权限的秒数。因此,浏览器不是必须为满足给定权限的后续请求发送预检。

image.png 预检请求整个过程对于 JavaScript 是不可见的!JavaScript 仅仅获取主请求的 response

# 非简单跨域例子

假设我们现在有一个跨域请求

let response = await fetch('https://site.com/service.json', {
  method: 'PATCH',
  headers: {
    'Content-Type': 'application/json',
    'API-Key': 'secret'
  }
});

他的 method 、 headers 都不满足简单请求的规则,那么接下来会发生非简单请求:

# 第一步 发送预检请求

浏览器检测到非简单跨域请求后,会自动先发送一个预检

OPTIONS /service.json
Host: site.com
Origin: https://javascript.info
Access-Control-Request-Method: PATCH
Access-Control-Request-Headers: Content-Type,API-Key

包含了上面说的非简单请求的 method 和 非简单的 HTTP-Header 列表

# 第二步 服务器响应预检请求

200 OK
Access-Control-Allow-Origin: https://javascript.info
Access-Control-Allow-Methods: PUT,PATCH,DELETE
Access-Control-Allow-Headers: API-Key,Content-Type,If-Modified-Since,Cache-Control
Access-Control-Max-Age: 86400

这个 response 表示:

  1. 请求通过 200 ,
  2. 允许的 Origin 是我们 request 的源,
  3. 他不仅允许我们 request 的 PATCH ,还允许 PUT/DELETE 等特殊 method ,当然 GET,POST 或 HEAD 本身就是允许的,response 不用写进去
  4. 也允许了一些 header : API-Key,Content-Type,If-Modified-Since,Cache-Control
  5. 设置了缓存时间一天,后续的请求就不用再触发预检了

# 第三步 发送实际请求

通过了预检,自然是开始发送实际 requset,注意浏览器一定会加上 Origin header ,因为他是跨域的

PATCH /service.json
Host: site.com
Content-Type: application/json
API-Key: secret
Origin: https://javascript.info

# 第四步 返回实际响应

服务器返回的 response 也必须加上 Access-Control-Allow-Origin,即时我们已经通过了预检

Access-Control-Allow-Origin: https://javascript.info

至此一个非简单跨域完成

# 凭据

在上面的跨域情况中,无法发送任何 凭据(cookies 或者 HTTP 认证)  这是因为具有凭据的请求比没有凭据的请求要强大得多。如果被允许,它会使用它们的凭据授予 JavaScript 代表用户行为和访问敏感信息的全部权力。 如果需要发送凭据,需要加上 credentials: "include" :

fetch('http://another.com', {
  credentials: "include"
});

而服务器如果同意接受带有凭据的请求,那么需要加上一个 header: Access-Control-Allow-Credentials: true ,当然也别忘记必须有的 Access-Control-Allow-Origin

200 OK
Access-Control-Allow-Origin: https://javascript.info
Access-Control-Allow-Credentials: true

# URL 对象

以往我们打开一个窗口,可能会用如下方式:

window.open("https://zh.javascript.info/url")

这种方式,url 是一串字符串,而现在我们有一个内建的 URL 对象

new URL(url, [base])

如下两个 url 是一样的

let url1 = new URL('https://javascript.info/profile/admin');
let url2 = new URL('/profile/admin', 'https://javascript.info');

alert(url1); // https://javascript.info/profile/admin
alert(url2); // https://javascript.info/profile/admin

也可以根据现有 URL 创建新 URL

let url = new URL('https://javascript.info/profile/admin');
let newUrl = new URL('tester', url);

alert(newUrl); // https://javascript.info/profile/tester

还可以访问他的组件属性

let url = new URL('https://javascript.info/url');

alert(url.protocol); // https:
alert(url.host);     // javascript.info
alert(url.pathname); // /url

image.png 我们还可以处理 url 的参数:

  • append(name, value)  —— 按照 name 添加参数,
  • delete(name)  —— 按照 name 移除参数,
  • get(name)  —— 按照 name 获取参数,
  • getAll(name) —— 获取相同 name 的所有参数(这是可行的,例如 ?user=John&user=Pete),
  • has(name)  —— 按照 name 检查参数是否存在,
  • set(name, value)  —— set/replace 参数,
  • sort()  —— 按 name 对参数进行排序,很少使用,

这些方法处理参数的时候,会自动进行编码 传统的编码一般是用这些方法:

  • encodeURI —— 编码整个 URL。
  • decodeURI —— 解码为编码前的状态。
  • encodeURIComponent —— 编码 URL 组件,例如搜索参数,或者 hash,或者 pathname。
  • decodeURIComponent —— 解码为编码前的状态。

# 轮询

# 短轮询

短轮询就是定时地对服务器进行 request

# 长轮询

发送 request -> 消息挂起 -> 服务器 response 返回 -> 客户端处理 response -> 发起下一个 request

async function subscribe() {
  let response = await fetch("/subscribe");

  if (response.status == 502) {
    // 状态 502 是连接超时错误,
    // 连接挂起时间过长时可能会发生,
    // 远程服务器或代理会关闭它
    // 让我们重新连接
    await subscribe();
  } else if (response.status != 200) {
    // 一个 error —— 让我们显示它
    showMessage(response.statusText);
    // 一秒后重新连接
    await new Promise(resolve => setTimeout(resolve, 1000));
    await subscribe();
  } else {
    // 获取并显示消息
    let message = await response.text();
    showMessage(message);
    // 再次调用 subscribe() 以获取下一条消息
    await subscribe();
  }
}

subscribe();

# WebSocket

# 创建连接

WebSocket  协议提供了一种在浏览器和服务器之间建立持久连接来交换数据的方法。数据可以作为“数据包”在两个方向上传递,而不会断开连接和其他 HTTP 请求。

let socket = new WebSocket("ws://javascript.info");

ws 是一个特殊的协议 ,还有一个 wss 协议,类似于 HTTPS 他是加密的,建议使用 wss://

  • open   —— 连接已建立,
  • message   —— 接收到数据,
  • error   —— WebSocket 错误,
  • close   —— 连接已关闭。
let socket = new WebSocket("wss://javascript.info/article/websocket/demo/hello");

socket.onopen = function(e) {
  alert("[open] Connection established");
  alert("Sending to server");
  socket.send("My name is John");
};

socket.onmessage = function(event) {
  alert(`[message] Data received from server: ${event.data}`);
};

socket.onclose = function(event) {
  if (event.wasClean) {
    alert(`[close] Connection closed cleanly, code=${event.code} reason=${event.reason}`);
  } else {
    // 例如服务器进程被杀死或网络中断
    // 在这种情况下,event.code 通常为 1006
    alert('[close] Connection died');
  }
};

socket.onerror = function(error) {
  alert(`[error] ${error.message}`);
};

# request

以下是由 new WebSocket("wss://javascript.info/chat")  发出的请求的浏览器 header 示例。

GET /chat
Host: javascript.info
Origin: https://javascript.info    [客户端页面的源]
Connection: Upgrade		[Upgrade —— 表示客户端想要更改协议。]
Upgrade: websocket		[websocket —— 请求的协议是 “websocket”]
Sec-WebSocket-Key: Iv8io/9s+lYFgZWcXczP8Q==		[浏览器随机生成的安全密钥]
Sec-WebSocket-Version: 13		[WebSocket 协议版本,当前为 13]

这些 header 在JavaScript 中不可见。 还有 Sec-WebSocket-Protocol: soap, wamp 代表我们不仅要传输任何数据,还要传输 SOAP  或 WAMP 协议中的数据。这个是我们可设置的:

let socket = new WebSocket("wss://javascript.info/chat", ["soap", "wamp"]);

# 数据传输

WebSocket 通信由 “frames”(即数据片段)组成,可以从任何一方发送,并且有以下几种类型:

  • “text frames” —— 包含各方发送给彼此的文本数据。
  • “binary data frames” —— 包含各方发送给彼此的二进制数据。
  • “ping/pong frames” 被用于检查从服务器发送的连接,浏览器会自动响应它们。
  • 还有 “connection close frame” 以及其他服务 frames。

客户端请求 .send() 可以发送文本和二进制数据(包括 Blob,ArrayBuffer 等)

而接收到 response 的时候,文本肯定是字符串的形式,但是如果是个二进制数据,可以通过 socket.binaryType 来设置格式类型,默认值就是 blob 。

socket.binaryType = "arraybuffer"; // 默认值是 blob 可以不设置
socket.onmessage = (event) => {
  // event.data 可以是文本(如果是文本),也可以是 arraybuffer(如果是二进制数据)
};

# 缓冲数据

假设我们一次发送了很多数据,但是网很慢,当我们反复 send() 的情况下,数据会缓存进内存, socket.bufferedAmount 可以查询当前缓存了多少字节

// 每 100ms 检查一次 socket
// 仅当所有现有的数据都已被发送出去时,再发送更多数据
setInterval(() => {
  if (socket.bufferedAmount == 0) {
    socket.send(moreData());
  }
}, 100);

# 关闭连接

不管是客户端还是服务端都可以主动关闭连接,当需要关闭的时候:

socket.close(code,reason)
  • code —— 一个关闭码:
    • 1000 —— 默认,正常关闭(如果没有指明 code 时使用它),
    • 1006 —— 没有办法手动设定这个数字码,表示连接丢失(没有 close frame)。
    • 1001 —— 一方正在离开,例如服务器正在关闭,或者浏览器离开了该页面,
    • 1009 —— 消息太大,无法处理,
    • 1011 —— 服务器上发生意外错误
  • reason —— 关闭原因,比如 “work complete”

我们可以在 close 事件中获取他们: event.code / event.reason

# 连接状态

要获取连接状态,可以通过带有值的 socket.readyState 属性:

  • 0 —— “CONNECTING”:连接还未建立,
  • 1 —— “OPEN”:通信中,
  • 2 —— “CLOSING”:连接关闭中,
  • 3 —— “CLOSED”:连接已关闭。

# 补充:Web Worker

既然上面提到了 WebSocket,那就顺带提一下 Web Worker

其实是我也不知道应该把它放在哪一块内容比较合适🙄

# 1. 概念

Web Worker 为Web内容在后台线程中运行脚本提供了一种简单的方法。线程可以执行任务而不干扰用户界面。注意,在worker内,不能直接操作DOM节点,也不能使用 window 对象的默认方法和属性。

# 2. 方法

先看一个例子:

  • index.html
<body>
  <div> 计数: <output id="result">0</output></div>
  <button onclick="start()">开始worker</button>
  <button onclick="end()">结束worker</button>
  <script>
    let worker
    function start() {
      // 检测浏览器是否支持 Web Worker
      if (typeof Worker === "undefined") {
        alert(`sor,br dont support`)
      } else {
        if (typeof worker == "undefined") {
          worker = new Worker("worker.js")
        }
        worker.onmessage = function (e) {
          result.textContent = e.data
        }
        worker.onerror = function(e){
          console.error(`错误信息:${e.message};错误脚本:${e.filename};错误行号:${e.lineno}`);
        }
      }
    }
    function end() {
      worker.terminate()
    }
  </script>
</body>
  • worker.js
let i = 0
function count() {
  if (++i == 10) close();
  postMessage(i)
  setTimeout(() => {
    count()
  }, 500)
}
count()

接下来结合上述代码说明一些方法👇

# 检测浏览器是否支持 Web Worker

if(typeof Worker !== "undefined"){
    // 是的! Web worker 支持!
    // 一些代码.....
}else{
    //抱歉! Web Worker 不支持 
}

# 开启一个 Web Worker

if (typeof worker == "undefined") {
  worker = new Worker("worker.js")
}

# worker 发送消息

postMessage(i)

# 接收 message

用 message 事件接收, e.data 是获取传来的数据

 worker.onmessage = function (e) {
   result.textContent = e.data
 }

# 终止 Web Worker

  • 在主线程上结束

如果你需要从主线程中立刻终止一个运行中的worker,可以调用 worker 的 terminate 方法,worker 线程会被立即杀死,不会有任何机会让它完成自己的操作或清理工作。:

worker.terminate()
  • 在 worker 线程中结束
close()

# 错误处理 error

  • message 可读性良好的错误消息。
  • filename 发生错误的脚本文件名。
  • lineno 发生错误时所在脚本文件的行号。
worker.onerror = function(e){
  console.error(`错误信息:${e.message};错误脚本:${e.filename};错误行号:${e.lineno}`);
}

# 补充:常用请求头

协议头 说明 示例
Accept 可接受的响应内容类型(Content-Types)。 Accept: text/plain
Accept-Charset 可接受的字符集 Accept-Charset: utf-8
Accept-Encoding 可接受的响应内容的编码方式。 Accept-Encoding: gzip, deflate
Accept-Language 可接受的响应内容语言列表。 Accept-Language: en-US
Accept-Datetime 可接受的按照时间来表示的响应内容版本 Accept-Datetime: Sat, 26 Dec 2015 17:30:00 GMT
Authorization 用于表示HTTP协议中需要认证资源的认证信息 Authorization: Basic OSdjJGRpbjpvcGVuIANlc2SdDE==
Cache-Control 用来指定当前的请求/回复中的,是否使用缓存机制。 Cache-Control: no-cache
Connection 客户端(浏览器)想要优先使用的连接类型 Connection: keep-alive``Connection: Upgrade
Cookie 由之前服务器通过Set-Cookie(见下文)设置的一个HTTP协议Cookie Cookie: $Version=1; Skin=new;
Content-Length 以8进制表示的请求体的长度 Content-Length: 348
Content-MD5 请求体的内容的二进制 MD5 散列值(数字签名),以 Base64 编码的结果 Content-MD5: oD8dH2sgSW50ZWdyaIEd9D==
Content-Type 请求体的MIME类型 (用于POST和PUT请求中) Content-Type: application/x-www-form-urlencoded
Date 发送该消息的日期和时间(以RFC 7231 中定义的"HTTP日期"格式来发送) Date: Dec, 26 Dec 2015 17:30:00 GMT
Expect 表示客户端要求服务器做出特定的行为 Expect: 100-continue
From 发起此请求的用户的邮件地址 From: user@itbilu.com
Host 表示服务器的域名以及服务器所监听的端口号。如果所请求的端口是对应的服务的标准端口(80),则端口号可以省略。 Host: www.itbilu.com:80``Host: www.itbilu.com
If-Match 仅当客户端提供的实体与服务器上对应的实体相匹配时,才进行对应的操作。主要用于像 PUT 这样的方法中,仅当从用户上次更新某个资源后,该资源未被修改的情况下,才更新该资源。 If-Match: "9jd00cdj34pss9ejqiw39d82f20d0ikd"
If-Modified-Since 允许在对应的资源未被修改的情况下返回304未修改 If-Modified-Since: Dec, 26 Dec 2015 17:30:00 GMT
If-None-Match 允许在对应的内容未被修改的情况下返回304未修改( 304 Not Modified ),参考 超文本传输协议 的实体标记 If-None-Match: "9jd00cdj34pss9ejqiw39d82f20d0ikd"
If-Range 如果该实体未被修改过,则向返回所缺少的那一个或多个部分。否则,返回整个新的实体 If-Range: "9jd00cdj34pss9ejqiw39d82f20d0ikd"
If-Unmodified-Since 仅当该实体自某个特定时间以来未被修改的情况下,才发送回应。 If-Unmodified-Since: Dec, 26 Dec 2015 17:30:00 GMT
Max-Forwards 限制该消息可被代理及网关转发的次数。 Max-Forwards: 10
Origin 发起一个针对跨域资源共享 的请求(该请求要求服务器在响应中加入一个Access-Control-Allow-Origin的消息头,表示访问控制所允许的来源)。 Origin: http://www.itbilu.com
Pragma 与具体的实现相关,这些字段可能在请求/回应链中的任何时候产生。 Pragma: no-cache
Proxy-Authorization 用于向代理进行认证的认证信息。 Proxy-Authorization: Basic IOoDZRgDOi0vcGVuIHNlNidJi2==
Range 表示请求某个实体的一部分,字节偏移以0开始。 Range: bytes=500-999
Referer 表示浏览器所访问的前一个页面,可以认为是之前访问页面的链接将浏览器带到了当前页面。Referer其实是Referrer这个单词,但RFC制作标准时给拼错了,后来也就将错就错使用Referer了。 Referer: http://itbilu.com/nodejs
TE 浏览器预期接受的传输时的编码方式:可使用回应协议头Transfer-Encoding中的值(还可以使用"trailers"表示数据传输时的分块方式)用来表示浏览器希望在最后一个大小为0的块之后还接收到一些额外的字段。 TE: trailers,deflate
User-Agent 浏览器的身份标识字符串 User-Agent: Mozilla/……
Upgrade 要求服务器升级到一个高版本协议。 Upgrade: HTTP/2.0, SHTTP/1.3, IRC/6.9, RTA/x11
Via 告诉服务器,这个请求是由哪些代理发出的。 Via: 1.0 fred, 1.1 itbilu.com.com (Apache/1.1)
Warning 一个一般性的警告,表示在实体内容体中可能存在错误。 Warning: 199 Miscellaneous warning
欢迎来到 Rodrick
看板娘