跨域 | http请求中的 OPTIONS 详解

一、导读

有过跨域请求的同学们应该发现过一个http请求有时会请求2次的时候,今天就给大家说说这个http请求的OPTIONS 方法是如何产生以及作用是啥。

二、解释

互联网上的各个节点之间本来都是连通的,但是有些节点,比如我们的个人电脑连接另外一些节点(比如服务器)的时候,总是通过浏览器。这样,浏览器作为一个中间人,就有机会管理一些连接,就好像高速路上的收费站检查进出的车辆。

这个类比还有一个可以借鉴的地方:就像收费站会根据一些章程文件来检查进出车辆,浏览器也根据一些技术约定来管理进出的连接。这些技术约定由 W3C,WHATWG 等组织制定。

我们今天要谈的跨域请求,Cross Origin Resource Sharing ( CORS ),就是浏览器执行的一种技术约定,一种 Protocol。

那么具体来说,到底什么是“跨域请求”呢?

首先,“域”(Origin)是指浏览器地址栏中显示的主机地址。“跨域”,就是网页程序想要请求的地址和地址栏中的“域”不同。合起来就是,一个网页程序想要去别人家的地址[1]索要资源。

这个概念基本上只在涉及浏览器的网页应用中会出现。在浏览器之外,“域”的概念(浏览器地址栏中显示的主机地址)都没有了,更谈不上跨域了。但这个概念也是重要的,因为目前主流的浏览器,不论是电脑上的,还是手机上的,都支持这个约定;也就是说,不论是哪家的浏览器,只要在他们的地盘活动,这个约定是必须要考虑的。

如果违反这个 Protocol 中的约定,会有什么后果么?

有一些 request 会收不到 response,因为 response 被浏览器拦截了,内容不告诉你
另外一些请求会根本发不出去,因为浏览器不允许发出那样的 request。
接下来,我们就来讨论,哪些情况会导致收不到 response,哪些情况会导致 request 失败。

Simple Requests 如何跨域请求
我们定义一种 request 叫 simple request,当且仅当一个 request 满足下面全部条件的时候:

request method 只能是 GET,HEAD,POST
只能有浏览器默认添加的 headers,以及一些 CORS 协议中默许的 headers 比如 Accept 等,更多被允许的 headers,可以看这里
Content-Type这个header的value只能是特定的3个
在 js 代码中不要使用特定的方法,可参见文档
一旦一个 request 是 simple request,那么,尽管这个请求是跨域的,它也会被浏览器直接放行。但是,在 response 返回的时候,浏览器并不会把 response 直接交给你,而是去检查这个 response 的 headers 中有没有 Access-Control-Allow-Origin,以及这个 header 的 value 包含 request 发出的地址(也就是“域”)。

如果两个条件都满足, response 会被返回给发出请求的程序;如果没有这个 header 或者 value 不对, response 就会被拦截下来,因为在浏览器看来,这个 response 不属于你(因为服务器没有明确允许你这个“域”来请求它)。如果你使用的是 chrome 浏览器,在 response 被拦截下来的时候,console 中会显示一个类似于下面的错误信息:

repeat this in your console
尽管发出request的程序无法得到 response,但是这个请求实际上是被发出了的,而且服务器也会完整的处理这个request。可以想见,如果被请求的服务器支持被跨域请求,那么它一定会想办法在 response 中加上Access-Controll-Allow-Origin这个 header,并且附上合适的值。什么是合适的值呢?在 Request 的headers中会有一个 Origin,只要Access-Controll-Allow-Origin包含这个 Origin 就可以了(如果是 wildcard *,那么就等于包含所有的 Origin)。

Preflighted Requests 如何跨域请求
进行跨域的请求只会被分为两类,第一类就是 Simple Requests,其他的都是 Preflighted Requests。所以,只要一个请求,不满足上面一小节中对 simple requests 的要求,就是 preflighted requests 了。也就是说,一个请求只要满足下面几个条件中的任意一个就可以被划归此类了:

不是 GET,HEAD,POST 请求;比如是 PUT 请求
包含一些非 CORS 协议默许的 headers,比如Authorization,X-Request-With 或者一些自定义的headers。
Content-Type 不是默许的那 3 种
在 js 代码中使用了特定的方法,可参见文档
看完了 preflighted requests 的入选条件,我们再来从字面和行为上理解一下这种跨域请求。preflight 的中文意思是起飞前的,而 preflighted 的意译可能是:被在起飞前搞了一番的(有点蹩脚,哈哈)。这种跨域请求的实际行为也确实包含 preflight (起飞前)的部分:在一个请求被发出之前,浏览器会先发一个 OPTIONS 请求到目标“域”的服务器上,这个提前发出的请求,被称为 preflight request。

