返回

浅析CORS跨域中一次动作两次请求的背后原理

前端

在当今互联网应用飞速发展的时代,前后端分离已成为一种主流的架构模式。然而,跨域问题也随之而来,阻碍着前后端之间的顺畅通信。为了解决这一难题,CORS(Cross-Origin Resource Sharing)应运而生,它为我们提供了安全、灵活的跨域访问机制。本文将深入浅出地剖析CORS跨域机制,探究为何在一次动作中会出现两次请求,并提供清晰示例,帮助您轻松掌握CORS跨域的精髓。

CORS简介

CORS(Cross-Origin Resource Sharing)跨域资源共享是一种浏览器端和服务器端共同协作的机制,它允许不同源的Web应用之间进行资源共享。CORS的本质是通过允许或拒绝来自不同源的HTTP请求,从而防止跨域请求对数据和资源的非法访问。

CORS的工作原理是,浏览器首先会向服务器发送一个预检请求(Preflight Request)来询问服务器是否允许跨域请求。如果服务器返回允许跨域请求的响应,浏览器才会发送实际的请求。预检请求和实际请求之间存在着一些关键的区别:

  • 预检请求使用OPTIONS方法,而实际请求使用GET、POST等常规方法。
  • 预检请求只包含一些基本的信息,如请求方法、请求头等,而实际请求包含更多的数据。
  • 预检请求不会携带任何数据,而实际请求可能携带数据。

为何会出现一次动作两次请求

在CORS跨域中,一次动作之所以会出现两次请求,是因为浏览器在发送实际请求之前,会先发送一个预检请求。预检请求的作用是询问服务器是否允许跨域请求,服务器会根据预检请求中的信息来决定是否允许跨域请求。如果服务器允许跨域请求,浏览器才会发送实际的请求。

预检请求和实际请求之间的主要区别在于,预检请求使用OPTIONS方法,而实际请求使用GET、POST等常规方法。此外,预检请求只包含一些基本的信息,如请求方法、请求头等,而实际请求包含更多的数据。

简单请求和复杂请求

在CORS跨域中,请求分为简单请求和复杂请求两种类型。简单请求是指满足以下所有条件的请求:

  • 请求方法为GET、HEAD、POST。
  • 请求头只有以下几个字段:Accept、Accept-Language、Content-Language、Content-Type(只限于application/x-www-form-urlencoded、multipart/form-data、text/plain)。
  • 不使用自定义的HTTP头。
  • 没有请求体。

复杂请求是指不满足简单请求条件的请求,即请求方法不是GET、HEAD、POST,或者请求头包含了自定义的HTTP头,或者请求体存在数据。

CORS跨域示例

为了更好地理解CORS跨域,我们来看一个具体的示例。假设我们有一个前端应用,运行在域名www.example.com下,而我们的后端API运行在域名api.example.com下。当前端应用向后端API发送请求时,就会发生跨域。

为了解决跨域问题,我们可以通过在后端API中设置Access-Control-Allow-Origin响应头来允许跨域请求。例如,我们可以设置如下响应头:

Access-Control-Allow-Origin: *

这样,前端应用就可以向后端API发送跨域请求了。但是,由于这是一个简单的请求,浏览器不会发送预检请求。

如果我们想发送一个复杂的请求,比如使用PUT方法向后端API发送数据,那么浏览器就会发送一个预检请求。预检请求的请求方法是OPTIONS,请求头包含了Access-Control-Request-Method和Access-Control-Request-Headers字段,分别指定了实际请求的方法和请求头。

服务器端收到预检请求后,会根据预检请求中的信息来决定是否允许跨域请求。如果服务器允许跨域请求,则会返回一个200 OK响应,并设置Access-Control-Allow-Origin响应头来允许跨域请求。

浏览器收到服务器端的响应后,就会发送实际的请求。实际请求的方法是PUT,请求头包含了Access-Control-Request-Method和Access-Control-Request-Headers字段,分别指定了实际请求的方法和请求头。请求体中包含了需要发送的数据。

结语

CORS跨域是一种安全、灵活的跨域访问机制,它允许不同源的Web应用之间进行资源共享。在CORS跨域中,一次动作之所以会出现两次请求,是因为浏览器在发送实际请求之前,会先发送一个预检请求。预检请求的作用是询问服务器是否允许跨域请求,服务器会根据预检请求中的信息来决定是否允许跨域请求。如果服务器允许跨域请求,浏览器才会发送实际的请求。