-
Notifications
You must be signed in to change notification settings - Fork 17
/
http_proxy.go
115 lines (99 loc) · 2.65 KB
/
http_proxy.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
package mps
import (
"errors"
"fmt"
"net"
"net/http"
)
// The basic proxy type. Implements http.Handler.
type HttpProxy struct {
// Handles Connect requests use the TunnelHandler by default
HandleConnect http.Handler
// HTTP requests use the ForwardHandler by default
HttpHandler http.Handler
// HTTP requests use the ReverseHandler by default
ReverseHandler http.Handler
// Client request Context
Ctx *Context
}
func NewHttpProxy() *HttpProxy {
// default Context with Proxy
ctx := NewContext()
return &HttpProxy{
Ctx: ctx,
// default handles Connect method
HandleConnect: &TunnelHandler{Ctx: ctx},
// default handles HTTP request
HttpHandler: &ForwardHandler{Ctx: ctx},
// default Reverse proxy
ReverseHandler: &ReverseHandler{Ctx: ctx},
}
}
// Standard net/http function.
func (proxy *HttpProxy) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
if req.Method == http.MethodConnect {
proxy.HandleConnect.ServeHTTP(rw, req)
return
}
// reverse proxy http request for example:
// GET / HTTP/1.1
// Host: www.example.com
// Connection: keep-alive
//
// forward proxy http request for example :
// GET http://www.example.com/ HTTP/1.1
// Host: www.example.com
// Proxy-Connection: keep-alive
//
// Determines whether the path is absolute
if !req.URL.IsAbs() {
proxy.ReverseHandler.ServeHTTP(rw, req)
} else {
proxy.HttpHandler.ServeHTTP(rw, req)
}
}
// Use registers an Middleware to proxy
func (proxy *HttpProxy) Use(middleware ...Middleware) {
proxy.Ctx.Use(middleware...)
}
// UseFunc registers an MiddlewareFunc to proxy
func (proxy *HttpProxy) UseFunc(fus ...MiddlewareFunc) {
proxy.Ctx.UseFunc(fus...)
}
// OnRequest filter requests through Filters
func (proxy *HttpProxy) OnRequest(filters ...Filter) *ReqFilterGroup {
return &ReqFilterGroup{ctx: proxy.Ctx, filters: filters}
}
// OnResponse filter response through Filters
func (proxy *HttpProxy) OnResponse(filters ...Filter) *RespFilterGroup {
return &RespFilterGroup{ctx: proxy.Ctx, filters: filters}
}
// Transport get http.Transport instance
func (proxy *HttpProxy) Transport() *http.Transport {
return proxy.Ctx.Transport
}
// hijacker an HTTP handler to take over the connection.
func hijacker(rw http.ResponseWriter) (conn net.Conn, err error) {
hij, ok := rw.(http.Hijacker)
if !ok {
err = errors.New("not a hijacker")
return
}
conn, _, err = hij.Hijack()
if err != nil {
err = fmt.Errorf("cannot hijack connection %v", err)
}
return
}
func copyHeaders(dst, src http.Header, keepDestHeaders bool) {
if !keepDestHeaders {
for k := range dst {
dst.Del(k)
}
}
for k, vs := range src {
for _, v := range vs {
dst.Add(k, v)
}
}
}