Vue使用axios及http-proxy-middleware解決跨域存取RESTful APIs問題

前言

由於Vue.Js官方已不在維護vue-resource,而另推薦使用axios。因此就以axios為例,搭配http-proxy-middleware,做到

  1. 跨域存取
  2. 前後端分離的開發,最終部署仍是同一台server的話,也可以讓API網址直接寫成部署後的內部使用樣子,避免部署時需要再修改的網址的雜事

而VUE-CLI產生的專案本身已有先將proxytable寫好了!因此裝好套件設定好後,就可以直接使用了!

安裝axios及http-proxy-middleware

1
2
3
npm i axios --save-dev
npm i vue-axios --save-dev
npm i http-proxy-middleware --save-dev

載入axios

打開src/main.js,輸入

1
2
3
import axios from 'axios';
import VueAxios from 'vue-axios';
Vue.use(VueAxios,axios);

設定http-proxy-middleware

打開config/index.js,搜尋proxyTable,會看到官方已經預置在裡面,將設定填進至{}裡面

1
2
3
4
5
6
7
8
9
proxyTable: {
'/api': { // 前端的變數
target: 'http://127.0.0.1:8000/api/', // 遠端或後端提供的連結
changeOrigin: true,
pathRewrite: {
'^/api': ''
},
//可設定多個,用,隔開
}

app.vue檔新增一個methods測試 (記得template要加個button關聯)

1
2
3
4
5
6
7
8
9
10
11
12
13
methods: {
test(){
let vm = this;
vm.axios.post('/api/user/',{usr:'test',pwd:'pwd'}).then(res=>{
console.log(res.data);
});
//若沒設定http-proxy-middleware,後端有關閉垮域限制供開發使用。則開發時需寫成這樣來取資料
//但最終又會部署在同一台,導致build檔時還需要再修改地址,很麻煩
vm.axios.post('http://127.0.0.1:8000/api/user/',{usr:'test',pwd:'pwd'}).then(res=>{
console.log(res.data);
});
}
}

打開chrome的console,會看到順利取得資料

其實他的作業方式也很容易理解

當遇到/api時,在前面加上http://127.0.0.1:8000/api/,但路徑就變成了http://127.0.0.1:8000/api/api了!網址就錯了!

所以接著在pathRewrite裡把原本的關鍵字/api拿掉,這樣在get時得到的網址,就會是http://127.0.0.1:8000/api/user/了!

注意!每次修改proxyTable後,都需要重新啟動服務!!他沒有hot-reload!

即按ctrl+c後在npm run dev

分享一個踩過的坑

若proxyTable路徑很相似的話,他會直接以先取到的為主,然後網址就會解析錯誤啦!

比如以下例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
proxyTable: {
'/api': { // 前端的變數
target: 'http://127.0.0.1:8000/api/', // 遠端或後端提供的連結
changeOrigin: true,
pathRewrite: {
'^/api': ''
},
'/api-auth/': { // 前端的變數
target: 'http://127.0.0.1:8000/api-auth/', // 遠端或後端提供的連結
changeOrigin: true,
pathRewrite: {
'^/api-auth': ''
},
}

會發現得到的網址是http://127.0.0.1:8000/api/-auth/

這個坑最大的問題是在console看到的post網址是正確的,沒注意的話還真的滿不容易發現的…

解決方法很簡單,把每個的後面都加/,讓他完整取代

1
2
3
4
5
6
7
8
9
10
11
12
13
14
proxyTable: {
+ '/api/': { // 前端的變數
target: 'http://127.0.0.1:8000/api/', // 遠端或後端提供的連結
changeOrigin: true,
pathRewrite: {
+ '^/api/': ''
},
+ '/api-auth/': { // 前端的變數
target: 'http://127.0.0.1:8000/api-auth/', // 遠端或後端提供的連結
changeOrigin: true,
pathRewrite: {
+ '^/api-auth/': ''
},
}

在Vue.Js寫axios時記得每個網址結尾都要寫好/,如/api/user/,不要偷懶只寫個/api/user,就不太會出現這種錯誤了!

參考資料

如何在 Vue-CLI 建立的開發環境呼叫跨域遠端 RESTful APIs

Github/http-proxy-middleware