mirror of
https://github.com/dstotijn/hetty
synced 2025-02-17 04:38:28 +00:00
Add request and response modifier support
This commit is contained in:
parent
ee8e4330c1
commit
9d9c46c63f
3 changed files with 62 additions and 18 deletions
9
main.go
9
main.go
|
@ -33,6 +33,15 @@ func main() {
|
||||||
log.Fatalf("[FATAL] Could not create Proxy: %v", err)
|
log.Fatalf("[FATAL] Could not create Proxy: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
proxy.UseRequestModifier(func(req *http.Request) {
|
||||||
|
log.Printf("[DEBUG] Incoming request: %v", req.URL)
|
||||||
|
})
|
||||||
|
|
||||||
|
proxy.UseResponseModifier(func(res *http.Response) error {
|
||||||
|
log.Printf("[DEBUG] Downstream response: %v %v %v", res.Proto, res.StatusCode, http.StatusText(res.StatusCode))
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
|
||||||
s := &http.Server{
|
s := &http.Server{
|
||||||
Addr: ":8080",
|
Addr: ":8080",
|
||||||
Handler: proxy,
|
Handler: proxy,
|
||||||
|
|
11
proxy/modify.go
Normal file
11
proxy/modify.go
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
package proxy
|
||||||
|
|
||||||
|
import "net/http"
|
||||||
|
|
||||||
|
var (
|
||||||
|
nopReqModifier = func(req *http.Request) {}
|
||||||
|
nopResModifier = func(res *http.Response) error { return nil }
|
||||||
|
)
|
||||||
|
|
||||||
|
type RequestModifyFunc func(req *http.Request)
|
||||||
|
type ResponseModifyFunc func(res *http.Response) error
|
|
@ -12,19 +12,6 @@ import (
|
||||||
"net/http/httputil"
|
"net/http/httputil"
|
||||||
)
|
)
|
||||||
|
|
||||||
var httpHandler = &httputil.ReverseProxy{
|
|
||||||
Director: func(r *http.Request) {},
|
|
||||||
ErrorHandler: errorHandler,
|
|
||||||
}
|
|
||||||
|
|
||||||
var httpsHandler = &httputil.ReverseProxy{
|
|
||||||
Director: func(r *http.Request) {
|
|
||||||
r.URL.Host = r.Host
|
|
||||||
r.URL.Scheme = "https"
|
|
||||||
},
|
|
||||||
ErrorHandler: errorHandler,
|
|
||||||
}
|
|
||||||
|
|
||||||
func errorHandler(w http.ResponseWriter, r *http.Request, err error) {
|
func errorHandler(w http.ResponseWriter, r *http.Request, err error) {
|
||||||
if err == context.Canceled {
|
if err == context.Canceled {
|
||||||
return
|
return
|
||||||
|
@ -37,6 +24,11 @@ func errorHandler(w http.ResponseWriter, r *http.Request, err error) {
|
||||||
// HTTP requests and responses.
|
// HTTP requests and responses.
|
||||||
type Proxy struct {
|
type Proxy struct {
|
||||||
certConfig *CertConfig
|
certConfig *CertConfig
|
||||||
|
handler http.Handler
|
||||||
|
|
||||||
|
// TODO: Add mutex for modifier funcs.
|
||||||
|
reqModifier RequestModifyFunc
|
||||||
|
resModifier ResponseModifyFunc
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewProxy returns a new Proxy.
|
// NewProxy returns a new Proxy.
|
||||||
|
@ -46,9 +38,19 @@ func NewProxy(ca *x509.Certificate, key crypto.PrivateKey) (*Proxy, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return &Proxy{
|
p := &Proxy{
|
||||||
certConfig: certConfig,
|
certConfig: certConfig,
|
||||||
}, nil
|
reqModifier: nopReqModifier,
|
||||||
|
resModifier: nopResModifier,
|
||||||
|
}
|
||||||
|
|
||||||
|
p.handler = &httputil.ReverseProxy{
|
||||||
|
Director: p.modifyRequest,
|
||||||
|
ModifyResponse: p.modifyResponse,
|
||||||
|
ErrorHandler: errorHandler,
|
||||||
|
}
|
||||||
|
|
||||||
|
return p, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Proxy) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
func (p *Proxy) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
|
@ -57,7 +59,21 @@ func (p *Proxy) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
httpHandler.ServeHTTP(w, r)
|
p.handler.ServeHTTP(w, r)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Proxy) modifyRequest(r *http.Request) {
|
||||||
|
// Fix r.URL for HTTPS requests after CONNECT.
|
||||||
|
if r.URL.Scheme == "" {
|
||||||
|
r.URL.Host = r.Host
|
||||||
|
r.URL.Scheme = "https"
|
||||||
|
}
|
||||||
|
|
||||||
|
p.reqModifier(r)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Proxy) modifyResponse(res *http.Response) error {
|
||||||
|
return p.resModifier(res)
|
||||||
}
|
}
|
||||||
|
|
||||||
// handleConnect hijacks the incoming HTTP request and sets up an HTTP tunnel.
|
// handleConnect hijacks the incoming HTTP request and sets up an HTTP tunnel.
|
||||||
|
@ -91,7 +107,7 @@ func (p *Proxy) handleConnect(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
l := &OnceAcceptListener{clientConnNotify.Conn}
|
l := &OnceAcceptListener{clientConnNotify.Conn}
|
||||||
|
|
||||||
err = http.Serve(l, httpsHandler)
|
err = http.Serve(l, p.handler)
|
||||||
if err != nil && err != ErrAlreadyAccepted {
|
if err != nil && err != ErrAlreadyAccepted {
|
||||||
log.Printf("[ERROR] Serving HTTP request failed: %v", err)
|
log.Printf("[ERROR] Serving HTTP request failed: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -110,6 +126,14 @@ func (p *Proxy) clientTLSConn(conn net.Conn) (*tls.Conn, error) {
|
||||||
return tlsConn, nil
|
return tlsConn, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *Proxy) UseRequestModifier(fn RequestModifyFunc) {
|
||||||
|
p.reqModifier = fn
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Proxy) UseResponseModifier(fn ResponseModifyFunc) {
|
||||||
|
p.resModifier = fn
|
||||||
|
}
|
||||||
|
|
||||||
func writeError(w http.ResponseWriter, r *http.Request, code int) {
|
func writeError(w http.ResponseWriter, r *http.Request, code int) {
|
||||||
http.Error(w, http.StatusText(code), code)
|
http.Error(w, http.StatusText(code), code)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue