103 lines
2.6 KiB
Go
103 lines
2.6 KiB
Go
package port
|
|
|
|
import (
|
|
"net/http"
|
|
"sync"
|
|
|
|
"gitea.dwysokinski.me/twhelp/corev3/internal/app"
|
|
"gitea.dwysokinski.me/twhelp/corev3/internal/port/internal/apimodel"
|
|
"gitea.dwysokinski.me/twhelp/corev3/internal/port/internal/swgui"
|
|
"github.com/getkin/kin-openapi/openapi3"
|
|
"github.com/go-chi/chi/v5"
|
|
"github.com/go-chi/chi/v5/middleware"
|
|
)
|
|
|
|
type apiHTTPHandler struct {
|
|
versionSvc *app.VersionService
|
|
serverSvc *app.ServerService
|
|
tribeSvc *app.TribeService
|
|
openAPISchema func() (*openapi3.T, error)
|
|
}
|
|
|
|
func WithOpenAPIConfig(oapiCfg OpenAPIConfig) APIHTTPHandlerOption {
|
|
return func(cfg *apiHTTPHandlerConfig) {
|
|
cfg.openAPI = oapiCfg
|
|
}
|
|
}
|
|
|
|
func NewAPIHTTPHandler(
|
|
versionSvc *app.VersionService,
|
|
serverSvc *app.ServerService,
|
|
tribeSvc *app.TribeService,
|
|
opts ...APIHTTPHandlerOption,
|
|
) http.Handler {
|
|
cfg := newAPIHTTPHandlerConfig(opts...)
|
|
|
|
h := &apiHTTPHandler{
|
|
versionSvc: versionSvc,
|
|
serverSvc: serverSvc,
|
|
tribeSvc: tribeSvc,
|
|
openAPISchema: sync.OnceValues(func() (*openapi3.T, error) {
|
|
return getOpenAPISchema(cfg.openAPI)
|
|
}),
|
|
}
|
|
|
|
r := chi.NewRouter()
|
|
|
|
if cfg.openAPI.Enabled {
|
|
r.Group(func(r chi.Router) {
|
|
if cfg.openAPI.SwaggerEnabled {
|
|
r.HandleFunc("/v2/swagger", func(w http.ResponseWriter, r *http.Request) {
|
|
http.Redirect(w, r, r.RequestURI+"/", http.StatusMovedPermanently)
|
|
})
|
|
r.Handle("/v2/swagger/*", swgui.Handler(
|
|
cfg.openAPI.BasePath+"/v2/swagger",
|
|
cfg.openAPI.BasePath+"/v2/openapi3.json",
|
|
))
|
|
}
|
|
r.Get("/v2/openapi3.json", h.sendOpenAPIJSON)
|
|
})
|
|
}
|
|
|
|
// these handlers must be set after the swagger/openapi routes
|
|
// because we don't want to override the default handlers for these routes
|
|
r.NotFound(h.handleNotFound)
|
|
r.MethodNotAllowed(h.handleMethodNotAllowed)
|
|
|
|
return apimodel.HandlerWithOptions(h, apimodel.ChiServerOptions{
|
|
BaseRouter: r,
|
|
Middlewares: []apimodel.MiddlewareFunc{
|
|
middleware.NoCache,
|
|
h.versionMiddleware,
|
|
h.serverMiddleware,
|
|
},
|
|
ErrorHandlerFunc: func(w http.ResponseWriter, r *http.Request, err error) {
|
|
apiErrorRenderer{errors: []error{err}}.render(w, r)
|
|
},
|
|
})
|
|
}
|
|
|
|
func (h *apiHTTPHandler) handleNotFound(w http.ResponseWriter, r *http.Request) {
|
|
apiErrorRenderer{
|
|
errors: []error{
|
|
apiError{
|
|
status: http.StatusNotFound,
|
|
code: "route-not-found",
|
|
message: "route not found",
|
|
},
|
|
},
|
|
}.render(w, r)
|
|
}
|
|
|
|
func (h *apiHTTPHandler) handleMethodNotAllowed(w http.ResponseWriter, r *http.Request) {
|
|
apiErrorRenderer{
|
|
errors: []error{
|
|
apiError{
|
|
status: http.StatusMethodNotAllowed,
|
|
code: "method-not-allowed",
|
|
message: "method not allowed",
|
|
},
|
|
},
|
|
}.render(w, r)
|
|
}
|