2020-06-15 10:04:08 +00:00
|
|
|
package http_mock
|
2020-04-01 02:08:21 +00:00
|
|
|
|
|
|
|
import (
|
2020-10-02 09:56:48 +00:00
|
|
|
"bytes"
|
|
|
|
"github.com/baez90/inetmock/pkg/logging"
|
|
|
|
"github.com/prometheus/client_golang/prometheus"
|
|
|
|
"go.uber.org/zap"
|
2020-04-01 02:08:21 +00:00
|
|
|
"net/http"
|
|
|
|
"regexp"
|
2020-10-02 09:56:48 +00:00
|
|
|
"strconv"
|
2020-04-01 02:08:21 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
type route struct {
|
|
|
|
pattern *regexp.Regexp
|
|
|
|
handler http.Handler
|
|
|
|
}
|
|
|
|
|
|
|
|
type RegexpHandler struct {
|
2020-10-02 09:56:48 +00:00
|
|
|
handlerName string
|
|
|
|
logger logging.Logger
|
|
|
|
routes []*route
|
2020-04-01 02:08:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (h *RegexpHandler) Handler(pattern *regexp.Regexp, handler http.Handler) {
|
|
|
|
h.routes = append(h.routes, &route{pattern, handler})
|
|
|
|
}
|
|
|
|
|
|
|
|
func (h *RegexpHandler) HandleFunc(pattern *regexp.Regexp, handler func(http.ResponseWriter, *http.Request)) {
|
|
|
|
h.routes = append(h.routes, &route{pattern, http.HandlerFunc(handler)})
|
|
|
|
}
|
|
|
|
|
|
|
|
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-04-01 02:08:21 +00:00
|
|
|
for _, route := range h.routes {
|
|
|
|
if route.pattern.MatchString(r.URL.Path) {
|
2020-10-02 09:56:48 +00:00
|
|
|
totalRequestCounter.WithLabelValues(h.handlerName, strconv.FormatBool(true)).Inc()
|
2020-04-01 02:08:21 +00:00
|
|
|
route.handler.ServeHTTP(w, r)
|
|
|
|
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()),
|
|
|
|
)
|
|
|
|
|
|
|
|
h.Handler(rule.Pattern(), createHandlerForTarget(h.logger, rule.response))
|
|
|
|
}
|
|
|
|
|
|
|
|
func createHandlerForTarget(logger logging.Logger, targetPath string) http.Handler {
|
|
|
|
return http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) {
|
|
|
|
headerWriter := &bytes.Buffer{}
|
|
|
|
request.Header.Write(headerWriter)
|
|
|
|
|
|
|
|
logger.Info(
|
|
|
|
"Handling request",
|
|
|
|
zap.String("source", request.RemoteAddr),
|
|
|
|
zap.String("host", request.Host),
|
|
|
|
zap.String("method", request.Method),
|
|
|
|
zap.String("protocol", request.Proto),
|
|
|
|
zap.String("path", request.RequestURI),
|
|
|
|
zap.String("response", targetPath),
|
|
|
|
zap.Reflect("headers", request.Header),
|
|
|
|
)
|
|
|
|
|
|
|
|
http.ServeFile(writer, request, targetPath)
|
|
|
|
})
|
|
|
|
}
|