想要实现 HTTP 代理和反向代理,可以使用 Go 语言内置的 net/http/httputil 包。
实现 HTTP 代理
- 首先,使用
net/http/httputil
包中的NewSingleHostReverseProxy
函数创建一个逆向代理器:
go
func main() {
remote, err := url.Parse("http://remote-server.com:8080")
if err != nil {
log.Fatalf("error: %v", err)
}
proxy := httputil.NewSingleHostReverseProxy(remote)
}
在上面的代码中,我们将远程服务器的 URL 解析为一个 *url.URL
变量,并使用 NewSingleHostReverseProxy
函数创建了一个逆向代理器 proxy
。
- 接下来,针对每个 HTTP 请求创建一个处理函数,并在其中调用逆向代理器的
ServeHTTP
方法:
go
func main() {
// ...
http.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) {
proxy.ServeHTTP(w, req)
})
// ...
}
在这段代码中,我们创建了一个 http.HandleFunc
处理器函数,当客户端请求根路径时,调用 proxy.ServeHTTP
函数。
- 最后,通过
http.ListenAndServe
函数监听本地端口并启动 HTTP 服务:
go
func main() {
// ...
err = http.ListenAndServe(":9090", nil)
if err != nil {
log.Fatalf("error: %v", err)
}
}
在上面的代码中,我们使用 http.ListenAndServe
函数监听本地 9090 端口,并将 nil
作为处理器传递给函数。
完整的示例代码如下:
package main
import (
"log"
"net/http"
"net/http/httputil"
"net/url"
)
func main() {
remote, err := url.Parse("http://remote-server.com:8080")
if err != nil {
log.Fatalf("error: %v", err)
}
proxy := httputil.NewSingleHostReverseProxy(remote)
http.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) {
proxy.ServeHTTP(w, req)
})
err = http.ListenAndServe(":9090", nil)
if err != nil {
log.Fatalf("error: %v", err)
}
}
实现反向代理
-
首先,创建一个 HTTP 客户端并使用其进行发送 HTTP 请求:
go
func main() {
client := &http.Client{}
req, err := http.NewRequest(http.MethodGet, "http://backend-server.com/api/v1/path", nil)
if err != nil {
log.Fatalf("error: %v", err)
}
resp, err := client.Do(req)
if err != nil {
log.Fatalf("error: %v", err)
}
// ...
}
在上面的代码中,我们创建了一个 HTTP 客户端并使用其向远程服务器发送了一个 GET
请求。
-
然后,从 HTTP 响应中读取响应体:
go
func main() {
// ...
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
log.Fatalf("error: %v", err)
}
// ...
}
在上面的代码中,我们使用 ioutil.ReadAll
函数读取了响应体,并将其存储在 body
变量中。
-
最后,将响应体写入 HTTP 响应并将其发送回客户端:
go
func main() {
// ...
for k, v := range resp.Header {
for _, vv := range v {
w.Header().Add(k, vv)
}
}
w.WriteHeader(resp.StatusCode)
if _, err := w.Write(body); err != nil {
log.Fatalf("error: %v", err)
}
}
在上面的代码中,我们使用 http.ResponseWriter
接口将响应体写入 HTTP 响应,并使用 W.Header().Add
函数设置响应头信息。
完整的示例代码如下:
package main
import (
"io/ioutil"
"log"
"net/http"
)
func main() {
http.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) {
client := &http.Client{}
backendURL := "http://backend-server.com/api/v1/path"
req.URL, _ = url.Parse(backendURL)
resp, err := client.Do(req)
if err != nil {
log.Fatalf("error: %v", err)
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
log.Fatalf("error: %v", err)
}
for k, v := range resp.Header {
for _, vv := range v {
w.Header().Add(k, vv)
}
}
w.WriteHeader(resp.StatusCode)
if _, err := w.Write(body); err != nil {
log.Fatalf("error: %v", err)
}
})
err := http.ListenAndServe(":9090", nil)
if err != nil {
log.Fatalf("error: %v", err)
}
}
以上两个示例代码分别展示了如何实现 HTTP 代理和反向代理,可以根据实际需求选择合适的方法。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:golang 如何实现HTTP代理和反向代理 - Python技术站