api/plugins/http_proxy/proxy_handler.go
Peter Kurfer 49e58ac2e4 Add advanced matching options to HTTP handler
- move to Gitlab
- make code better testable
- create app abstraction for server
- cleanup
2020-12-26 13:11:49 +00:00

101 lines
2.8 KiB
Go

package http_proxy
import (
"context"
"crypto/tls"
"net/http"
"net/url"
"github.com/prometheus/client_golang/prometheus"
"gitlab.com/inetmock/inetmock/pkg/logging"
"go.uber.org/zap"
"gopkg.in/elazarl/goproxy.v1"
)
type proxyHttpHandler struct {
handlerName string
options httpProxyOptions
logger logging.Logger
}
type proxyHttpsHandler struct {
handlerName string
tlsConfig *tls.Config
logger logging.Logger
}
func (p *proxyHttpsHandler) HandleConnect(req string, _ *goproxy.ProxyCtx) (*goproxy.ConnectAction, string) {
totalHttpsRequestCounter.WithLabelValues(p.handlerName).Inc()
p.logger.Info(
"Intercepting HTTPS proxy request",
zap.String("request", req),
)
return &goproxy.ConnectAction{
Action: goproxy.ConnectMitm,
TLSConfig: func(host string, ctx *goproxy.ProxyCtx) (*tls.Config, error) {
return p.tlsConfig, nil
},
}, ""
}
func (p *proxyHttpHandler) Handle(req *http.Request, ctx *goproxy.ProxyCtx) (retReq *http.Request, resp *http.Response) {
timer := prometheus.NewTimer(requestDurationHistogram.WithLabelValues(p.handlerName))
defer timer.ObserveDuration()
totalRequestCounter.WithLabelValues(p.handlerName).Inc()
retReq = req
p.logger.Info(
"Handling request",
zap.String("source", req.RemoteAddr),
zap.String("host", req.Host),
zap.String("method", req.Method),
zap.String("protocol", req.Proto),
zap.String("path", req.RequestURI),
zap.Reflect("headers", req.Header),
)
var err error
if resp, err = ctx.RoundTrip(p.redirectHTTPRequest(req)); err != nil {
p.logger.Error(
"error while doing roundtrip",
zap.Error(err),
)
return req, nil
}
return
}
func (p proxyHttpHandler) redirectHTTPRequest(originalRequest *http.Request) (redirectReq *http.Request) {
redirectReq = &http.Request{
Method: originalRequest.Method,
URL: &url.URL{
Host: p.options.Target.host(),
Path: originalRequest.URL.Path,
ForceQuery: originalRequest.URL.ForceQuery,
Fragment: originalRequest.URL.Fragment,
Opaque: originalRequest.URL.Opaque,
RawPath: originalRequest.URL.RawPath,
RawQuery: originalRequest.URL.RawQuery,
User: originalRequest.URL.User,
},
Proto: originalRequest.Proto,
ProtoMajor: originalRequest.ProtoMajor,
ProtoMinor: originalRequest.ProtoMinor,
Header: originalRequest.Header,
Body: originalRequest.Body,
GetBody: originalRequest.GetBody,
ContentLength: originalRequest.ContentLength,
TransferEncoding: originalRequest.TransferEncoding,
Close: false,
Host: originalRequest.Host,
Form: originalRequest.Form,
PostForm: originalRequest.PostForm,
MultipartForm: originalRequest.MultipartForm,
Trailer: originalRequest.Trailer,
}
redirectReq = redirectReq.WithContext(context.Background())
return
}