[轉載]React跨域新版解決方案(v16.9)

https://zhuanlan.zhihu.com/p/96735100

 

React跨域

解決方案在二,想簡單瞭解下跨域的可讀一。

我們由於項目需要經常會需要對不同域名、不同子域的網站接口發起請求,有時甚至是對於同一域名的不同端口發起請求,此時我們經常看到以下報錯:

Access to XMLHttpRequest at 'xxx' from origin 'xxx' has been blocked by CORS 
policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

是的,錯誤的原因就是你跨域了。剛碰到跨域問題時在網上尋找了大半天,不是報錯就是無法跨域轉發。最後才發現是react新版本更新了相關規則的緣故。記述下來供大家參考。

一、爲什麼會有跨域問題?

看到網上舉的一個形象例子,先設想下,如果允許跨域,那麼黑衣人是不是可以在自己的網頁上把請求轉發給其他網站?例如,黑衣人在自己的頁面設計了一個跨域請求到某錢堆的網址,當用戶訪問黑衣人網址時,瀏覽器按照黑衣人設計去訪問了錢堆(還攜帶了用戶在錢堆那兒的cookie)......之後,之後警察叔叔們又要加班了。還有諸如此類許多安全隱患。所以後來的瀏覽器都開始實行同源策略。

同源策略,其實就是隻允許相同協議+域名+端口號(如存在)的HTTP請求互相訪問。這麼理解其實就夠了。關於跨域資源共享標準( cross-origin sharing standard )CORS的詳細內容,大家可參考這篇文章:鏈接

本文主要講React框架下怎麼解決跨域問題。

二、怎麼解決跨域問題?

這裏我給出兩種React的跨域解決方案(React16.9親測可行),第一種比較實用,第二種需要服務端協調。

1.http-proxy-middleware

網上一大片說直接在package.json中配置proxy的,這個方法已經失效很久了。官方給出的新版本解決方案需要藉助http-proxy-middleware這個包:


1. npm install http-proxy-middleware
2. src目錄下創建setupProxy.js,配置如下:

const proxy = require('http-proxy-middleware')

module.exports = function (app) {
    // proxy第一個參數爲要代理的路由
    // 第二參數中target爲代理後的請求網址,changeOrigin是否改變請求頭,其他參數請看官網
    app.use(proxy('/cityjson', {
        target: 'http://pv.sohu.com',
        changeOrigin: true
    }))
}

3. 測試一下:

   //頁面代碼:
   import React,{ useEffect,useState } from 'react'
   import axios from 'axios';
   
   const App = function () {
       const [ip,setIp] = useState()
   
       useEffect(()=>{
           (async function f(){
               let res = await axios.get('/cityjson') //這裏使用搜狐的ip信息查詢接口
               setIp(res.data.toString())
           })()
       },[])
   
       return (
           <h1>獲取的IP信息:{ip}</h1>
       )
   }
   
   export default App


成功獲取!

2.藉助服務端配置

其實有過服務端開發經驗的同學應該一眼就能看出,上面配置setupProxy.js的樣子像極了node服務端使用中間件的樣子。再看看,http-proxy-middleware,middleware就是中間件的意思。

好了,大概知道了,其實新版本的更新就是想把跨域請求放在服務端去做,而削弱前端跨域的能力(大概是爲了安全吧,個人臆想)

在服務端配置的話,只需要在服務端中間件文件裏插入http-proxy-middleware即可。express框架和上面的配置基本一樣,koa的話參考以下這樣:

const Koa = require('koa')
const proxy = require('http-proxy-middleware')

const app = new Koa()

//跨域代理
app.use(async (ctx, next) => {
    if(ctx.url.startsWith('/cityjson')) {
        ctx.respond = false
        return proxy({
            target: 'http://pv.sohu.com', // 服務器地址
            changeOrigin: true,
        })(ctx.req, ctx.res, next)
    }
    return next()
})
......
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章