使用proxytable 配置解決 vue-cli 的跨域請求問題

本文適用人羣:javascript

  • 會使用 vue-cli 搭建一個基本的 vue webpack 項目,本文的目錄結構基於 webpack 模板結構
  • 懂得 axios 基本用法

問題導向前端

平常開發中,前端常常須要經過 ajax 從後端獲取數據。而在這種先後端分離的開發模式下,每每前端項目與後端項目的 IP地址、端口號、協議 大機率是不同的,因爲瀏覽器的安全策略設定,不進行相應配置的話,前端的請求就會被瀏覽器攔截掉啦。vue

假設某個頁面組件在加載的時候會向後端發送一個請求,而後根據返回的結果來渲染頁面。代碼示例以下:java

前端項目經過 npm run dev 運行在 localhost:8081 上,webpack

後端項目經過 apache 運行在 localhost/test/public/api/books ios

<template>
 <div class="hello">
 <ul>
  <li v-for="book of books">{{book.name}}</li>
 </ul>
 </div>
</template>
<script>
 import axios from 'axios';
 export default {
 name: 'HelloWorld',
 data() {
  return {
  books: []
  }
 },
 created(){
  let self = this;
  axios.get("http://localhost/test/public/api/books")
  .then((response)=>{
  self.books = response.data;
  });
 }
 }
</script>

直接訪問後端連接,將能獲得如下返回內容:git

[
 {"name":"javascript \u4ece\u5165\u95e8\u5230\u653e\u5f03"},
 {"name":"\u9888\u690e\u75c5\u5eb7\u590d\u6307\u5357"},
 {"name":"\u89c6\u529b\u4fdd\u62a4\u6307\u5357"}
]

可是當咱們在瀏覽器中運行前端頁面,會報錯!控制檯打印以下:github

可見,瀏覽器對於跨域訪問進行了限制,由於在例子中前端項目url與後端項目url的端口號不相同,因此瀏覽器攔截了咱們的請求。web

解決方案ajax

解決方式有不少種,包括能夠很簡單粗暴地讓後端代碼設置一個 Access-Control-Allow-Origin 頭來解決這個問題。可是,在實際開發中,後端的小哥哥們纔不會理會你這個羞恥的小請求呢~

那怎麼辦咧~

其實咱們能夠經過配置 vue 項目中的 config/index.js 來解決問題。

將 dev 中的 proxyTable 改成以下:

proxyTable: {
 '/api': {
 target: 'http://localhost/test/public/api/',
 changeOrigin: true,
 pathRewrite: {
  '^/api': ''
 }
 }
},

接着,再將 vue 組件頁面中的 ajax 請求代碼改成以下:

// 改成這樣,原來是這樣:axios.get("http://localhost/test/public/api/books")
axios.get("/api/books")

從新運行 npm run dev ,運行效果以下:

爲何這麼作?

當咱們打開瀏覽器的開發者工具查看一下網絡請求就會發現,這個 ajax 請求居然是向咱們前端的 webpack-dev-server 發送的:

 

並且竟然能返回正確的數據???

瀏覽器有安全策略限制,可是第三方的服務(服務器)沒有呀,因此咱們能夠經過讓瀏覽器訪問前端開發服務器的url,讓前端開發服務器去向後端服務器發送請求,再返回數據給瀏覽器,這樣子就不存在跨域問題啦。

當咱們在配置中這麼寫時:

proxyTable: {
 '/api': {
 target: 'http://localhost/test/public/api/',
 }
},

對於8081端口的開發服務器而言,全部以 /api 開頭的 uri 都會被轉發到 http://localhost/test/public/api/ ,

也就是說,在瀏覽器中訪問 localhost:8081/api/books ,前端開發服務器就會向 http://localhost/test/public/api/api/books 請求數據。就是簡單粗暴地在 target 以後拼接上當前的uri。

會發現這樣子作,實際的 url 中多了一個 /api ,不知足咱們的需求,因此能夠經過 pathRewrite 將這幾個字符串替換掉。

// 將 "/api" 開頭的 url 中的 "api" 替換成 空
proxyTable: {
 '/api': {
 target: 'http://localhost/test/public/api/',
 pathRewrite: {
  '^/api': ''
 }
 }
},
// 根據上面的規則
// 當在瀏覽器訪問 localhost:8081/api/books
// 則實際訪問的是 http://localhost/test/public/api/books
// 假設設置成 
pathRewrite: {'^/api': '/somethingnew'}
// 當在瀏覽器訪問 localhost:8081/api/books
// 則實際訪問的是 http://localhost/test/public/somethingnew/books

而配置項 changeOrigin: true 則是設置了前端開發服務器向後端發送請求時 HTTP 包中的 HOST 字段。當設置爲 true 時,HOST 會被設置成目標地址(target)中的主機。當後端服務器是虛擬主機時,這個選項顯得尤其重要,或者說,同一個IP綁定了多個服務器服務時顯得尤其重要。不設置的話,可能會致使請求不到數據。

更多的 proxyTable 可用參數能夠參考 http-proxy-middleware 的文檔

相關文章
相關標籤/搜索