跨域请求 fetch 实现

本文详细介绍了CORS的两种分类:简单的请求和带有preflight预请求的CORS,强调了带有preflight的CORS会先发送OPTIONS请求以获取服务器的许可。对于带有身份凭证的CORS请求,通常xhr需要设置,fetch则需在request中设置。要注意,如果服务器在预请求时不返回相应头,cookie将不会随实际请求发送。同时,对于简单的GET请求,如果没有预请求,服务器未返回相应头,响应也不会交给请求者。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

reference : [1].https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Access_control_CORS

1.CORS 的分类

分为两大类:简单的请求;带有preflight预请求的CORS。两类请求的区分标准如下:

简单请求

某些请求不会触发 CORS 预检请求。本文称这样的请求为“简单请求”。若请求满足所有下述条件,则该请求可视为“简单请求”:

 1. 使用下列方法之一: GET HEAD POST 
 2. Fetch 规范定义了对 CORS 安全的首部字段集合,不得人为设置该集合之外的其他首部字段。该集合为: Accept Accept-Language Content-Language Content-Type (需要注意额外的限制) DPR Downlink Save-Data Viewport-Width Width  
 3. Content-Type 的值属于下列之一: application/x-www-form-urlencoded multipart/form-data text/plain

剩下的都是,带有preflight的CORS。带有preflight的CORS ,浏览器会先发出一个 OPTIONS请求,服务器在响应里写入是否允许该域名发起访问,在response的header里面加入了Access-Control-Allow-Origin,Access-Contral-Allow-Methods,Access-Contraol-Allow-Headers,Access-Control-Max-Age,这几个字段(各个字段详细意义参见reference 1),
这里写图片描述

2.进行带有身份凭证的CORS 请求

默认情况下的跨域请求都是不会把cookie发送给服务器的,在需要发送的情况下,如果是xhr,那么需要设置xhr.withCredentials = true,如果是采用fetch获取的话,那么需要在request里面设置 credentials:'include', 但是如果服务器在预请求的时候没返回Access-Control-Allow-Crenditials:true的话,那么在实际请求的时候,cookie是不会被发送给服务器端的,要特别注意对于简单的get请求,不会有预请求的过程,那么在实际请求的时候,如果服务器没有返回Access-Control-Allow-Crenditials:true的话 那么响应结果浏览器也不会交给请求者

3.fetch的配置

import {
  baseUrl
} from '../../config/env.config.js'
import {formDataToJson} from '../../utils/form.js';
import * as es6Promise from 'es6-promise'
import 'isomorphic-fetch'

es6Promise.polyfill();

export default async(type = 'GET', url = '', data = {}) => {

  type = type.toUpperCase();
  url = baseUrl + url;

  if (type == 'GET') {
    let dataStr = ''; //数据拼接字符串
    Object.keys(data).forEach(key => {
      dataStr += key + '=' + data[key] + '&';
    })

    if (dataStr !== '') {
      dataStr = dataStr.substr(0, dataStr.lastIndexOf('&'));
      url = url + '?' + dataStr;
    }
  }
  if (type == 'DELETE') {
    url = url + "/" + data.id;
  }

  let requestConfig = {
    credentials: 'include',
    method: type,
    headers: {
      'Accept': 'application/json',
      'Content-Type' : 'application/json'
    },
    mode: "cors",
    cache: "force-cache"
  }

  if (type == 'POST') {
    if (window.FormData && data instanceof FormData) {
      Object.defineProperty(requestConfig, 'body', {
        value: formDataToJson(data)
      })
    } else {
      Object.defineProperty(requestConfig, 'body', {
        value: JSON.stringify(data)
      })
    }

  }

  try {
    var response = await fetch(url, requestConfig);
    var responseJson = await response.json();
  } catch (error) {
    throw new Error(error)
  }
  return responseJson

}
### Fetch 请求的相关问题及解决方案 当使用 `fetch` 处理请求时,CORS源资源共享)配置是非常重要的一步。如果没有正确配置 CORS,可能会导致浏览器阻止请求完成。以下是几种常见的解决方法及其具体实现。 #### 后端配置 CORS 最安全和推荐的做法是在后端启用 CORS 支持。这通常涉及设置 HTTP 响应头以允许特定的名访问资源。例如,在 Express.js 中可以这样配置[^2]: ```javascript app.all('*', function(req, res, next) { res.header("Access-Control-Allow-Origin", "*"); res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept"); res.header("Access-Control-Allow-Methods", "PUT,POST,GET,DELETE,OPTIONS"); res.header("Content-Type", "application/json;charset=utf-8"); next(); }); ``` 以上代码片段设置了通用的权限,适用于大多数场景下的开发需求。注意 `"*"` 表示允许任何来源访问,但在生产环境中建议替换为具体的白名单地址列表以提高安全性。 #### 使用 Vue CLI 的代理功能 在前端框架如 Vue.js 中,也可以通过配置代理的方式来规避限制。这种方法特别适合于本地调试阶段。可以在项目的 `vue.config.js` 文件里添加如下内容[^1]: ```javascript module.exports = { devServer: { proxy: { '/api': { target: 'http://localhost:5000', // 替换为目标服务器的实际URL changeOrigin: true, pathRewrite: { '^/api': '' } } } } }; ``` 这里 `/api` 是一个路径前缀,所有的匹配到这个前缀的请求都会被转发给目标服务器,并且会修改原始请求中的 Host 字段使之看起来像是直接向目标服务器发出的一样。 #### 客户端 fetch 设置 withCredentials 属性 有时候即使已经完成了基本的 CORS 配置,仍然可能出现身份验证失败的情况。这是因为默认情况下 cookies 或者其他认证信息不会随同请求一起发送出去。此时需要显式开启 credentials option: ```javascript fetch('https://other-domain.com/api/resource', { method: 'GET', credentials: 'include' // or 'same-origin' }) .then(response => response.json()) .catch(error => console.error('Error:', error)); ``` 这里的 `credentials: 'include'` 参数告诉浏览器应该连同请求一同提交 cookie 数据等敏感资料[^3]。 --- ### 总结 综上所述,针对 fetch 请求的问题可以从以下几个方面入手解决:一是确保后端已适当开放了必要的 CORS 权限;二是在前端利用构建工具提供的代理机制绕过浏览器的安全策略约束;三是必要时候调整客户端 fetch 请求的行为使其能够携带所需的身份凭证信息。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值