3
0

Re-enable API Gateway route handling (/api/gateway/...)

API Gateway routes are now bind under <base>/api/gateway.

This also removes custom route method validation and
handles not-found responses with a chi's NotFound method
This commit is contained in:
Denis Arh 2021-10-03 15:45:08 +02:00
parent 0d429fa641
commit 6c8bec2c3c
5 changed files with 36 additions and 40 deletions

View File

@ -112,6 +112,9 @@ func (app *CortezaApp) mountHttpRoutes(r chi.Router) {
r.Handle("/docs", http.RedirectHandler(fullpathDocs+"/", http.StatusPermanentRedirect))
r.Handle("/docs*", http.StripPrefix(fullpathDocs, http.FileServer(docs.GetFS())))
var fullpathGateway = options.CleanBase(ho.BaseUrl, ho.ApiBaseUrl, "gateway")
r.Handle("/gateway*", http.StripPrefix(fullpathGateway, app.ApigwService))
})
}()

View File

@ -13,9 +13,11 @@ const (
func helperDefaultResponse(opt *options.ApigwOpt) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
if opt.LogEnabled {
// Say something friendly when logging is enabled
http.Error(w, devHelperResponseBody, http.StatusTeapot)
} else {
http.Error(w, ``, http.StatusFound)
// Default 404 response
http.Error(w, "", http.StatusNotFound)
}
}
}

View File

@ -54,12 +54,6 @@ func (r route) ServeHTTP(w http.ResponseWriter, req *http.Request) {
scope.Set("opts", r.opts)
scope.Set("payload", body)
if err := r.validate(req); err != nil {
r.log.Debug("error validating request on route", zap.Error(err))
r.errHandler(w, req, err)
return
}
if r.opts.LogEnabled {
o, _ := httputil.DumpRequest(req, r.opts.LogRequestBody)
r.log.Debug("incoming request", zap.Any("request", string(o)))
@ -74,14 +68,6 @@ func (r route) ServeHTTP(w http.ResponseWriter, req *http.Request) {
)
}
func (r route) validate(req *http.Request) (err error) {
if req.Method != r.method {
err = fmt.Errorf("invalid method %s", req.Method)
}
return
}
func (r route) String() string {
return fmt.Sprintf("%s %s", r.method, r.endpoint)
}

View File

@ -68,18 +68,6 @@ func Test_pl(t *testing.T) {
expStatus: http.StatusTemporaryRedirect,
expError: "{\"error\":{\"message\":\"test error\"}}\n",
},
{
name: "request method validation fail",
handler: &types.MockHandler{
Handler_: func(rw http.ResponseWriter, r *http.Request) error {
rw.WriteHeader(http.StatusTemporaryRedirect)
return errors.New("test error")
},
},
method: "GET",
expStatus: http.StatusInternalServerError,
expError: "{\"error\":{\"message\":\"invalid method POST\"}}\n",
},
}
)

View File

@ -44,10 +44,6 @@ func Service() *apigw {
return apiGw
}
func Set(a *apigw) {
apiGw = a
}
// Setup handles the singleton service
func Setup(opts *options.ApigwOpt, log *zap.Logger, storer storer) {
if apiGw != nil {
@ -74,6 +70,23 @@ func New(opts *options.ApigwOpt, logger *zap.Logger, storer storer) *apigw {
//
// When reloading routes, make sure to replace the original mux
func (s *apigw) ServeHTTP(w http.ResponseWriter, r *http.Request) {
if s.mx == nil {
http.Error(w, "API Gateway not initialized", http.StatusInternalServerError)
return
}
if len(s.routes) == 0 {
helperDefaultResponse(s.opts)(w, r)
return
}
// Remove route context for chi
//
// Without this, chi can not properly handle requests
// in API gateway's sub-router
r = r.WithContext(context.WithValue(r.Context(), chi.RouteCtxKey, nil))
// Handle api-gw request
s.mx.ServeHTTP(w, r)
}
@ -94,21 +107,25 @@ func (s *apigw) Reload(ctx context.Context) (err error) {
// Rebuild the mux
s.mx = chi.NewMux()
s.mx.HandleFunc("/", helperDefaultResponse(s.opts))
for _, r := range s.routes {
s.mx.Handle(r.endpoint, r)
// Register route handler on endpoint & method
s.mx.Method(r.method, r.endpoint, r)
}
// API GW 404 handler
s.mx.NotFound(helperDefaultResponse(s.opts))
return nil
}
// Init all the routes
func (s *apigw) Init(ctx context.Context, route ...*route) {
// Init all routes
func (s *apigw) Init(ctx context.Context, routes ...*route) {
var (
defaultPostFilter types.Handler
)
s.routes = route
s.routes = routes
s.log.Debug("registering routes", zap.Int("count", len(s.routes)))
@ -138,17 +155,17 @@ func (s *apigw) Init(ctx context.Context, route ...*route) {
continue
}
for _, f := range regFilters {
flog := log.With(zap.String("ref", f.Ref))
for _, rf := range regFilters {
flog := log.With(zap.String("ref", rf.Ref))
// make sure there is only one postfilter
// on async routes
if r.meta.async && f.Kind == string(types.PostFilter) {
if r.meta.async && rf.Kind == string(types.PostFilter) {
flog.Debug("not registering filter for async route")
continue
}
ff, err := s.registerFilter(f, r)
ff, err := s.registerFilter(rf, r)
if err != nil {
flog.Error("could not register filter", zap.Error(err))