React axios 使用 http-proxy-middleware 解決跨域問題小記


壹 ❀ 引

在上篇bug分析的記錄文中,提到axios可做到取消接口請求,所以想寫一篇關於axios.CancelToken使用以及原理分析的文章(主要是自己好奇到底如何做到的取消)。在准備工作階段,我需要在本地寫一個發起請求的demo並模擬取消,這樣才便於例子分析和理解。但在本地react demo運行的過程中遇到了跨域問題,解決跨域的過程中,也被一些錯誤的文章所誤導,占用了一些時間,因此此篇文章主要詳細記錄react使用axios如何解決跨域問題(其實跟axios也沒啥關系),那么本文開始。

貳 ❀ 開始准備

我的react demo是基於Create React App,這里就不提怎么安裝了,具體可參考官方文檔或者從零開始的react入門教程(一),讓我們從hello world開始一文。於是乎我在終端執行了npm install axios安裝 axios

由於我們需要請求一個接口,方便后續的請求展示,我順手在百度輸入了接口測試,於是找到了getman,點擊了確認了按鈕,打開控制台發現發起了一個請求https://getman.cn/api/request,那么我們也來請求這個地址好了。

於是我在index.js中定義了一個簡單的組件,代碼如下:

import React, {
  Component
} from 'react';
import ReactDOM from 'react-dom';
import axios from 'axios';

class Parent extends Component {
  componentDidMount() {
    // 我們也來獲取這個地址
    axios.get('https://getman.cn/api/request')
      .then((res) => {
        console.log(res)
      })
      .catch((err) => {
        console.log(err)
      })
  }
  render() {
    return (
      <div>你好,echo。</div>
    );
  }
}

ReactDOM.render(
  <Parent />,
  document.getElementById('root')
);

npm start運行項目發現報錯,看錯誤信息就知道是跨域了,畢竟我們本地協議以及端口http://localhost:3001/都跟需要請求的地址完全不同。那么就開始着手解決跨域吧,網上也有一些方案,折騰了一番,這里我們使用代理來解決。

叄 ❀ http-proxy-middleware解決跨域

我們需要額外下載一個三方包http-proxy-middleware,在編輯器終端直接執行npm install http-proxy-middleware --save進行安裝。安裝完畢后,在src目錄下新建文件setupProxy.js,具體配置如下:

const {createProxyMiddleware} = require('http-proxy-middleware');
module.exports = function(app) {
  app.use(createProxyMiddleware('/api', 
    {
        "target": "https://getman.cn",
        "changeOrigin": true,
    }))
}

注意,一定是const {createProxyMiddleware} = require('http-proxy-middleware')而不是const proxy = require('http-proxy-middleware'),很多人的博客都是用后面這句,如果這么那就是瘋狂報錯,完全沒效果....

然后回到我們的index.js,修改請求地址的那一句代碼為:

// 原代碼為
// axios.get('https://getman.cn/api/request')
// 修改為
axios.get('api/request')

保存,刷新頁面,你會發現跨域報錯已經不存在,而控制台也成功展示了我們請求拿回來的接口數據。

簡單解釋下這段配置,代理它到底幫我們做了什么。我們可以把本地跑起來的服務理解為用戶A,A發起請求,希望去自己所在的服務(我們當前運行的本地項目)的api/request路徑下找一個東西,很明顯我們項目中沒有這個路徑,所以常規來說請求http://localhost:3001/api/request一定報404

此時來了個代理商B,他跟我們本地服務A說,你把你要請求的地址告訴我,我幫你轉發,幫你訪問到你真正想要訪問的信息。而我們本地可以發起N種請求,哪些要代理哪些不要代理呢?因此A和B約定了,只要你的請求帶有/api,我就幫你轉發,轉發到哪呢?轉發到https://getman.cn

於是A請求了api/request,B發現這個地段里面有/api,於是就去https://getman.cn的目錄下找,找什么呢?找api/request,所以最終轉發的地址就是https://getman.cn + api/request,所以順利請求了https://getman.cn/api/request

createProxyMiddleware后的第一個字段,更像是一個約定,同時也是代理商去target尋找的第一級目錄,比如我們把代碼修改成如下:

// index.js修改為
axios.get('request')
// 配置修改為
module.exports = function(app) {
  app.use(createProxyMiddleware('/request', 
    {
        "target": "https://getman.cn/api",
        "changeOrigin": true,
    }))
}

上述修改中,前端請求request,其實也就是要到服務端request目錄下拿個東西,於是代理監聽到了,就去https://getman.cn/下找,那這樣肯定找不到,所以我們在target進行了手動補全,自己在默認加了/api,這樣就成了https://getman.cn/api + request,重新運行項目,你發現也成功請求了。

打開控制台查看我們請求的地址其實是http://localhost:3000/request,但事實上代理幫我們轉發,實際訪問的是另一個地址,大概如此了。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM