Charles 在模拟 POST 接口时的预请求处理

439 阅读9分钟

省流:
你可以查看接口服务器返回的响应头部(Response headers)信息,当请求正确地配置了 CORS 头部,特别是 Access-Control-Allow-OriginAccess-Control-Allow-MethodsAccess-Control-Allow-Headers 等 CORS 头部,说明接口服务器允许跨域请求,那么跨域请求可能不会触发预请求。

故事的开始,是想要 mock 一下接口的成功状态,打开 Charles,发起请求,发现有这么两条

image.png

image.png

image.png

其中实际请求的 res 是

{
	"code": 501010003,
	"info": "不可操作已被处理或已失效的申请"
}
  • 提问 1:OPTIONS 请求是什么?

    OPTIONS请求旨在发送一种“探测”请求以确定针对某个目标地址的请求必须具有怎样的约束(比如应该采用怎样的HTTP方法以及自定义的请求报头),然后根据其约束发送真正的请求。比如针对“跨域资源”的预检(Preflight)请求采用的HTTP方法就是OPTIONS。

    简而言之,OPTIONS请求方法的主要用途有两个:
    1、获取服务器支持的HTTP请求方法;
    2、用来检查服务器的性能。

    在浏览器中进行跨域请求时,浏览器会发送预检请求(preflight request)来确定是否可以安全地发送实际的请求。预检请求使用 OPTIONS 方法发送,并包含一些用于检查跨域请求是否安全的头部信息,例如请求中的方法(POST、GET等)、自定义头部信息等。

因为很少见,于是我忽略了这个 OPTIONS 请求。

  • 提问 2:为什么 GET 请求没有 OPTIONS,而 POST 请求有?

    POST 请求通常比 GET 请求更有可能包含自定义头部信息或者发送一些敏感数据,因此浏览器更倾向于发送预检请求以确保安全。而 GET 请求一般不会包含这些可能引起安全问题的信息,因此通常不需要发送预检请求。

    1. 200 OK:表示服务器收到了请求,并且返回了正常的响应。这通常用于指示服务器支持的方法。
    2. 204 No Content:表示服务器收到了请求,但是没有额外的内容返回。这通常用于指示服务器支持的方法,并且没有其他相关信息需要返回给客户端。

按照平常 GET 的请求的 mock 方式,先 save response,然后修改,再 map Local 选择修改后的文件。同时需要 rewrite Response headers,可以使用浏览器插件,也可以直接用 Charles 的 rewrite 添加如下内容,解决跨域问题。

Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: {发起请求的网站域名}

问题来了,Map Local 换掉第二条响应之后,原本的 POST 变成了 OPTIONS,原本的 OPTIONS 消失了。

image.png

浏览器中的表现就是并没有获取到响应,且 response headers 集体失踪了

image.png

  • 提问 3:为什么 OPTIONS 之后的 POST 请求消失了?

    这应该是预请求失败导致的实际请求被拒绝。如果预请求(OPTIONS 请求)失败,可能会导致以下问题:

    1. 实际请求被拒绝:预请求失败可能意味着服务器不允许跨域请求,或者实际请求所需的条件不满足。这将导致实际请求被浏览器拒绝,从而导致请求失败。
    2. 安全性问题:预请求的目的是确定跨域请求的安全性,如果预请求失败,浏览器可能会认为跨域请求是不安全的,并拒绝执行实际请求,从而保护用户的安全。
    3. 跨域资源访问限制:预请求失败可能意味着服务器未正确配置跨域资源共享(CORS),或者没有正确响应预请求。这可能导致浏览器不允许跨域请求,从而限制了对跨域资源的访问。
    4. 跨域请求失败:如果预请求失败,实际请求可能会因为跨域限制而被浏览器拦截,导致请求失败。这可能会影响应用程序的功能和性能。

    因此,预请求的失败可能会导致跨域请求无法正常执行,从而影响到应用程序的正常运行。为了避免这种情况,服务器需要正确配置 CORS,并且确保预请求能够成功执行。

