原文鏈接:https://ssshooter.com/2019-05...
反向代理是什麼
放兩個神圖,圖片來自這裏。
這是正向代理
這是反向代理
- 正向代理是你發出請求的時候先經過代理服務器,所以實際上發出請求的是代理服務器。
- 反向代理是“代理你的目標服務器”,請求目標服務器的代理,做一些處理後再真正請求。
在這篇文章裏,反向代理用於處理跨域問題。
測試環境的跨域
module.exports = {
publicPath: '/',
devServer: {
proxy: {
'/wiki': {
target: 'http://xxx.com.cn', // 代理到的目標地址
pathRewrite: { '^/wiki': '' }, // 重寫部分路徑
ws: true, // 是否代理 websockets
changeOrigin: true,
},
},
},
}
我們神奇的 webpack 有一個可以幫你實現測試跨域的插件,相信大家都比較熟悉,本質上這個插件的功能來自 http-proxy-middleware。
* 關於 changeOrigin:這個選項的作用真的看不懂(下面是源碼),看代碼貌似是改變 headers 的 host 字段,但是實際上我修改成 true 和 false 測試,請求頭好像並沒有變化。但是以前的一個項目中有一個情況是必須把這個選項設定爲 true 才能正常跨域,所以保險起見設 true。這個問題先放下吧,或者大家知道的話在評論區留言指導一下 OTL。
// 附源碼
if (options.changeOrigin) {
outgoing.headers.host =
required(outgoing.port, options[forward || 'target'].protocol) &&
!hasPort(outgoing.host)
? outgoing.host + ':' + outgoing.port
: outgoing.host
}
按照上面的配置啓動測試環境之後,直接在瀏覽器輸入 http://localhost/wiki/rest/api/2/user/picker
就等於訪問 http://xxx.com.cn/rest/api/2/user/picker
。
在 nginx 配置
聯動一下之前的普通地址配置。
在這次要做的配置甚至沒有上次相對位置的理解難,寫法都跟 node 的配置差不多,只需要兩句:
location /wiki/ {
rewrite ^/wiki/(.*)$ /$1 break;
proxy_pass http://xxx.com.cn;
}
rewrite 的語法是(來自文檔):rewrite regex replacement [flag];
所以上面的效果是匹配 ^/wiki/(.*)$
然後替換爲 /
加匹配到的後面括號後的分塊。
按照上面的配置,重啓 nginx ./nginx -s reload
,直接在瀏覽器輸入 http://localhost/wiki/rest/api/2/user/picker
就等於訪問 http://xxx.com.cn/rest/api/2/user/picker
啦。
附加的正則小知識
其實 $1
在 JavaScript 的正則裏也能使用:
let reg = /^\/wiki\/(.*)$/
'/wiki/2111edqd'.replace(reg, '$1')
// => 2111edqd
在這裏,括號的作用就是用於匹配一個分塊。作爲對比再舉一個例子:
let reg = /^\/wiki\/(.*)$/
let reg2 = /^\/wiki\/.*$/
// 其實不用括號也完全可以匹配你需要的字符串
// 但是在 match 的時候你就能看到區別
'/wiki/2111edqd'.match(reg)
// 輸出 ["/wiki/2111edqd", "2111edqd", index: 0, input: "/wiki/2111edqd", groups: undefined]
'/wiki/2111edqd'.match(reg2)
// 輸出 ["/wiki/2111edqd", index: 0, input: "/wiki/2111edqd", groups: undefined]
reg 輸出的數組的第二個參數就是所謂的 $1
,如果後面還有其他括號分組就會有 $2
、$3
,但是不加括號就不存在這個東西。