XMLHttpRequest(下)
跨域请求
当要在在页面中使用js获取其他网站的数据时,就会产生跨域问题,比如在网站中使用ajax请求其他网站的数据接口时浏览器就会提示以下错误。这种场景下就要解决js的跨域问题。
跨域的方式有多种,比如JSONP,CORS等。
JSONP解决方案
原理是浏览器的script标签是不受同源策略限制(你可以在你的网页中设置script的src属性问cdn服务器中静态文件的路径)。那么就可以使用script标签从服务器获取数据,请求时添加一个参数为callbakc=?,?号是要执行的回调方法。
这样在前端请求脚本,后端将返回的内容以脚本的方式运行,一般是callback(response)
的方式,这样就能获取到不同域的数据了
CORS方式
jsonp只能支持GET请求,因为加载脚本的时候只能使用get请求,对于post请求是无法完成的,所以就需要别的方式,比如CORS(跨域资源共享,Cross-Origin Resource Sharing)
CORS定义一种跨域访问的机制,可以让AJAX实现跨域访问。CORS 允许一个域上的网络应用向另一个域提交跨域 AJAX 请求。实现此功能非常简单,只需由服务器发送一个响应标头即可。比如从www.test1.com
向www.test2.com
发送请求,则需要在www.test2.com
的请求响应头中添加Access-Control-Allow-Origin:*
,即允许www.test1.com
这个域的请求,这样www.test1.com
就可以访问www.test2.com
的接口了。
CORS请求默认不发送Cookie和HTTP认证信息,如果需要发送这些信息的话,需要client和server都进行设置,在client中增加xhr.withCredentials = true;
,server的响应头中增加header('Access-Control-Allow-Credentials',true)
,二者缺一不可。而且如果要发送Cookie的话,Access-Control-Allow-Origin
就不能设置为*
了,必须指定请求来源的域名,而且原网页代码中的document.cookie
也无法读取服务器域名下的Cookie。需要服务端设置
如果发送的请求是复杂的请求,比如PUT,DELETE或者Content-Type为application/json,仍然是不能直接请求的,一般会有一次预检请求。浏览器先询问服务器,当前网页所在的域名是否在服务器的许可名单之中,以及可以使用哪些HTTP动词和头信息字段。只有得到肯定答复,浏览器才会发出正式的XMLHttpRequest请求,否则就报错。
HTTP Methods
https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html
类型 |
CRUD |
描述 |
GET |
Read |
获取内容 |
POST |
Create |
创建内容 |
PUT |
Update/Replace |
全部更新/替换 |
PATCH |
Update/Modify |
局部更新 |
DELETE |
Delete |
删除操作 |
容易混淆的请求类型:
- post和put:一般创建对象的话使用post,修改用put,URL也能反映二者的不同,如
/order/add
就是一个post请求,这个URL是由server决定的,而/order/edit/1002
就是一个PUT请求,表示对ID 1002的订单进行修改,这个URL是由client决定的。
- put和patch:put是全量更新,也就是完全替换,client提供一个完整的资源对象,缺失的字段会清空。而PATCH是增量更新,只是更新接受的字段,更节省资源。
不常用的几种Methods:
- OPTIONS:用于请求获得由Request-URI标识的资源在请求/响应的通信过程中可以使用的功能选项。通过这个方法,客户端可以在采取具体资源请求之前,决定对该资源采取何种必要措施,或者了解服务器的性能。
- HEAD: “HEAD”方式同“GET”基本一致,只是“ HEAD”请求不在回复中返回信息主体。这种方式用于获得关于不直接传送实体主体本身而暗含的实体的META信息。这个方式也常用于检测超文本链接的有效性,可用性,META和最近的更新。
- TRACE: TRACE方法是用来调用一个远程的请求信息应用程序层的循环后退。TRACE允许client看到通过请求链的那一端在接收了些什么并使用那些数据来测试和诊断信息情况。
- CONNECT: 规范的保留方法名称CONNECT,用于可动态切换到隧道的代理(什么鬼?)
HTTP Headers
HTTP头字段,指的是在超文本传输协议 (HTTP)的请求和回复消息中,协议头部分的那些信息。它们定义了某个超文本传输协议事务中的操作参数,如编码类型,解析方式等。自定义专用消息头可通过'X-' 前缀来添加。
请求字段
- Accept: 能够接受的响应内容类型(Content-Types),如
Accept: text/plain
- Accept-Charset: 能够接受的字符集,如
Accept-Charset: utf-8
- Accept-Encoding: 能够接受的编码方式列表,如
Accept-Encoding: gzip, deflate
- Accept-Language: 能够接受的回应内容的自然语言列表,如
Accept-Language: en-US
- Authorization:用于超文本传输协议的认证的认证信息,如
Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
- Cache-Control: 用来指定在这次的请求/回复链中的所有缓存机制,如
Cache-Control: no-cache
- Connection: 该浏览器想要优先使用的连接类型,如
Connection: keep-alive
- Cookie:Cookie内容,如
Cookie: $Version=1; Skin=new;
- Content-Length: 以 八位字节数组 (8位的字节)表示的请求体的长度,如
Content-Length: 348
- Content-Type:请求体的多媒体类型,
Content-Type: application/json
- Date:发送该消息的日期和时间,如
Date: Tue, 15 Nov 1994 08:12:31 GMT
- Expect:表明客户端要求服务器做出特定的行为,如
Expect: 100-continue
- From: 发起此请求的用户的邮件地址 ,如
From: user@example.com
- Host: 服务器的域名,以及服务器所监听的 传输控制协议端口号。如果所请求的端口是对应的服务的标准端口,则可被省略。 如
Host:127.0.0.1:8080
- Origin: 发起一个针对跨来源资源共享的请求,如
Origin:http://localhost:8083
- User-Agent: 浏览器的浏览器身份标识字符串,如
User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.71 Safari/537.36
- Upgrade: 要求服务器升级到另一个协议。 如
Upgrade: HTTP/2.0, SHTTP/1.3, IRC/6.9, RTA/x11
- Max-Forwards:限制该消息可被代理及网关转发的次数。 如
Max-Forwards: 10
- Proxy-Authorization:用来向代理进行认证的认证信息。 如
Proxy-Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
- Referer:表示浏览器所访问的前一个页面,正是那个页面上的某个链接将浏览器带到了当前所请求的这个页面。如
Referer: http://en.wikipedia.org/wiki/Main_Page
- TE: 浏览器预期接受的传输编码方式。如
TE: trailers, deflate
- Via: 向服务器告知,这个请求是由哪些代理发出的。 如
Via: 1.0 fred, 1.1 example.com (Apache/1.1)
- Warning: 一个一般性的警告,告知,在实体内容体中可能存在错误。
Warning: 199 Miscellaneous warning
响应字段
- Access-Control-Allow-Origin:指定哪些网站可参与到 跨来源资源共享 过程中,如
Access-Control-Allow-Origin: *
- Age:这个对象在 代理缓存 中存在的时间,以秒为单位,如
Age: 12
- Allow: 对于特定资源有效的动作。如
Allow: GET, HEAD
- Cache-Control:定义缓存策略。缓存指令是单向的,意味着请求中的给定指令不意味着在响应中给出相同的指令。其单位为秒,如
Cache-Control: max-age=3600
- Pragma: 与具体的实现相关,这些字段可能在请求/回应链中的任何时候产生多种效果。 它用于与HTTP/1.0缓存的向后兼容,其中Cache-Control 在HTTP/1.1报头尚未存在。
- Connection: 针对该连接所预期的选项,
Connection: keep-alive
- Content-Encoding: 在数据上使用的编码类型。
Content-Encoding: gzip
- Content-Length:回应消息体的长度,以 字节 (8位为一字节)为单位
- Content-Encoding: 在数据上使用的编码类型。参考 超文本传输协议压缩 。
- Content-Type:当前内容的MIME类型
- Date: 此条消息被发送时的日期和时间
- Expires:指定一个日期/时间,超过该时间则认为此回应已经过期,不合法的日期格式被认为是已经过期的,如果Cache-Control设置了"max-age" 或 "s-max-age",则Expires即无效
- Last-Modified:所请求的对象的最后修改日期(按照 RFC 7231 中定义的“超文本传输协议日期”格式来表示)
- Location:用来 进行 重定向 ,或者在创建了某个新资源时使用
- P3P: 用来设置P3P策略,是一种个人隐私安全平台项目(the Platform for Privary Preferences)的标准。能够保护在线隐私权,可以选择在浏览网页时,是否被第三方收集并利用自己的个人信息。
- Server: 服务器的名字
- Set-Cookie:HTTP Cookies,
Set-Cookie: UserID=JohnDoe; Max-Age=3600; Version=1
- Vary:告知下游的代理服务器,应当如何对未来的请求协议头进行匹配,以决定是否可使用已缓存的回应内容而不是重新从原始服务器请求新的内容。
Vary:Accept-Encoding
- Transfer-Encoding:用来将实体安全地传输给用户的编码形式。
transfer-encoding:chunked
HTTP Header的字段比较多,这里只摘录了比较常见的几个,更多的内容参考List of HTTP header fields,
Cache-Control
指定请求和响应中的缓存机制。 缓存指令是单向的,意味着请求中的给定指令不意味着在响应中给出相同的指令。默认是private
请求中的缓存指令
- Cache-Control: max-age=<seconds>
定义资源被重新加载的最长时间,时间是相对于请求的时间,和Expires是冲突的。
- Cache-Control: max-stale[=<seconds>]
表示client愿意接受已超过其到期时间的响应。可以指定一个单位为秒的时间以表示最大的响应过期时间
- Cache-Control: min-fresh=<seconds>
响应至少在指定的秒数内仍然是新的。
- Cache-control: no-cache
表示此请求或响应不能用缓存替代,强制将请求提交到源服务器进行验证。
- Cache-control: no-store
缓存不存储任何请求或响应的内容
- Cache-control: no-transform
不对资源进行转换。 Content-Encoding, Content-Range, Content-Type 等都不能由代理修改。
- Cache-control: only-if-cached
表示不去获取新数据。客户端只希望获取缓存的响应,并且不去联系服务器去检查是否存在较新的副本。
响应中的缓存指令
- Cache-control: must-revalidate
缓存必须在使用之前验证旧资源的状态,并且不可使用过期资源。
- Cache-control: no-cache
- Cache-control: no-store
- Cache-control: no-transform
- Cache-control: public
表示响应可以被任何缓存区缓存。
- Cache-control: private
表示对于单个用户的响应,不能被共享缓存处理。
- Cache-control: proxy-revalidate
与must-revalidate相同,但它仅适用于共享缓存(例如代理),并被私有缓存忽略。
- Cache-Control: max-age=
- Cache-control: s-maxage=
覆盖max-age 或者 Expires 头,但是仅适用于共享缓存(比如代理),并且可以被设置为私有缓存。
浏览器对不同缓存指令的响应
formData
可以通过JavaScript用一些键值对来模拟一系列表单控件,还可以使用XMLHttpRequest的send()方法来异步的提交这个"表单".比起普通的ajax,使用FormData的最大优点就是可以异步上传文件.
方法
- append:新增键值对,如果已经有同名的键,则新的值会追加到原来的值后面。注意在get的时候并不会获取到后append的值。第三个参数可选,用于指定文件名
- delete: 删除键,如果该键名不存在的话,返回null,而不是undefined
- entries: 返回一个迭代器,可以遍历formdata中的键值对。注意,遍历的时候,同名键的值不会合并
- get: 返回FormData对象中和指定的键关联的第一个值,如果你想要返回和指定键关联的全部值,那么可以使用getAll()方法。
- getAll: 返回同一个键的所有值组成是数组
- has: 判断是否包含某个名字的键
- keys: 返回一个迭代器,遍历所有的键,同名的会依次遍历多次
- set: 设置一个新的值在一个已经存在的键上,如果不存在的话,会进行创建
- values: 返回一个迭代器,遍历所有的值