2022年5月28日
By: Chase

本地转发解决前端跨域

前言

在开发过程中, 遇到非自己人开发的后端接口, 时不时遇到跨域问题. 我们本着能动手不逼逼的原则, 自己本地启个服务转发一下, 绕开报跨域的浏览器大爷即可.

本文涉及安装依赖: node, yarn(npm也行), Nginx

本文以本地3000端口请求百度为例, 在我的react demo页面请求一下百度

import React from 'react'

function App() {
  
  const handleTestRequest = async () => {
    try {
    	const res = await fetch('https://www.baidu.com')
		console.log(res)
    } catch (error) {
		console.log('fetch error', error)
    }
  }

  return (
    <div className="App">
      <button onClick={handleTestRequest}>fetch</button>
    </div>
  );
}

export default App;

结果, 毫无意外的报跨域错误.

image.png

解决方案:

image.png

独立的http-proxy-middleware来解决

它是一个npm库, 之前Marvin的Vue项目里见过面了, 可以很方便的帮助我们做请求转发, 先简单的非集成式的实现一下.

根据官方文档抄一下作业https://www.npmjs.com/package/http-proxy-middleware

  1. 安装expresshttp-proxy-middleware
 yarn add express http-proxy-middleware
  1. 新建一个index.js
const express = require('express');
const { createProxyMiddleware } = require('http-proxy-middleware');

const app = express();
app.use(
    '/api',
    createProxyMiddleware({ 
        target: 'https://www.baidu.com/', // 需要跨域处理的请求地址
        changeOrigin: true,
        pathRewrite: { // 请求中去除/api
            "^/api": ""
        },
        onProxyReq: function onProxyReq(proxyReq, req, res) {
 // 我就打个log康康
            console.log('-->  ', req.method, req.baseUrl, '->', proxyReq.host + proxyReq.path);
        }
    })
)

app.listen(3001);
  1. 命令行启动一下
node index.js

这下我们已经有了一个本地3001端口的转发服务小帮手了, 所有发向http://localhost:3001/api的请求, 小助手都会帮我处理一下后转发给百度.

  1. 代码改动试一下
fetch('http://localhost:3001/api')
  1. 不用上截图我就告诉你还是失败 因为http://localhost:3000http://localhost:3001的请求依然属于跨域, 他们还不是好朋友. 跨域的判定: 协议 + 域 + 端口 文档: https://developer.mozilla.org/zh-CN/docs/Glossary/Origin

下面让我们的3001小助手认可3000, 在们的index.js文件中, 添加onProxyRes等代码.

  ......
        onProxyReq: function onProxyReq(proxyReq, req, res) {
            console.log('-->  ', req.method, req.baseUrl, '->', proxyReq.host + proxyReq.path);
        },
        onProxyRes: function onProxyReq(proxyRes, req, res) {
            proxyRes.headers["Access-Control-Allow-Origin"] = "*"; // 或者直接写"http://localhost:3000"成为唯一好友
        } 
  ......
  1. 再请求试试. 肯定成功了, 自信回头不上图了

http-proxy-middleware 集成到 create-react-app

create-react-appreact-scripts@0.2.3之后对http-proxy-middleware自带很好的集成 参考文档: https://create-react-app.dev/docs/proxying-api-requests-in-development 按照他的方式, 他会在我们启动的服务上(如我的localhost:3000端口)直接集成转发, 省去我们手动启3001, 以及让它和3000成为好朋友的一步.

  1. 安装
yarn add http-proxy-middleware
  1. 在项目根目录src下新建setupProx.js文件 tips: 修改调试setupProxy.js文件需要重启服务
const { createProxyMiddleware } = require('http-proxy-middleware');

module.exports = function(app) {
  	app.use(
		'/api',
		createProxyMiddleware({
			target: 'https://www.baidu.com',
			changeOrigin: true,
			pathRewrite: { // 请求中去除/api
				"^/api": ""
			},
			onProxyReq: function onProxyReq(proxyReq, req, res) {
				console.log('-->  ', req.method, req.baseUrl, '->', proxyReq.host + proxyReq.path);
			},
		})
  	);
};
  1. 请求里尝试一下
    try {
    	const res = await fetch('http://localhost:3000/api')
      	console.log(res)
    } catch (error) {
	    console.log('fetch error', error)
    }
  }
  1. 肯定成功了, 自信回头.

Nginx转发

  1. nginx各个平台的安装过程自己百度, 略

  2. 安装完了nginx -t一下, 查看一下nginx的配置文件位置, 直接去修改nginx.conf, 修改代码如下:

server {
        listen       3001; 
        server_name  localhost;
  
        location / {
            add_header Access-Control-Allow-Origin "*";
            proxy_pass https://www.baidu.com;
        }
    }

启一个3001的服务, 负责转发, 同时也别忘了我们之前3000 -> 3001报跨域错误的问题, 记得添加一个header.

  1. 改完修改, nginx -s reload重启一下, 收工.
Tags: 前端 跨域