1 回答
TA贡献1860条经验 获得超9个赞
TCP转发就是实现隧道代理不需要解析数据。反向代理可以使用标准库。
实现隧道代理以分离 http 和 https 协议。客户端一般使用隧道发送https,发送Connect方法。发送http是Get方法。对于https请求服务,只有dail创建连接tcp转换,http请求使用反向代理实现。
func(w http.ResponseWriter, r *http.Request) {
// check url host
if r.URL.Host != "" {
if r.Method == eudore.MethodConnect {
// tunnel proxy
conn, err := net.Dial("tcp", r.URL.Host)
if err != nil {
w.WriteHeader(502)
return
}
client, _, err := w.Hijack()
if err != nil {
w.WriteHeader(502)
conn.Close()
return
}
client.Write([]byte("HTTP/1.0 200 OK\r\n\r\n"))
go func() {
io.Copy(client, conn)
client.Close()
conn.Close()
}()
go func() {
io.Copy(conn, client)
client.Close()
conn.Close()
}()
} else {
// reverse proxy
httputil.NewSingleHostReverseProxy(r.URL).ServeHTTP(w, r)
}
}
}
实现反向代理会解析客户端请求,代理会将请求发送到目标服务器。
反向代理转换请求,未经测试:
func(w http.ResponseWriter, r *http.Request) {
// set host
r.URL.Scheme = "http"
r.URL.Path = "example.com"
// send
resp,err := http.DefaultClient.Do(r)
if err != nil {
w.WriteHeader(502)
return
}
// write respsonse
defer resp.Body.Close()
w.WriteHeader(resp.StatusCode)
h := w.Header()
for k,v := range resp.Header {
h[k]=v
}
io.Copy(w, resp.Body)
}
但是,直接转发请求不处理跳到跳标头。跳到跳标头在rfc中明确说明。hop-to-hop header是两个连接之间的传输信息。例如,客户端到代理和代理到服务器是两个。客户端到服务器是端到端的。
反向代理请直接使用标准库,它已经为您处理了跳到跳标头和升级。
带有过滤器的示例 NewSingleHostReverseProxy:
package main
import (
"net/http"
"strings"
"net/http/httputil"
"net/url"
)
func main() {
addr, _ := url.Parse("http://localhost:8088")
proxy := httputil.NewSingleHostReverseProxy(addr)
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
if strings.HasPrefix(r.URL.Path, "/api/") {
proxy.ServeHTTP(w, r)
} else {
w.WriteHeader(404)
}
})
// Listen Server
}
- 1 回答
- 0 关注
- 105 浏览
添加回答
举报