2020-06-15 10:04:08 +00:00
|
|
|
package http_mock
|
2020-04-01 02:08:21 +00:00
|
|
|
|
|
|
|
import (
|
2021-01-04 16:52:21 +00:00
|
|
|
"net"
|
2020-04-01 02:08:21 +00:00
|
|
|
"net/http"
|
2020-10-02 09:56:48 +00:00
|
|
|
"strconv"
|
2021-01-04 16:52:21 +00:00
|
|
|
"strings"
|
2020-12-26 13:11:49 +00:00
|
|
|
|
|
|
|
"github.com/prometheus/client_golang/prometheus"
|
2021-01-04 16:52:21 +00:00
|
|
|
"gitlab.com/inetmock/inetmock/pkg/audit"
|
2020-12-26 13:11:49 +00:00
|
|
|
"gitlab.com/inetmock/inetmock/pkg/logging"
|
|
|
|
"go.uber.org/zap"
|
2021-01-04 16:52:21 +00:00
|
|
|
"google.golang.org/protobuf/types/known/anypb"
|
2020-04-01 02:08:21 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
type route struct {
|
2020-12-26 13:11:49 +00:00
|
|
|
rule targetRule
|
2020-04-01 02:08:21 +00:00
|
|
|
handler http.Handler
|
|
|
|
}
|
|
|
|
|
|
|
|
type RegexpHandler struct {
|
2020-10-02 09:56:48 +00:00
|
|
|
handlerName string
|
|
|
|
logger logging.Logger
|
|
|
|
routes []*route
|
2021-01-04 16:52:21 +00:00
|
|
|
emitter audit.Emitter
|
2020-04-01 02:08:21 +00:00
|
|
|
}
|
|
|
|
|
2020-12-26 13:11:49 +00:00
|
|
|
func (h *RegexpHandler) Handler(rule targetRule, handler http.Handler) {
|
|
|
|
h.routes = append(h.routes, &route{rule, handler})
|
2020-04-01 02:08:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (h *RegexpHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
2020-10-02 09:56:48 +00:00
|
|
|
timer := prometheus.NewTimer(requestDurationHistogram.WithLabelValues(h.handlerName))
|
|
|
|
defer timer.ObserveDuration()
|
|
|
|
|
2020-12-26 13:11:49 +00:00
|
|
|
for idx := range h.routes {
|
|
|
|
rule := h.routes[idx].rule
|
|
|
|
if h.routes[idx].rule.requestMatchTarget.Matches(r, rule.targetKey, rule.pattern) {
|
2020-10-02 09:56:48 +00:00
|
|
|
totalRequestCounter.WithLabelValues(h.handlerName, strconv.FormatBool(true)).Inc()
|
2020-12-26 13:11:49 +00:00
|
|
|
h.routes[idx].handler.ServeHTTP(w, r)
|
2020-04-01 02:08:21 +00:00
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// no pattern matched; send 404 response
|
2020-10-02 09:56:48 +00:00
|
|
|
totalRequestCounter.WithLabelValues(h.handlerName, strconv.FormatBool(false)).Inc()
|
2020-04-01 02:08:21 +00:00
|
|
|
http.NotFound(w, r)
|
|
|
|
}
|
2020-10-02 09:56:48 +00:00
|
|
|
|
|
|
|
func (h *RegexpHandler) setupRoute(rule targetRule) {
|
|
|
|
h.logger.Info(
|
|
|
|
"setup routing",
|
|
|
|
zap.String("route", rule.Pattern().String()),
|
|
|
|
zap.String("response", rule.Response()),
|
|
|
|
)
|
|
|
|
|
2021-01-04 16:52:21 +00:00
|
|
|
h.Handler(rule, emittingFileHandler{
|
|
|
|
emitter: h.emitter,
|
|
|
|
targetPath: rule.response,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
type emittingFileHandler struct {
|
|
|
|
emitter audit.Emitter
|
|
|
|
targetPath string
|
2020-10-02 09:56:48 +00:00
|
|
|
}
|
|
|
|
|
2021-01-04 16:52:21 +00:00
|
|
|
func (f emittingFileHandler) ServeHTTP(writer http.ResponseWriter, request *http.Request) {
|
|
|
|
f.emitter.Emit(eventFromRequest(request))
|
|
|
|
http.ServeFile(writer, request, f.targetPath)
|
|
|
|
}
|
|
|
|
|
|
|
|
func eventFromRequest(request *http.Request) audit.Event {
|
|
|
|
details := audit.HTTPDetails{
|
|
|
|
Method: request.Method,
|
|
|
|
Host: request.Host,
|
|
|
|
URI: request.RequestURI,
|
|
|
|
Proto: request.Proto,
|
|
|
|
Headers: request.Header,
|
|
|
|
}
|
|
|
|
var wire *anypb.Any
|
|
|
|
if w, err := details.MarshalToWireFormat(); err == nil {
|
|
|
|
wire = w
|
|
|
|
}
|
|
|
|
|
|
|
|
localIP, localPort := ipPortFromAddr(LocalAddr(request.Context()))
|
|
|
|
remoteIP, remotePort := ipPortFromAddr(RemoteAddr(request.Context()))
|
|
|
|
|
|
|
|
return audit.Event{
|
|
|
|
Transport: audit.TransportProtocol_TCP,
|
|
|
|
Application: audit.AppProtocol_HTTP,
|
|
|
|
SourceIP: remoteIP,
|
|
|
|
DestinationIP: localIP,
|
|
|
|
SourcePort: remotePort,
|
|
|
|
DestinationPort: localPort,
|
|
|
|
ProtocolDetails: wire,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func ipPortFromAddr(addr net.Addr) (ip net.IP, port uint16) {
|
|
|
|
if tcpAddr, isTCPAddr := addr.(*net.TCPAddr); isTCPAddr {
|
|
|
|
return tcpAddr.IP, uint16(tcpAddr.Port)
|
|
|
|
}
|
|
|
|
|
|
|
|
ipPortSplit := strings.Split(addr.String(), ":")
|
|
|
|
if len(ipPortSplit) != 2 {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
ip = net.ParseIP(ipPortSplit[0])
|
|
|
|
|
|
|
|
if p, err := strconv.Atoi(ipPortSplit[1]); err == nil {
|
|
|
|
port = uint16(p)
|
|
|
|
}
|
|
|
|
|
|
|
|
return
|
2020-10-02 09:56:48 +00:00
|
|
|
}
|