-
Notifications
You must be signed in to change notification settings - Fork 1
/
forward.go
125 lines (111 loc) · 3.22 KB
/
forward.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
116
117
118
119
120
121
122
123
124
125
// Package forward implements http handler that forwards requests to remote server
// and serves back the response.
// websocket proxying support based on https://github.com/yhat/wsutil
package forward
import (
"net/http"
"os"
"gopkg.in/vinxi/utils.v0"
)
// ReqRewriter can alter request headers and body
type ReqRewriter interface {
Rewrite(r *http.Request)
}
// OptSetter represents the forwarder setter function.
type OptSetter func(f *Forwarder) error
// PassHostHeader specifies if a client's Host header field should
// be delegated
func PassHostHeader(b bool) OptSetter {
return func(f *Forwarder) error {
f.passHost = b
return nil
}
}
// RoundTripper sets a new http.RoundTripper
// Forwarder will use http.DefaultTransport as a default round tripper
func RoundTripper(r http.RoundTripper) OptSetter {
return func(f *Forwarder) error {
f.roundTripper = r
return nil
}
}
// Rewriter defines a request rewriter for the HTTP forwarder
func Rewriter(r ReqRewriter) OptSetter {
return func(f *Forwarder) error {
f.httpForwarder.rewriter = r
return nil
}
}
// WebsocketRewriter defines a request rewriter for the websocket forwarder
func WebsocketRewriter(r ReqRewriter) OptSetter {
return func(f *Forwarder) error {
f.websocketForwarder.rewriter = r
return nil
}
}
// ErrorHandler is a functional argument that sets error handler of the server
func ErrorHandler(h utils.ErrorHandler) OptSetter {
return func(f *Forwarder) error {
f.errHandler = h
return nil
}
}
// Logger specifies the logger to use.
// Forwarder will default to utils.NullLogger if no logger has been specified
func Logger(l utils.Logger) OptSetter {
return func(f *Forwarder) error {
f.log = l
return nil
}
}
// Forwarder wraps two traffic forwarding implementations: HTTP and websockets.
// It decides based on the specified request which implementation to use
type Forwarder struct {
*httpForwarder
*websocketForwarder
*handlerContext
}
// handlerContext defines a handler context for error reporting and logging
type handlerContext struct {
errHandler utils.ErrorHandler
log utils.Logger
}
// New creates an instance of Forwarder based on the provided list of configuration options
func New(setters ...OptSetter) (*Forwarder, error) {
f := &Forwarder{
httpForwarder: &httpForwarder{},
websocketForwarder: &websocketForwarder{},
handlerContext: &handlerContext{},
}
for _, s := range setters {
if err := s(f); err != nil {
return nil, err
}
}
if f.httpForwarder.roundTripper == nil {
f.httpForwarder.roundTripper = utils.DefaultTransport
}
if f.httpForwarder.rewriter == nil {
h, err := os.Hostname()
if err != nil {
h = "localhost"
}
f.httpForwarder.rewriter = &HeaderRewriter{TrustForwardHeader: true, Hostname: h}
}
if f.log == nil {
f.log = utils.NullLogger
}
if f.errHandler == nil {
f.errHandler = utils.DefaultHandler
}
return f, nil
}
// ServeHTTP decides which forwarder to use based on the specified
// request and delegates to the proper implementation
func (f *Forwarder) ServeHTTP(w http.ResponseWriter, req *http.Request) {
if utils.IsWebsocketRequest(req) {
f.websocketForwarder.serveHTTP(w, req, f.handlerContext)
} else {
f.httpForwarder.serveHTTP(w, req, f.handlerContext)
}
}