但我注意到一点,在 www.uat.missevan.com/ 网站中访问 fm.uat.missevan.com 域名的接口并没有发起预请求,而且本地 localhost 服务的预请求提示跨域了。

  • 提问 4:预请求就是跨域请求吗

    预请求(Preflight Request)是跨域请求的一种形式,但并不等同于跨域请求。跨域请求是指在同一页面中的脚本尝试访问另一个域的资源时发生的请求。而预请求是一种特殊的 OPTIONS 请求,用于在发送实际的跨域请求之前,向服务器询问关于跨域请求的权限信息。

    在跨域请求中,如果实际请求符合一定的条件(例如是简单请求,或者已被服务器允许跨域),浏览器会直接发送实际的请求,而不会触发预请求。而当实际请求不符合这些条件时,浏览器会先发送一个预请求,询问服务器是否允许发送实际请求。

    因此,预请求是跨域请求的一种情况,但并不是所有的跨域请求都会触发预请求。

  • 提问 5:是因为接口允许 www.uat.missevan.com/ 跨域请求吗?

    A:实际上,跨域请求是否触发预请求取决于浏览器的同源策略和CORS(跨源资源共享)设置。如果接口服务器允许来自 www.uat.missevan.com/ 的跨域请求,并且正确地配置了 CORS 头部,那么预请求可能不会发生。

    CORS 通过在响应头中包含特定的 CORS 头部信息来控制跨域请求的行为。如果接口服务器的响应中包含了允许来自 www.uat.missevan.com/ 的跨域请求的 CORS 头部信息,浏览器就会认为跨域请求是安全的,不需要发送预请求。这种情况下,浏览器会直接发送实际的请求。

    要检查接口服务器是否允许跨域请求,并且正确地配置了 CORS 头部,你可以查看接口服务器返回的响应头部信息,特别是 Access-Control-Allow-OriginAccess-Control-Allow-MethodsAccess-Control-Allow-Headers 等 CORS 头部。如果这些头部中包含了适当的设置,那么跨域请求可能不会触发预请求。

  • 提问 6:接口返回的哪些内容说明允许跨域

    当接口服务器返回特定的 CORS(跨源资源共享)头部信息时,说明该接口允许跨域请求。以下是一些常见的 CORS 头部信息,它们可以告知浏览器哪些跨域请求是被允许的:

    1. Access-Control-Allow-Origin:指定允许访问该资源的域名。如果设置为 `` ,表示允许任意域名访问。
    2. Access-Control-Allow-Methods:指定允许的 HTTP 方法,如 GET、POST、PUT、DELETE 等。
    3. Access-Control-Allow-Headers:指定允许的自定义请求头部信息,如 Authorization、Content-Type 等。
    4. Access-Control-Allow-Credentials:指示是否允许包含凭据(例如 cookies、HTTP 认证信息)的请求。如果设置为 true,则允许。
    5. Access-Control-Expose-Headers:指定允许浏览器访问的响应头部信息。

    通常情况下,服务器在响应中包含上述头部信息中的一部分或全部,就表示允许跨域请求。这些头部信息告诉浏览器请求该资源的页面具有跨域权限,浏览器在接收到这些信息后,就会执行跨域请求并且不会触发预请求(OPTIONS 请求)。

  • 提问 7:预请求的触发条件

    预请求(Preflight Request)是跨域请求中的一种机制,用于在发送实际请求之前,向服务器发送一个 OPTIONS 请求,以确定是否可以安全地发送实际请求。预请求的触发条件通常有以下几种情况:

    1. 使用了非简单请求:如果实际请求是非简单请求,浏览器会先发送预请求。非简单请求包括使用了自定义头部、或者请求方法不是 GET、HEAD 或 POST。
    2. 使用了某些特殊头部信息:如果在实际请求中使用了某些浏览器认为可能引起安全问题的头部信息(例如 AuthorizationContent-Type),也会触发预请求。
    3. 跨域请求:如果实际请求跨域了(即请求的目标服务器和当前页面所在的服务器不同源),浏览器通常会先发送预请求。
    4. 使用了某些不常见的方法:尽管大多数情况下 OPTIONS 请求是为了检查跨域请求的安全性,但有时候某些不常见的方法(如 DELETE、PUT 等)也可能触发预请求。

    预请求是由浏览器自动发起的,因此触发条件的具体细节可能会因浏览器而异。通常来说,只要涉及到跨域请求或者使用了非简单请求,就有可能触发预请求。

于是为请求添加了 Access-Control-Allow-Methods 和 Access-Control-Allow-Headers 就好了!!

  • 最后一个提问 8:预请求的 response 和一般请求的 response 有什么不同

    预请求(OPTIONS 请求)的响应和普通请求的响应在很多方面都是相似的,但也有一些重要的区别。以下是它们之间的主要不同点:

    1. 状态码
      • 预请求的响应通常会返回 200 OK 状态码,表示服务器已经接收到预请求并且能够处理它。
      • 普通请求的响应则根据实际情况返回不同的状态码,如 200 OK、404 Not Found、500 Internal Server Error 等。
    2. 响应体
      • 预请求的响应体通常为空,因为预请求主要是用于询问服务器关于跨域请求的权限信息,一般不包含实际的响应数据。
      • 普通请求的响应体则包含了请求的实际响应数据。
    3. CORS 头部信息
      • 预请求的响应中可能包含 CORS 头部信息,如 Access-Control-Allow-Origin、Access-Control-Allow-Methods、Access-Control-Allow-Headers 等,用于指示服务器允许的跨域请求信息。
      • 普通请求的响应中也可以包含 CORS 头部信息,但这取决于服务器是否支持跨域请求。
    4. 缓存
      • 由于预请求通常只是用于确定跨域请求的安全性,不包含实际的响应数据,因此一般不会被浏览器缓存。
      • 普通请求的响应数据可能会被浏览器缓存,具体取决于响应头部的缓存控制策略。

    总的来说,预请求和普通请求的响应在内容和用途上有一些差异,但它们都是 HTTP 响应,遵循相同的协议规范。