2021-01-13 17:07:04 +00:00
|
|
|
package mock
|
2020-04-01 02:08:21 +00:00
|
|
|
|
|
|
|
import (
|
2020-10-02 09:56:48 +00:00
|
|
|
"context"
|
|
|
|
"errors"
|
2021-02-10 20:26:45 +00:00
|
|
|
"net"
|
2020-04-01 02:08:21 +00:00
|
|
|
"net/http"
|
2020-12-26 13:11:49 +00:00
|
|
|
|
2021-02-10 20:26:45 +00:00
|
|
|
"github.com/soheilhy/cmux"
|
|
|
|
"gitlab.com/inetmock/inetmock/internal/endpoint"
|
2021-01-20 18:03:05 +00:00
|
|
|
imHttp "gitlab.com/inetmock/inetmock/internal/endpoint/handler/http"
|
2020-12-26 13:11:49 +00:00
|
|
|
"gitlab.com/inetmock/inetmock/pkg/logging"
|
|
|
|
"go.uber.org/zap"
|
2020-04-01 02:08:21 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
const (
|
2020-10-02 09:56:48 +00:00
|
|
|
name = "http_mock"
|
|
|
|
handlerNameLblName = "handler_name"
|
|
|
|
ruleMatchedLblName = "rule_matched"
|
2020-04-01 02:08:21 +00:00
|
|
|
)
|
|
|
|
|
2020-04-01 22:58:44 +00:00
|
|
|
type httpHandler struct {
|
2020-04-13 22:14:56 +00:00
|
|
|
logger logging.Logger
|
2020-04-01 02:08:21 +00:00
|
|
|
server *http.Server
|
|
|
|
}
|
|
|
|
|
2021-02-10 20:26:45 +00:00
|
|
|
func (p *httpHandler) Matchers() []cmux.Matcher {
|
|
|
|
return []cmux.Matcher{cmux.HTTP1()}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (p *httpHandler) Start(lifecycle endpoint.Lifecycle) (err error) {
|
|
|
|
p.logger = lifecycle.Logger().With(
|
2020-12-26 13:11:49 +00:00
|
|
|
zap.String("protocol_handler", name),
|
|
|
|
)
|
|
|
|
|
|
|
|
var options httpOptions
|
2021-02-10 20:26:45 +00:00
|
|
|
if options, err = loadFromConfig(lifecycle); err != nil {
|
2020-12-26 13:11:49 +00:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2020-04-01 02:08:21 +00:00
|
|
|
p.logger = p.logger.With(
|
2021-02-10 20:26:45 +00:00
|
|
|
zap.String("address", lifecycle.Uplink().Addr().String()),
|
2020-04-01 02:08:21 +00:00
|
|
|
)
|
|
|
|
|
2020-10-02 09:56:48 +00:00
|
|
|
router := &RegexpHandler{
|
|
|
|
logger: p.logger,
|
2021-02-10 20:26:45 +00:00
|
|
|
emitter: lifecycle.Audit(),
|
|
|
|
handlerName: lifecycle.Name(),
|
2020-10-02 09:56:48 +00:00
|
|
|
}
|
2021-01-04 16:52:21 +00:00
|
|
|
p.server = &http.Server{
|
|
|
|
Handler: router,
|
2021-01-20 18:03:05 +00:00
|
|
|
ConnContext: imHttp.StoreConnPropertiesInContext,
|
2021-01-04 16:52:21 +00:00
|
|
|
}
|
2020-10-02 09:56:48 +00:00
|
|
|
|
2020-04-01 02:08:21 +00:00
|
|
|
for _, rule := range options.Rules {
|
2020-10-02 09:56:48 +00:00
|
|
|
router.setupRoute(rule)
|
2020-04-01 02:08:21 +00:00
|
|
|
}
|
|
|
|
|
2021-02-10 20:26:45 +00:00
|
|
|
go p.startServer(lifecycle.Uplink().Listener)
|
|
|
|
go p.shutdownOnCancel(lifecycle.Context())
|
2020-04-13 22:14:56 +00:00
|
|
|
return
|
2020-04-01 02:08:21 +00:00
|
|
|
}
|
|
|
|
|
2021-02-10 20:26:45 +00:00
|
|
|
func (p *httpHandler) shutdownOnCancel(ctx context.Context) {
|
|
|
|
<-ctx.Done()
|
2020-04-12 01:51:41 +00:00
|
|
|
p.logger.Info("Shutting down HTTP mock")
|
2021-02-10 20:26:45 +00:00
|
|
|
if err := p.server.Close(); err != nil {
|
2020-04-01 02:08:21 +00:00
|
|
|
p.logger.Error(
|
|
|
|
"failed to shutdown HTTP server",
|
|
|
|
zap.Error(err),
|
|
|
|
)
|
|
|
|
}
|
2020-04-13 22:14:56 +00:00
|
|
|
return
|
2020-04-01 02:08:21 +00:00
|
|
|
}
|
|
|
|
|
2021-02-10 20:26:45 +00:00
|
|
|
func (p *httpHandler) startServer(listener net.Listener) {
|
|
|
|
defer func() {
|
|
|
|
if err := listener.Close(); err != nil {
|
|
|
|
p.logger.Warn("failed to close listener", zap.Error(err))
|
2021-01-26 17:42:07 +00:00
|
|
|
}
|
2021-02-10 20:26:45 +00:00
|
|
|
}()
|
|
|
|
if err := p.server.Serve(listener); err != nil && !errors.Is(err, http.ErrServerClosed) {
|
2020-04-01 02:08:21 +00:00
|
|
|
p.logger.Error(
|
|
|
|
"failed to start http listener",
|
|
|
|
zap.Error(err),
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|