• 跨域实例和解决方案


    跨域实例和解决方案

    以下我们用 nodejs 演示了一个 http 服务, 接口为 http://localhost:8000/ .如果正常连接成功, 则会返回文本 ok .

    然后以 js 在浏览器中进行 fetch 进行请求测试, 演示各种形式的跨域, 以及对应的解决方式, 所有代码都是可运行的实例.

    服务端代码, 默认没有跨域

    const http = require('http');
    const server = http.createServer((req, res) => {
      res.writeHead(200, {
        'x-age': '18',
      });
      res.end('ok');
    });
    server.listen(8000, () => console.log(`启动成功 http://localhost:8000`));
    

    客户端代码报错以及对应的设置方式

    /**
    简单请求
      await fetch('http://localhost:8000/api/test').then(res => res.text())
    报错
      Access to fetch at 'http://localhost:8000/api/test' from origin 'http://localhost:9005' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
    设置响应头
      'Access-Control-Allow-Origin': '*'
     */
    
    /**
    自定义请求头
      await fetch('http://localhost:8000/api/test ', {
        headers: { 'Content-Type': 'application/json' },
      }).then(res => res.text())
    错误
      Access to fetch at 'http://localhost:8000/api/test' from origin 'http://localhost:9005' has been blocked by CORS policy: Request header field content-type is not allowed by Access-Control-Allow-Headers in preflight response.
    设置响应头
      'Access-Control-Allow-Origin': '*',
      'Access-Control-Allow-Headers': '*',
     */
    
    /**
    自定义方法
      await fetch('http://localhost:8000/api/test ', {
        method: 'PATCH',
      }).then(res => res.text())
    错误
      Access to fetch at 'http://localhost:8000/api/test' from origin 'http://localhost:9005' has been blocked by CORS policy: Method PATCH is not allowed by Access-Control-Allow-Methods in preflight response.
    设置响应头
      'Access-Control-Allow-Origin': '*',
      'Access-Control-Allow-Methods': '*',
     */
    
    
    /**
    携带 cookie
      await fetch('http://localhost:8000/api/test', {
        credentials: 'include',
      }).then(res => res.text())
    报错
      Access to fetch at 'http://localhost:8000/api/test' from origin 'http://localhost:9005' has been blocked by CORS policy: The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'.
      Access to fetch at 'http://localhost:8000/api/test' from origin 'http://localhost:9005' has been blocked by CORS policy: The value of the 'Access-Control-Allow-Credentials' header in the response is '' which must be 'true' when the request's credentials mode is 'include'.
    设置响应头
      'Access-Control-Allow-Origin': 'http://localhost:9005',
      'Access-Control-Allow-Credentials': 'true',
     */
    
    
    /**
    设置自定义 header
      await fetch('http://localhost:8000/api/test', {
        headers: { 'x-age': '28' },
      }).then(res => res.text())
    报错
      Access to fetch at 'http://localhost:8000/api/test' from origin 'http://localhost:9005' has been blocked by CORS policy: Request header field x-age is not allowed by Access-Control-Allow-Headers in preflight response.
    设置响应头
      'Access-Control-Allow-Origin': '*',
      'Access-Control-Allow-Headers': '*',
     */
    
    
    /**
    读取自定义 header
      await fetch('http://localhost:8000/api/test').then(res => res.headers.get('x-age'))
    报错
      无, 但不能读取到 header 中的 x-age
    设置响应头, 表明允许获取的自定义头
      'Access-Control-Allow-Origin': '*',
      'Access-Control-Expose-Headers': 'x-age',
     */
    
    /**
    综合测试
      await fetch('http://localhost:8000/api/test', {
        method: 'PATCH',
        credentials: 'include',
        headers: { 'x-age': '28' },
        body: JSON.stringify({
          token: 'test_token',
          content: 'test_content'
        })
      }).then(async res => ({text: await res.text(), age: res.headers.get('x-age')}))
     */
    
    

    总结

    是否可以跨域, 是由服务器端决定的. 通常设置响应头即可, 在响应头中告诉浏览器允许跨域的域名, 以及允许跨域的方式, 还有允许读取和设置的请求头, 全都由服务端决定.

    一般我们有几种解决方案:

    • 关闭浏览器的安全策略
    • 安装浏览器插件
    • 直接从后端代码上设置为允许
    • 使用代理方式

    其中插件的方式和代理的方式其他都是在中途拦截并设置 header 为对应的跨域标致.

    在前端项目的开发环境中, 一般可以使用 webpack 的 proxy 功能, 或者可以使用 mockm 的 proxy 功能. 推荐 mockm, 因为它不仅可以代理, 并且不需要复杂的配置, 还能获取到请求的接口历史和数据.

  • 相关阅读:
    my.cnf 配置文档
    win11 默认 右击 老菜单
    慎重修改 profile 文件
    响应延迟数据集 p90/p99 是什么
    Windows 修改 注册表 鼠标右键 菜单 使用**打开
    windows 系统 开启 mysql binlog 变更数据后 根据日志 寻找变更前的数据
    Mysql 的 read_only 只读属性 权限分配 动态权限
    utf8 和 utf8mb4 的区别
    MySQL 数据库 隔离 的 四个级别 和 事务 的 四个特性
    26. 删除有序数组中的重复项
  • 原文地址:https://www.cnblogs.com/daysme/p/14698118.html
Copyright © 2020-2023  润新知