【導(dǎo)讀】在本文中,我們將了解反向代理,它的應(yīng)用場景以及如何在 Golang 中實現(xiàn)它。
反向代理是位于 Web 服務(wù)器前面并將客戶端(例如 Web 瀏覽器)的請求轉(zhuǎn)發(fā)到 Web 服務(wù)器的服務(wù)器。它們讓你可以控制來自客戶端的請求和來自服務(wù)器的響應(yīng),然后我們可以利用這個特點, 可以增加緩存、做一些提高網(wǎng)站的安全性措施等。
在我們深入了解有關(guān)反向代理之前,讓我們快速看普通代理(也稱為正向代理)和反向代理之間的區(qū)別。
在正向代理中,代理代表原始客戶端從另一個網(wǎng)站檢索數(shù)據(jù)。它位于客戶端(瀏覽器)前面,并確保沒有后端服務(wù)器直接與客戶端通信。所有客戶端的請求都通過代理被轉(zhuǎn)發(fā),因此服務(wù)器只與這個代理通信(服務(wù)器會認為代理是它的客戶端)。在這種情況下,代理可以隱藏真正的客戶端。
img
另一方面,反向代理位于后端服務(wù)器的前面,確保沒有客戶端直接與服務(wù)器通信。所有客戶端請求都會通過反向代理發(fā)送到服務(wù)器,因此客戶端始終只與反向代理通信, 而從不會直接與實際服務(wù)器通信。在這種情況下,代理可以隱藏后端服務(wù)器。幾個常見的反向代理有 Nginx, HAProxy。
反向代理使用場景
負載均衡(Load balancing):反向代理可以提供負載均衡解決方案,將傳入的流量均勻地分布在不同的服務(wù)器之間,以防止單個服務(wù)器過載。
防止安全攻擊:由于真正的后端服務(wù)器永遠不需要暴露公共 IP,所以 DDoS 等攻擊只能針對反向代理進行, 這能確保在網(wǎng)絡(luò)攻擊中盡量多的保護你的資源,真正的后端服務(wù)器始終是安全的。
緩存:假設(shè)你的實際服務(wù)器與用戶所在的地區(qū)距離比較遠,那么你可以在當?shù)夭渴鸱聪虼恚梢跃彺婢W(wǎng)站內(nèi)容并為當?shù)赜脩籼峁┓?wù)。
SSL 加密:由于與每個客戶端的 SSL 通信會耗費大量的計算資源,因此可以使用反向代理處理所有與 SSL 相關(guān)的內(nèi)容, 然后釋放你真正服務(wù)器上的寶貴資源。
Golang 實現(xiàn)
import (
“l(fā)og”
“net/http”
“net/http/httputil”
“net/url”
)
// NewProxy takes target host and creates a reverse proxy// NewProxy 拿到 targetHost 后,創(chuàng)建一個反向代理func NewProxy(targetHost string) (*httputil.ReverseProxy, error) {
url, err := url.Parse(targetHost)
if err != nil {
return nil, err
}
return httputil.NewSingleHostReverseProxy(url), nil
}
// ProxyRequestHandler handles the http request using proxy// ProxyRequestHandler 使用 proxy 處理請求func ProxyRequestHandler(proxy *httputil.ReverseProxy) func(http.ResponseWriter, *http.Request) {
return func(w http.ResponseWriter, r *http.Request) {
proxy.ServeHTTP(w, r)
}
}
func main() {
// initialize a reverse proxy and pass the actual backend server url here
// 初始化反向代理并傳入真正后端服務(wù)的地址
proxy, err := NewProxy(“http://my-api-server.com”)
if err != nil {
panic(err)
}
// handle all requests to your server using the proxy
// 使用 proxy 處理所有請求到你的服務(wù)
http.HandleFunc(“/”, ProxyRequestHandler(proxy))
log.Fatal(http.ListenAndServe(“:8080”, nil))
}
是的沒錯!這就是在 Go 中創(chuàng)建一個簡單的反向代理所需的全部內(nèi)容。我們使用標準庫 net/http/httputil 創(chuàng)建了一個單主機的反向代理。到達我們代理服務(wù)器的任何請求都會被代理到位于 http://my-api-server.com。如果你對 Go 比較熟悉,這個代碼的實現(xiàn)一目了然。
修改響應(yīng)
HttpUtil 反向代理為我們提供了一種非常簡單的機制來修改我們從服務(wù)器獲得的響應(yīng), 可以根據(jù)你的應(yīng)用場景來緩存或更改此響應(yīng),讓我們看看應(yīng)該如何實現(xiàn):
// NewProxy takes target host and creates a reverse proxyfunc NewProxy(targetHost string) (*httputil.ReverseProxy, error) {
url, err := url.Parse(targetHost)
if err != nil {
return nil, err
}
proxy := httputil.NewSingleHostReverseProxy(url)
proxy.ModifyResponse = modifyResponse()
return proxy, nil
}
func modifyResponse() func(*http.Response) error {
return func(resp *http.Response) error {
resp.Header.Set(“X-Proxy”, “Magical”)
return nil
}
}
可以在 modifyResponse 方法中看到 ,我們設(shè)置了自定義 Header 頭。同樣,你也可以讀取響應(yīng)體正文,并對其進行更改或緩存,然后將其設(shè)置回客戶端。
在 modifyResponse 中,可以返回一個錯誤(如果你在處理響應(yīng)發(fā)生了錯誤), 如果你設(shè)置了 proxy.ErrorHandler, modifyResponse 返回錯誤時會自動調(diào)用 ErrorHandler 進行錯誤處理。
// NewProxy takes target host and creates a reverse proxyfunc NewProxy(targetHost string) (*httputil.ReverseProxy, error) {
url, err := url.Parse(targetHost)
if err != nil {
return nil, err
}
proxy := httputil.NewSingleHostReverseProxy(url)
proxy.ModifyResponse = modifyResponse()
proxy.ErrorHandler = errorHandler()
return proxy, nil
}
func errorHandler() func(http.ResponseWriter, *http.Request, error) {
return func(w http.ResponseWriter, req *http.Request, err error) {
fmt.Printf(“Got error while modifying response: %v
”, err)
return
}
}
func modifyResponse() func(*http.Response) error {
return func(resp *http.Response) error {
return errors.New(“response body is invalid”)
}
}
修改請求
你也可以在將請求發(fā)送到服務(wù)器之前對其進行修改。在下面的例子中,我們將會在請求發(fā)送到服務(wù)器之前添加了一個 Header 頭。同樣的,你可以在請求發(fā)送之前對其進行任何更改。
// NewProxy takes target host and creates a reverse proxyfunc NewProxy(targetHost string) (*httputil.ReverseProxy, error) {
url, err := url.Parse(targetHost)
if err != nil {
return nil, err
}
proxy := httputil.NewSingleHostReverseProxy(url)
originalDirector := proxy.Director
proxy.Director = func(req *http.Request) {
originalDirector(req)
modifyRequest(req)
}
proxy.ModifyResponse = modifyResponse()
proxy.ErrorHandler = errorHandler()
return proxy, nil
}
func modifyRequest(req *http.Request) {
req.Header.Set(“X-Proxy”, “Simple-Reverse-Proxy”)
}
完整代碼
package main
import (
“errors”
“fmt”
“l(fā)og”
“net/http”
“net/http/httputil”
“net/url”
)
// NewProxy takes target host and creates a reverse proxyfunc NewProxy(targetHost string) (*httputil.ReverseProxy, error) {
url, err := url.Parse(targetHost)
if err != nil {
return nil, err
}
proxy := httputil.NewSingleHostReverseProxy(url)
originalDirector := proxy.Director
proxy.Director = func(req *http.Request) {
originalDirector(req)
modifyRequest(req)
}
proxy.ModifyResponse = modifyResponse()
proxy.ErrorHandler = errorHandler()
return proxy, nil
}
func modifyRequest(req *http.Request) {
req.Header.Set(“X-Proxy”, “Simple-Reverse-Proxy”)
}
func errorHandler() func(http.ResponseWriter, *http.Request, error) {
return func(w http.ResponseWriter, req *http.Request, err error) {
fmt.Printf(“Got error while modifying response: %v
”, err)
return
}
}
func modifyResponse() func(*http.Response) error {
return func(resp *http.Response) error {
return errors.New(“response body is invalid”)
}
}
// ProxyRequestHandler handles the http request using proxyfunc ProxyRequestHandler(proxy *httputil.ReverseProxy) func(http.ResponseWriter, *http.Request) {
return func(w http.ResponseWriter, r *http.Request) {
proxy.ServeHTTP(w, r)
}
}
func main() {
// initialize a reverse proxy and pass the actual backend server url here
proxy, err := NewProxy(“http://my-api-server.com”)
if err != nil {
panic(err)
}
// handle all requests to your server using the proxy
http.HandleFunc(“/”, ProxyRequestHandler(proxy))
log.Fatal(http.ListenAndServe(“:8080”, nil))
}
反向代理非常強大,如文章之前所說,它有很多應(yīng)用場景。你可以根據(jù)你的情況對其進行自定義。如果遇到任何問題,我非常樂意為你提供幫助。如果你覺得這篇文章有趣,請分享一下,讓更多 gopher 可以閱讀!非常感謝你的閱讀。
轉(zhuǎn)自:h1z3y3.me/posts/simple-and-powerful-reverse-proxy-in-golang/
責任編輯:haq
-
服務(wù)器
+關(guān)注
關(guān)注
12文章
9579瀏覽量
86936 -
代理
+關(guān)注
關(guān)注
1文章
44瀏覽量
11280
原文標題:Go 簡單而強大的Reverse Proxy反向代理
文章出處:【微信號:gh_3980db2283cd,微信公眾號:開關(guān)電源芯片】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
相關(guān)推薦
如何在S32K146中實現(xiàn)以下功能?
如何在熱敏打印機中實現(xiàn)圖片的灰階打印效果嗎?
Nginx代理轉(zhuǎn)發(fā)實戰(zhàn):零基礎(chǔ)掌握服務(wù)器流量分發(fā)技巧
Python編程:處理網(wǎng)絡(luò)請求的代理技術(shù)
Golang配置代理方法

【米爾NXP i.MX 93開發(fā)板試用評測】4、使用golang搭建Modbus 服務(wù)器
如何在反向降壓-升壓拓撲中使用TPS6290x

如何在FPGA中實現(xiàn)隨機數(shù)發(fā)生器

如何在FPGA中實現(xiàn)狀態(tài)機
如何在Tensorflow中實現(xiàn)反卷積
如何在PyTorch中實現(xiàn)LeNet-5網(wǎng)絡(luò)
如何在SDK中實現(xiàn)WPS?
如何使用nginx反向代理功能?保姆級教程!

評論