讲完了 preflight request 这个最重要的概念,我们可以比较方便的梳理这种跨域请求的流程:

浏览器发送 preflight request(那个 OPTIONS 请求[2])
浏览器收到 preflight response(也就是刚刚那个 request 的返回)
浏览器根据 preflight response 中的 Access-Control-Allow-Origin, Access-Control-Allow-Headers以及其他Access-Control-*类的headers 中的 value 来判断网页程序真正要发出的 request 是否符合要求
如果这个 request 符合要求,request 被发出,网页程序可以收到正常的 response(如果不出网络通讯上的意外);如果这个 request 被判定为不符合要求,这个 request 干脆就不会被发出。

三、后记

一般的跨域请求有多种方式来解决,可以服务器设置跨域请求;可以使用代理的方式,等等。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 当使用HTTPS进行跨域请求时,浏览器会先发送一个OPTIONS请求,以确认服务器是否允许跨域请求。这个OPTIONS请求包含了一些请求头信息,例如Origin、Access-Control-Request-Method、Access-Control-Request-Headers等。服务器需要根据这些请求头信息,返回一个响应头信息,例如Access-Control-Allow-Origin、Access-Control-Allow-Methods、Access-Control-Allow-Headers等。只有当服务器返回的响应头信息包含了Access-Control-Allow-Origin,且值为请求头的Origin时,浏览器才会发送真正的跨域请求。 ### 回答2: 在进行跨域请求时,浏览器会先发送一个OPTIONS请求,以确认对方服务器是否支持跨域请求,并确定哪些请求方式和头部信息可以被允许。这种请求被称为“预检请求(Preflight Request)”。 OPTIONS请求的HTTP方法是一种请求方式,它类似于GET、POST、PUT、DELETE等常见的HTTP请求方法,但它的目的不是获取资源,而是对服务器发起一个探测性请求,以获取服务器对跨域请求的支持情况,从而安全地执行跨域请求。 OPTIONS请求一般包含如下信息: 1.请求方式:OPTIONS 2.请求头部信息:包括请求的URL、协议版本、请求的Host、Origin(指请求方的域名或IP地址)、Access-Control-Request-Method、Access-Control-Request-Headers(指发送请求时携带的自定义头部信息),这些数据将告诉对方服务器,请求方的支持是否满足对方服务器的要求。 3.响应头部信息:对方服务器从请求头部信息获取到了想要的信息之后,会回复一个响应头部信息,包括允许 CORS 的 Origin、支持的HTTP请求方法、支持的头部信息等等。 在进行跨域请求时,浏览器会先发送一个OPTIONS请求,以确认对方服务器是否支持跨域请求,并确定哪些请求方式和头部信息可以被允许。这种请求被称为“预检请求(Preflight Request)”。 对于接收到OPTIONS请求的服务器,如果它允许跨域请求,就会在响应头加入Access-Control-Allow-Origin、Access-Control-Allow-Methods等字段来告诉浏览器可以进行跨域请求。如果不允许跨域请求,则响应头不会包含这些字段。 ### 回答3: 在进行跨域请求时,浏览器会先发送一个options请求来询问服务器是否允许跨域请求,并携带自身的请求方法、请求头、请求域等信息。这样可以避免在真正发送请求时发生意外的错误。 Options请求通过http请求的"Access-Control-Request-Method"和"Access-Control-Request-Headers"字段,告知服务器客户端想要采用的请求方式和请求头。如果服务器允许客户端使用这些方式,它会在返回的响应头添加"Access-Control-Allow-Methods"和"Access-Control-Allow-Headers"字段,指明允许的请求方式和请求头,同时也可以指定允许跨域请求的域名。 此外,还可以通过"Access-Control-Max-Age"字段指定响应信息在客户端浏览器本地缓存的时间,减少重复的Options请求。 如果服务器不允许客户端进行跨域请求,响应头会包含"Access-Control-Allow-Origin"字段并设置为"*",表示拒绝所有跨域请求。这时,浏览器会收到一个403 Forbidden错误。 需要注意的是,在进行跨域请求时,请求前端也需要在请求头添加Origin字段,告知服务器此请求的源地址。这样服务器才能知道这个请求是否来自允许跨域请求的源,并进行相应的处理。如果没有这个字段,服务器会认为这是两个不同的域名之间的普通请求,导致跨域请求失败。 因此,了解Options请求的原理和具体操作可以帮助我们在进行跨域请求时更加顺利地处理跨域问题,提高开发效率和用户体验。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值