写在前面
主要梳理了一些通用方法之类的,比较有用的内容是CORS protocol,这部分的内容主要参考了fetch在whatwg的文档
历史
XHR对象是用来获取网络资源的一个对象,其名字是历史性原因并不代表其功能。XHR对象最初是WHATWG的HTML定义的一部分。2006年移到了W3C中,其扩展(例如:progress events、cross-origin requests)写在了另一草案中(XHR Level2)。到2011年两份定义汇总到了一起成为了标准文档并重新回到了WHATWG。
Interface XMLHttpRequest
// 事件接口
interface XMLHttpRequestEventTarget : EventTarget {
// event handlers
attribute EventHandler onloadstart;
attribute EventHandler onprogress;
attribute EventHandler onabort;
attribute EventHandler onerror;
attribute EventHandler onload;
attribute EventHandler ontimeout;
attribute EventHandler onloadend;
};
// responseType枚举值
enum XMLHttpRequestResponseType {
"", "arraybuffer", "blob",
"document", "json", "text"
};
interface XMLHttpRequest : XMLHttpRequestEventTarget {
// event handler
attribute EventHandler onreadystatechange;
// states
const unsigned short UNSENT = 0;
const unsigned short OPENED = 1;
const unsigned short HEADERS_RECEIVED = 2;
const unsigned short LOADING = 3;
const unsigned short DONE = 4;
readonly attribute unsigned short readyState;
// request
void open(ByteString method, USVString url);
void open(ByteString method, USVString url, boolean async, optional USVString? username = null, optional USVString? password = null);
void setRequestHeader(ByteString name, ByteString value);
attribute unsigned long timeout;
attribute boolean withCredentials;
[SameObject] readonly attribute XMLHttpRequestUpload upload;
void send(optional (Document or BodyInit)? body = null);
void abort();
// response
readonly attribute USVString responseURL;
readonly attribute unsigned short status;
readonly attribute ByteString statusText;
ByteString? getResponseHeader(ByteString name);
ByteString getAllResponseHeaders();
void overrideMimeType(DOMString mime);
attribute XMLHttpRequestResponseType responseType;
readonly attribute any response;
readonly attribute USVString responseText;
[Exposed=Window] readonly attribute Document? responseXML;
}
垃圾回收
当XHR对象的state是opend/headers received/loading或者有事件监听器在readystatechange/progress/abort/error/load/timeout/loadend上时都不会被回收(注:但基于JavaScript的垃圾回收机制,当XHR对象是unreachable的时候也会被回收)
事件
loadstart/progress/abort/error/load/timeout/loadend这些集成与XMLHttpRequestEventTarget,readystatechange来自XMLHttpRequest对象本身
状态
分为五个状态:unsent 0 / opened 1 / headers received 2 / loading 3 / done 4(XHR.readyState)
- 我们判断请求是否完成就依靠这个状态值
Request
XHR对象有open/setRequestHeader/send/abort方法、timeout/withCredentials/upload/属性
- withCredentials控制是否在发送请求时携带credentials,参考注1
Response
XHR对象有responseURL/status/statusText/responseType/response/responseText/responseXML属性、getResponseHeader/getAllResponseHeaders/overrideMimeType方法
- 其中status和readyState是我们判断请求情况的两个依赖值;
- responseType枚举:""、“arraybuffer”、“text”、“blob”、“document”、“json”、“text”
- overrideMimeType强制服务器返回的response带有指定的"Content-Type"header
Interface FormData
interface FormData {
void append(USVString name, USVString value);
void append(USVString name, Blob blobValue, optional USVString filename);
void delete(USVString name);
FormDataEntryValue? get(USVString name);
sequence<FormDataEntryValue> getAll(USVString name);
boolean has(USVString name);
void set(USVString name, USVString value);
void set(USVString name, Blob blobValue, optional USVString filename);
iterable<USVString, FormDataEntryValue>;
};
append(name, value/blobValue [, filename] ):根据name和value添加一个值;
delete(name):根据name删除一个值;
get(name):获取name下的第一个添加进去的值;
getAll(name):获取name下的所有值;
has(name):当name存在时返回true,否则返回false;
set(name, value/blobValue [,filename]):对name对应的值进行set,会把此前的值清空;
Interface ProgressEvent
interface ProgressEvent : Event {
readonly attribute boolean lengthComputable;
readonly attribute unsigned long long loaded;
readonly attribute unsigned long long total;
};
loadstart事件后会多次触发,可以读取其中的loaded/total算出总进度
安全策略CORS protocol
为了跨域分享资源,允许比HTML表单更多样化的提起,所以有了CORS protocol。
总
CORS protocol由众多的标示response可跨域 http header 组成。对于request可能类型远多于HTML form表单,所以一个CORS-preflight request会先发出OPTIONS请求以确保当前的URL是否支持CORS protocol。
HTTP requests
CORS request是包含Origin
头的HTTP协议,但这并不能够认为所有包含Origin
头的请求都是CORS request,因为GET
/HEAD
意外的请求也都包含Origin
头。
CORS-preflight request会包含Access-Control-Request-Method
(指示对于CORS request将会使用哪一种method来获取资源)和Access-Control-Request-Headers
(指示CORS request将会使用哪一些http headers)
HTTP responses
Access-Control-Allow-Origin
:指出这个response是否能够跨域共享,返回请求头里的Origin
的value或者’*’;
Access-Control-Allow-Credentials
:指出当request’s credentials mode[注1]是’include’时response是否能被跨域共享,值’true’;
Access-Control-Allow-Methods
:指出response资源在CORS protocol中一共支持哪些方法;
Access-Control-Allow-Headers
:指出response资源在CORS protocol中一个工支持哪些头;
Access-Control-Max-Age
:指出response资源在CORS protocol中能够被缓存多久;
Access-Control-Expose-Headers
:指出response header头中哪些头可以被client获取到(default:Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma)
// request
Access-Control-Request-Method = 'GET,POST'
Access-Control-Request-Headers = 'accept'
// response
Access-Control-Allow-Origin = origin-or-null / '*'
Access-Control-Allow-Credentials = 'true' (大小写敏感)
Access-Control-Allow-Methods = 'GET,OPTIONS,POST'
Access-Control-Allow-Headers = 'accept,Content-Type'
CORS protocol and credentials 跨域和凭证
假如www.a.com发起跨域请求,下面有个表来标示资源到底是否能被跨域共享
请求 credentials mode | Access-Control-Allow-Origin 头 | Access-Control-Allow-Credentials 头 | 是否共享 | 注 |
---|---|---|---|---|
‘omit’ | ‘*’ | Omitted | 是 | |
‘omit’ | ‘*’ | ‘true’ | 是 | |
‘omit’ | ‘https://www.a.com/’ | Omitted | 否 | 不应该带有末尾的’/’ |
‘omit’ | ‘https://www.a.com’ | Omitted | 是 | |
‘inclued’ | ‘*’ | ‘true’ | 否 | 如果credentials mode是include 那么Access-Control-Allow-Origin 头就不能是’*’ |
‘inclued’ | '‘https://www.a.com’ | ‘true’ | 是 | |
‘inclued’ | '‘https://www.a.com’ | ‘True’ | 否 | 大小写敏感 |
注
- credentials mode:共有三个值’omit’-发送请求时不允许携带任何credentials(凭证:cookie),'same-orgin’发送请求时允许携带同源credentials,'include’发送请求时总是携带所有credentials。这是一个定义在Fetch中的内容Fetch中由Request的credentials值决定,XHR中
withCredentials
属性与此类似。