feat(http): convert errorEncode to use interface

pull/14213/head
Kelvin Wang 2019-06-26 21:33:20 -04:00
parent 9dc5438e06
commit 9ecada4dce
42 changed files with 584 additions and 437 deletions

View File

@ -17,6 +17,7 @@ import (
// APIHandler is a collection of all the service handlers.
type APIHandler struct {
influxdb.HTTPErrorHandler
BucketHandler *BucketHandler
UserHandler *UserHandler
OrgHandler *OrgHandler
@ -41,8 +42,9 @@ type APIHandler struct {
// APIBackend is all services and associated parameters required to construct
// an APIHandler.
type APIBackend struct {
AssetsPath string // if empty then assets are served from bindata.
Logger *zap.Logger
AssetsPath string // if empty then assets are served from bindata.
Logger *zap.Logger
influxdb.HTTPErrorHandler
SessionRenewDisabled bool
NewBucketService func(*influxdb.Source) (influxdb.BucketService, error)
@ -97,7 +99,9 @@ func (b *APIBackend) PrometheusCollectors() []prometheus.Collector {
// NewAPIHandler constructs all api handlers beneath it and returns an APIHandler
func NewAPIHandler(b *APIBackend) *APIHandler {
h := &APIHandler{}
h := &APIHandler{
HTTPErrorHandler: b.HTTPErrorHandler,
}
internalURM := b.UserResourceMappingService
b.UserResourceMappingService = authorizer.NewURMService(b.OrgLookupService, b.UserResourceMappingService)
@ -160,9 +164,9 @@ func NewAPIHandler(b *APIBackend) *APIHandler {
fluxBackend := NewFluxBackend(b)
h.QueryHandler = NewFluxHandler(fluxBackend)
h.ChronografHandler = NewChronografHandler(b.ChronografService)
h.SwaggerHandler = newSwaggerLoader(b.Logger.With(zap.String("service", "swagger-loader")))
h.LabelHandler = NewLabelHandler(authorizer.NewLabelService(b.LabelService))
h.ChronografHandler = NewChronografHandler(b.ChronografService, b.HTTPErrorHandler)
h.SwaggerHandler = newSwaggerLoader(b.Logger.With(zap.String("service", "swagger-loader")), b.HTTPErrorHandler)
h.LabelHandler = NewLabelHandler(authorizer.NewLabelService(b.LabelService), b.HTTPErrorHandler)
return h
}
@ -206,8 +210,7 @@ var apiLinks = map[string]interface{}{
func (h *APIHandler) serveLinks(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
if err := encodeResponse(ctx, w, http.StatusOK, apiLinks); err != nil {
EncodeError(ctx, err, w)
return
h.HandleHTTPError(ctx, err, w)
}
}
@ -319,5 +322,5 @@ func (h *APIHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
return
}
notFoundHandler(w, r)
baseHandler{HTTPErrorHandler: h.HTTPErrorHandler}.notFound(w, r)
}

View File

@ -49,7 +49,9 @@ func TestAPIHandler_NotFound(t *testing.T) {
r := httptest.NewRequest(tt.args.method, tt.args.path, nil)
w := httptest.NewRecorder()
b := &APIBackend{}
b := &APIBackend{
HTTPErrorHandler: ErrorHandler(0),
}
b.Logger = zap.NewNop()
h := NewAPIHandler(b)

View File

@ -19,6 +19,7 @@ import (
// AuthorizationBackend is all services and associated parameters required to construct
// the AuthorizationHandler.
type AuthorizationBackend struct {
platform.HTTPErrorHandler
Logger *zap.Logger
AuthorizationService platform.AuthorizationService
@ -30,7 +31,8 @@ type AuthorizationBackend struct {
// NewAuthorizationBackend returns a new instance of AuthorizationBackend.
func NewAuthorizationBackend(b *APIBackend) *AuthorizationBackend {
return &AuthorizationBackend{
Logger: b.Logger.With(zap.String("handler", "authorization")),
HTTPErrorHandler: b.HTTPErrorHandler,
Logger: b.Logger.With(zap.String("handler", "authorization")),
AuthorizationService: b.AuthorizationService,
OrganizationService: b.OrganizationService,
@ -42,6 +44,7 @@ func NewAuthorizationBackend(b *APIBackend) *AuthorizationBackend {
// AuthorizationHandler represents an HTTP API handler for authorizations.
type AuthorizationHandler struct {
*httprouter.Router
platform.HTTPErrorHandler
Logger *zap.Logger
OrganizationService platform.OrganizationService
@ -53,8 +56,9 @@ type AuthorizationHandler struct {
// NewAuthorizationHandler returns a new instance of AuthorizationHandler.
func NewAuthorizationHandler(b *AuthorizationBackend) *AuthorizationHandler {
h := &AuthorizationHandler{
Router: NewRouter(),
Logger: b.Logger,
Router: NewRouter(b.HTTPErrorHandler),
HTTPErrorHandler: b.HTTPErrorHandler,
Logger: b.Logger,
AuthorizationService: b.AuthorizationService,
OrganizationService: b.OrganizationService,
@ -184,13 +188,13 @@ func (h *AuthorizationHandler) handlePostAuthorization(w http.ResponseWriter, r
req, err := decodePostAuthorizationRequest(ctx, r)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
user, err := getAuthorizedUser(r, h.UserService)
if err != nil {
EncodeError(ctx, platform.ErrUnableToCreateToken, w)
h.HandleHTTPError(ctx, platform.ErrUnableToCreateToken, w)
return
}
@ -198,18 +202,18 @@ func (h *AuthorizationHandler) handlePostAuthorization(w http.ResponseWriter, r
org, err := h.OrganizationService.FindOrganizationByID(ctx, auth.OrgID)
if err != nil {
EncodeError(ctx, platform.ErrUnableToCreateToken, w)
h.HandleHTTPError(ctx, platform.ErrUnableToCreateToken, w)
return
}
if err := h.AuthorizationService.CreateAuthorization(ctx, auth); err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
perms, err := newPermissionsResponse(ctx, auth.Permissions, h.LookupService)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
@ -318,14 +322,14 @@ func (h *AuthorizationHandler) handleGetAuthorizations(w http.ResponseWriter, r
req, err := decodeGetAuthorizationsRequest(ctx, r)
if err != nil {
h.Logger.Info("failed to decode request", zap.String("handler", "getAuthorizations"), zap.Error(err))
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
opts := platform.FindOptions{}
as, _, err := h.AuthorizationService.FindAuthorizations(ctx, req.filter, opts)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
@ -345,7 +349,7 @@ func (h *AuthorizationHandler) handleGetAuthorizations(w http.ResponseWriter, r
ps, err := newPermissionsResponse(ctx, a.Permissions, h.LookupService)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
@ -353,7 +357,7 @@ func (h *AuthorizationHandler) handleGetAuthorizations(w http.ResponseWriter, r
}
if err := encodeResponse(ctx, w, http.StatusOK, newAuthsResponse(auths)); err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
}
@ -414,37 +418,37 @@ func (h *AuthorizationHandler) handleGetAuthorization(w http.ResponseWriter, r *
req, err := decodeGetAuthorizationRequest(ctx, r)
if err != nil {
h.Logger.Info("failed to decode request", zap.String("handler", "getAuthorization"), zap.Error(err))
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
a, err := h.AuthorizationService.FindAuthorizationByID(ctx, req.ID)
if err != nil {
// Don't log here, it should already be handled by the service
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
o, err := h.OrganizationService.FindOrganizationByID(ctx, a.OrgID)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
u, err := h.UserService.FindUserByID(ctx, a.UserID)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
ps, err := newPermissionsResponse(ctx, a.Permissions, h.LookupService)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
if err := encodeResponse(ctx, w, http.StatusOK, newAuthResponse(a, o, u, ps)); err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
}
@ -480,42 +484,42 @@ func (h *AuthorizationHandler) handleUpdateAuthorization(w http.ResponseWriter,
req, err := decodeUpdateAuthorizationRequest(ctx, r)
if err != nil {
h.Logger.Info("failed to decode request", zap.String("handler", "updateAuthorization"), zap.Error(err))
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
a, err := h.AuthorizationService.FindAuthorizationByID(ctx, req.ID)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
a, err = h.AuthorizationService.UpdateAuthorization(ctx, a.ID, req.AuthorizationUpdate)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
o, err := h.OrganizationService.FindOrganizationByID(ctx, a.OrgID)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
u, err := h.UserService.FindUserByID(ctx, a.UserID)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
ps, err := newPermissionsResponse(ctx, a.Permissions, h.LookupService)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
if err := encodeResponse(ctx, w, http.StatusOK, newAuthResponse(a, o, u, ps)); err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
}
@ -558,13 +562,13 @@ func (h *AuthorizationHandler) handleDeleteAuthorization(w http.ResponseWriter,
req, err := decodeDeleteAuthorizationRequest(ctx, r)
if err != nil {
h.Logger.Info("failed to decode request", zap.String("handler", "deleteAuthorization"), zap.Error(err))
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
if err := h.AuthorizationService.DeleteAuthorization(ctx, req.ID); err != nil {
// Don't log here, it should already be handled by the service
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}

View File

@ -323,6 +323,7 @@ func TestService_handleGetAuthorizations(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
authorizationBackend := NewMockAuthorizationBackend()
authorizationBackend.HTTPErrorHandler = ErrorHandler(0)
authorizationBackend.AuthorizationService = tt.fields.AuthorizationService
authorizationBackend.UserService = tt.fields.UserService
authorizationBackend.OrganizationService = tt.fields.OrganizationService
@ -505,6 +506,7 @@ func TestService_handleGetAuthorization(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
authorizationBackend := NewMockAuthorizationBackend()
authorizationBackend.HTTPErrorHandler = ErrorHandler(0)
authorizationBackend.AuthorizationService = tt.fields.AuthorizationService
authorizationBackend.UserService = tt.fields.UserService
authorizationBackend.OrganizationService = tt.fields.OrganizationService
@ -682,6 +684,7 @@ func TestService_handlePostAuthorization(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
authorizationBackend := NewMockAuthorizationBackend()
authorizationBackend.HTTPErrorHandler = ErrorHandler(0)
authorizationBackend.AuthorizationService = tt.fields.AuthorizationService
authorizationBackend.UserService = tt.fields.UserService
authorizationBackend.OrganizationService = tt.fields.OrganizationService
@ -795,6 +798,7 @@ func TestService_handleDeleteAuthorization(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
authorizationBackend := NewMockAuthorizationBackend()
authorizationBackend.HTTPErrorHandler = ErrorHandler(0)
authorizationBackend.AuthorizationService = tt.fields.AuthorizationService
authorizationBackend.UserService = tt.fields.UserService
authorizationBackend.OrganizationService = tt.fields.OrganizationService
@ -881,6 +885,7 @@ func initAuthorizationService(f platformtesting.AuthorizationFields, t *testing.
}
authorizationBackend := NewMockAuthorizationBackend()
authorizationBackend.HTTPErrorHandler = ErrorHandler(0)
authorizationBackend.AuthorizationService = svc
authorizationBackend.UserService = svc
authorizationBackend.OrganizationService = svc
@ -897,7 +902,7 @@ func initAuthorizationService(f platformtesting.AuthorizationFields, t *testing.
}
authZ := NewAuthorizationHandler(authorizationBackend)
authN := NewAuthenticationHandler()
authN := NewAuthenticationHandler(ErrorHandler(0))
authN.AuthorizationService = svc
authN.Handler = authZ

View File

@ -14,6 +14,7 @@ import (
// AuthenticationHandler is a middleware for authenticating incoming requests.
type AuthenticationHandler struct {
platform.HTTPErrorHandler
Logger *zap.Logger
AuthorizationService platform.AuthorizationService
@ -28,11 +29,12 @@ type AuthenticationHandler struct {
}
// NewAuthenticationHandler creates an authentication handler.
func NewAuthenticationHandler() *AuthenticationHandler {
func NewAuthenticationHandler(h platform.HTTPErrorHandler) *AuthenticationHandler {
return &AuthenticationHandler{
Logger: zap.NewNop(),
Handler: http.DefaultServeMux,
noAuthRouter: httprouter.New(),
Logger: zap.NewNop(),
HTTPErrorHandler: h,
Handler: http.DefaultServeMux,
noAuthRouter: httprouter.New(),
}
}
@ -73,7 +75,7 @@ func (h *AuthenticationHandler) ServeHTTP(w http.ResponseWriter, r *http.Request
ctx := r.Context()
scheme, err := ProbeAuthScheme(r)
if err != nil {
UnauthorizedError(ctx, w)
UnauthorizedError(ctx, h, w)
return
}
@ -96,7 +98,7 @@ func (h *AuthenticationHandler) ServeHTTP(w http.ResponseWriter, r *http.Request
return
}
UnauthorizedError(ctx, w)
UnauthorizedError(ctx, h, w)
}
func (h *AuthenticationHandler) extractAuthorization(ctx context.Context, r *http.Request) (context.Context, error) {

View File

@ -122,7 +122,7 @@ func TestAuthenticationHandler(t *testing.T) {
w.WriteHeader(http.StatusOK)
})
h := platformhttp.NewAuthenticationHandler()
h := platformhttp.NewAuthenticationHandler(platformhttp.ErrorHandler(0))
h.AuthorizationService = tt.fields.AuthorizationService
h.SessionService = tt.fields.SessionService
h.Handler = handler
@ -275,7 +275,7 @@ func TestAuthenticationHandler_NoAuthRoutes(t *testing.T) {
w.WriteHeader(http.StatusOK)
})
h := platformhttp.NewAuthenticationHandler()
h := platformhttp.NewAuthenticationHandler(platformhttp.ErrorHandler(0))
h.AuthorizationService = mock.NewAuthorizationService()
h.SessionService = mock.NewSessionService()
h.Handler = handler

View File

@ -20,6 +20,7 @@ import (
// the BucketHandler.
type BucketBackend struct {
Logger *zap.Logger
influxdb.HTTPErrorHandler
BucketService influxdb.BucketService
BucketOperationLogService influxdb.BucketOperationLogService
@ -32,7 +33,8 @@ type BucketBackend struct {
// NewBucketBackend returns a new instance of BucketBackend.
func NewBucketBackend(b *APIBackend) *BucketBackend {
return &BucketBackend{
Logger: b.Logger.With(zap.String("handler", "bucket")),
HTTPErrorHandler: b.HTTPErrorHandler,
Logger: b.Logger.With(zap.String("handler", "bucket")),
BucketService: b.BucketService,
BucketOperationLogService: b.BucketOperationLogService,
@ -46,7 +48,7 @@ func NewBucketBackend(b *APIBackend) *BucketBackend {
// BucketHandler represents an HTTP API handler for buckets.
type BucketHandler struct {
*httprouter.Router
influxdb.HTTPErrorHandler
Logger *zap.Logger
BucketService influxdb.BucketService
@ -72,8 +74,9 @@ const (
// NewBucketHandler returns a new instance of BucketHandler.
func NewBucketHandler(b *BucketBackend) *BucketHandler {
h := &BucketHandler{
Router: NewRouter(),
Logger: b.Logger,
Router: NewRouter(b.HTTPErrorHandler),
HTTPErrorHandler: b.HTTPErrorHandler,
Logger: b.Logger,
BucketService: b.BucketService,
BucketOperationLogService: b.BucketOperationLogService,
@ -91,6 +94,7 @@ func NewBucketHandler(b *BucketBackend) *BucketHandler {
h.HandlerFunc("DELETE", bucketsIDPath, h.handleDeleteBucket)
memberBackend := MemberBackend{
HTTPErrorHandler: b.HTTPErrorHandler,
Logger: b.Logger.With(zap.String("handler", "member")),
ResourceType: influxdb.BucketsResourceType,
UserType: influxdb.Member,
@ -102,6 +106,7 @@ func NewBucketHandler(b *BucketBackend) *BucketHandler {
h.HandlerFunc("DELETE", bucketsIDMembersIDPath, newDeleteMemberHandler(memberBackend))
ownerBackend := MemberBackend{
HTTPErrorHandler: b.HTTPErrorHandler,
Logger: b.Logger.With(zap.String("handler", "member")),
ResourceType: influxdb.BucketsResourceType,
UserType: influxdb.Owner,
@ -113,9 +118,10 @@ func NewBucketHandler(b *BucketBackend) *BucketHandler {
h.HandlerFunc("DELETE", bucketsIDOwnersIDPath, newDeleteMemberHandler(ownerBackend))
labelBackend := &LabelBackend{
Logger: b.Logger.With(zap.String("handler", "label")),
LabelService: b.LabelService,
ResourceType: influxdb.BucketsResourceType,
HTTPErrorHandler: b.HTTPErrorHandler,
Logger: b.Logger.With(zap.String("handler", "label")),
LabelService: b.LabelService,
ResourceType: influxdb.BucketsResourceType,
}
h.HandlerFunc("GET", bucketsIDLabelsPath, newGetLabelsHandler(labelBackend))
h.HandlerFunc("POST", bucketsIDLabelsPath, newPostLabelHandler(labelBackend))
@ -298,12 +304,12 @@ func (h *BucketHandler) handlePostBucket(w http.ResponseWriter, r *http.Request)
req, err := decodePostBucketRequest(ctx, r)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
if err := h.BucketService.CreateBucket(ctx, req.Bucket); err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
@ -348,19 +354,19 @@ func (h *BucketHandler) handleGetBucket(w http.ResponseWriter, r *http.Request)
req, err := decodeGetBucketRequest(ctx, r)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
b, err := h.BucketService.FindBucketByID(ctx, req.BucketID)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
labels, err := h.LabelService.FindResourceLabels(ctx, influxdb.LabelMappingFilter{ResourceID: b.ID})
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
@ -401,12 +407,12 @@ func (h *BucketHandler) handleDeleteBucket(w http.ResponseWriter, r *http.Reques
req, err := decodeDeleteBucketRequest(ctx, r)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
if err := h.BucketService.DeleteBucket(ctx, req.BucketID); err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
@ -447,13 +453,13 @@ func (h *BucketHandler) handleGetBuckets(w http.ResponseWriter, r *http.Request)
req, err := decodeGetBucketsRequest(ctx, r)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
bs, _, err := h.BucketService.FindBuckets(ctx, req.filter, req.opts)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
@ -512,19 +518,19 @@ func (h *BucketHandler) handlePatchBucket(w http.ResponseWriter, r *http.Request
req, err := decodePatchBucketRequest(ctx, r)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
b, err := h.BucketService.UpdateBucket(ctx, req.BucketID, req.Update)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
labels, err := h.LabelService.FindResourceLabels(ctx, influxdb.LabelMappingFilter{ResourceID: b.ID})
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
@ -844,13 +850,13 @@ func (h *BucketHandler) handleGetBucketLog(w http.ResponseWriter, r *http.Reques
req, err := decodeGetBucketLogRequest(ctx, r)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
log, _, err := h.BucketOperationLogService.GetBucketOperationLog(ctx, req.BucketID, req.opts)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}

View File

@ -317,6 +317,7 @@ func TestService_handleGetBucket(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
bucketBackend := NewMockBucketBackend()
bucketBackend.HTTPErrorHandler = ErrorHandler(0)
bucketBackend.BucketService = tt.fields.BucketService
h := NewBucketHandler(bucketBackend)
@ -527,6 +528,7 @@ func TestService_handleDeleteBucket(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
bucketBackend := NewMockBucketBackend()
bucketBackend.HTTPErrorHandler = ErrorHandler(0)
bucketBackend.BucketService = tt.fields.BucketService
h := NewBucketHandler(bucketBackend)
@ -826,6 +828,7 @@ func TestService_handlePatchBucket(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
bucketBackend := NewMockBucketBackend()
bucketBackend.HTTPErrorHandler = ErrorHandler(0)
bucketBackend.BucketService = tt.fields.BucketService
h := NewBucketHandler(bucketBackend)
@ -1085,6 +1088,7 @@ func initBucketService(f platformtesting.BucketFields, t *testing.T) (platform.B
}
bucketBackend := NewMockBucketBackend()
bucketBackend.HTTPErrorHandler = ErrorHandler(0)
bucketBackend.BucketService = svc
bucketBackend.OrganizationService = svc
handler := NewBucketHandler(bucketBackend)

View File

@ -4,6 +4,7 @@ import (
"net/http"
"github.com/NYTimes/gziphandler"
"github.com/influxdata/influxdb"
"github.com/influxdata/influxdb/chronograf/server"
"github.com/julienschmidt/httprouter"
)
@ -15,9 +16,9 @@ type ChronografHandler struct {
}
// NewChronografHandler is the constructor an chronograf handler.
func NewChronografHandler(s *server.Service) *ChronografHandler {
func NewChronografHandler(s *server.Service, he influxdb.HTTPErrorHandler) *ChronografHandler {
h := &ChronografHandler{
Router: NewRouter(),
Router: NewRouter(he),
Service: s,
}
/* API */

View File

@ -16,6 +16,7 @@ import (
// DashboardBackend is all services and associated parameters required to construct
// the DashboardHandler.
type DashboardBackend struct {
platform.HTTPErrorHandler
Logger *zap.Logger
DashboardService platform.DashboardService
@ -28,7 +29,8 @@ type DashboardBackend struct {
// NewDashboardBackend creates a backend used by the dashboard handler.
func NewDashboardBackend(b *APIBackend) *DashboardBackend {
return &DashboardBackend{
Logger: b.Logger.With(zap.String("handler", "dashboard")),
HTTPErrorHandler: b.HTTPErrorHandler,
Logger: b.Logger.With(zap.String("handler", "dashboard")),
DashboardService: b.DashboardService,
DashboardOperationLogService: b.DashboardOperationLogService,
@ -42,6 +44,7 @@ func NewDashboardBackend(b *APIBackend) *DashboardBackend {
type DashboardHandler struct {
*httprouter.Router
platform.HTTPErrorHandler
Logger *zap.Logger
DashboardService platform.DashboardService
@ -69,8 +72,9 @@ const (
// NewDashboardHandler returns a new instance of DashboardHandler.
func NewDashboardHandler(b *DashboardBackend) *DashboardHandler {
h := &DashboardHandler{
Router: NewRouter(),
Logger: b.Logger,
Router: NewRouter(b.HTTPErrorHandler),
HTTPErrorHandler: b.HTTPErrorHandler,
Logger: b.Logger,
DashboardService: b.DashboardService,
DashboardOperationLogService: b.DashboardOperationLogService,
@ -95,6 +99,7 @@ func NewDashboardHandler(b *DashboardBackend) *DashboardHandler {
h.HandlerFunc("PATCH", dashboardsIDCellsIDViewPath, h.handlePatchDashboardCellView)
memberBackend := MemberBackend{
HTTPErrorHandler: b.HTTPErrorHandler,
Logger: b.Logger.With(zap.String("handler", "member")),
ResourceType: platform.DashboardsResourceType,
UserType: platform.Member,
@ -106,6 +111,7 @@ func NewDashboardHandler(b *DashboardBackend) *DashboardHandler {
h.HandlerFunc("DELETE", dashboardsIDMembersIDPath, newDeleteMemberHandler(memberBackend))
ownerBackend := MemberBackend{
HTTPErrorHandler: b.HTTPErrorHandler,
Logger: b.Logger.With(zap.String("handler", "member")),
ResourceType: platform.DashboardsResourceType,
UserType: platform.Owner,
@ -117,9 +123,10 @@ func NewDashboardHandler(b *DashboardBackend) *DashboardHandler {
h.HandlerFunc("DELETE", dashboardsIDOwnersIDPath, newDeleteMemberHandler(ownerBackend))
labelBackend := &LabelBackend{
Logger: b.Logger.With(zap.String("handler", "label")),
LabelService: b.LabelService,
ResourceType: platform.DashboardsResourceType,
HTTPErrorHandler: b.HTTPErrorHandler,
Logger: b.Logger.With(zap.String("handler", "label")),
LabelService: b.LabelService,
ResourceType: platform.DashboardsResourceType,
}
h.HandlerFunc("GET", dashboardsIDLabelsPath, newGetLabelsHandler(labelBackend))
h.HandlerFunc("POST", dashboardsIDLabelsPath, newPostLabelHandler(labelBackend))
@ -310,7 +317,7 @@ func (h *DashboardHandler) handleGetDashboards(w http.ResponseWriter, r *http.Re
ctx := r.Context()
req, err := decodeGetDashboardsRequest(ctx, r)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
@ -323,7 +330,7 @@ func (h *DashboardHandler) handleGetDashboards(w http.ResponseWriter, r *http.Re
mappings, _, err := h.UserResourceMappingService.FindUserResourceMappings(ctx, filter)
if err != nil {
EncodeError(ctx, &platform.Error{
h.HandleHTTPError(ctx, &platform.Error{
Code: platform.EInternal,
Msg: "Error loading dashboard owners",
Err: err,
@ -338,7 +345,7 @@ func (h *DashboardHandler) handleGetDashboards(w http.ResponseWriter, r *http.Re
dashboards, _, err := h.DashboardService.FindDashboards(ctx, req.filter, req.opts)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
@ -426,11 +433,11 @@ func (h *DashboardHandler) handlePostDashboard(w http.ResponseWriter, r *http.Re
req, err := decodePostDashboardRequest(ctx, r)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
if err := h.DashboardService.CreateDashboard(ctx, req.Dashboard); err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
@ -460,19 +467,19 @@ func (h *DashboardHandler) handleGetDashboard(w http.ResponseWriter, r *http.Req
req, err := decodeGetDashboardRequest(ctx, r)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
dashboard, err := h.DashboardService.FindDashboardByID(ctx, req.DashboardID)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
labels, err := h.LabelService.FindResourceLabels(ctx, platform.LabelMappingFilter{ResourceID: dashboard.ID})
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
@ -512,13 +519,13 @@ func (h *DashboardHandler) handleGetDashboardLog(w http.ResponseWriter, r *http.
req, err := decodeGetDashboardLogRequest(ctx, r)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
log, _, err := h.DashboardOperationLogService.GetDashboardOperationLog(ctx, req.DashboardID, req.opts)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
@ -565,12 +572,12 @@ func (h *DashboardHandler) handleDeleteDashboard(w http.ResponseWriter, r *http.
req, err := decodeDeleteDashboardRequest(ctx, r)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
if err := h.DashboardService.DeleteDashboard(ctx, req.DashboardID); err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
@ -607,18 +614,18 @@ func (h *DashboardHandler) handlePatchDashboard(w http.ResponseWriter, r *http.R
req, err := decodePatchDashboardRequest(ctx, r)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
dashboard, err := h.DashboardService.UpdateDashboard(ctx, req.DashboardID, req.Upd)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
labels, err := h.LabelService.FindResourceLabels(ctx, platform.LabelMappingFilter{ResourceID: dashboard.ID})
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
@ -723,7 +730,7 @@ func (h *DashboardHandler) handlePostDashboardCell(w http.ResponseWriter, r *htt
req, err := decodePostDashboardCellRequest(ctx, r)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
cell := new(platform.Cell)
@ -735,7 +742,7 @@ func (h *DashboardHandler) handlePostDashboardCell(w http.ResponseWriter, r *htt
// load the view
opts.View, err = h.DashboardService.GetDashboardCellView(ctx, req.dashboardID, *req.UsingView)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
}
@ -743,7 +750,7 @@ func (h *DashboardHandler) handlePostDashboardCell(w http.ResponseWriter, r *htt
opts.View.Name = *req.Name
}
} else if req.CellProperty == nil {
EncodeError(ctx, &platform.Error{
h.HandleHTTPError(ctx, &platform.Error{
Code: platform.EInvalid,
Msg: "req body is empty",
}, w)
@ -755,7 +762,7 @@ func (h *DashboardHandler) handlePostDashboardCell(w http.ResponseWriter, r *htt
}
if err := h.DashboardService.AddDashboardCell(ctx, req.dashboardID, cell, *opts); err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
@ -799,12 +806,12 @@ func (h *DashboardHandler) handlePutDashboardCells(w http.ResponseWriter, r *htt
req, err := decodePutDashboardCellRequest(ctx, r)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
if err := h.DashboardService.ReplaceDashboardCells(ctx, req.dashboardID, req.cells); err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
@ -881,13 +888,13 @@ func (h *DashboardHandler) handleGetDashboardCellView(w http.ResponseWriter, r *
req, err := decodeGetDashboardCellViewRequest(ctx, r)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
view, err := h.DashboardService.GetDashboardCellView(ctx, req.dashboardID, req.cellID)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
@ -935,13 +942,13 @@ func (h *DashboardHandler) handlePatchDashboardCellView(w http.ResponseWriter, r
req, err := decodePatchDashboardCellViewRequest(ctx, r)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
view, err := h.DashboardService.UpdateDashboardCellView(ctx, req.dashboardID, req.cellID, req.upd)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
@ -957,11 +964,11 @@ func (h *DashboardHandler) handleDeleteDashboardCell(w http.ResponseWriter, r *h
req, err := decodeDeleteDashboardCellRequest(ctx, r)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
if err := h.DashboardService.RemoveDashboardCell(ctx, req.dashboardID, req.cellID); err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
@ -1020,12 +1027,12 @@ func (h *DashboardHandler) handlePatchDashboardCell(w http.ResponseWriter, r *ht
req, err := decodePatchDashboardCellRequest(ctx, r)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
cell, err := h.DashboardService.UpdateDashboardCell(ctx, req.dashboardID, req.cellID, req.upd)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}

View File

@ -332,6 +332,7 @@ func TestService_handleGetDashboards(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
dashboardBackend := NewMockDashboardBackend()
dashboardBackend.HTTPErrorHandler = ErrorHandler(0)
dashboardBackend.LabelService = tt.fields.LabelService
dashboardBackend.DashboardService = tt.fields.DashboardService
h := NewDashboardHandler(dashboardBackend)
@ -487,6 +488,7 @@ func TestService_handleGetDashboard(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
dashboardBackend := NewMockDashboardBackend()
dashboardBackend.HTTPErrorHandler = ErrorHandler(0)
dashboardBackend.DashboardService = tt.fields.DashboardService
h := NewDashboardHandler(dashboardBackend)
@ -622,6 +624,7 @@ func TestService_handlePostDashboard(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
dashboardBackend := NewMockDashboardBackend()
dashboardBackend.HTTPErrorHandler = ErrorHandler(0)
dashboardBackend.DashboardService = tt.fields.DashboardService
h := NewDashboardHandler(dashboardBackend)
@ -717,6 +720,7 @@ func TestService_handleDeleteDashboard(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
dashboardBackend := NewMockDashboardBackend()
dashboardBackend.HTTPErrorHandler = ErrorHandler(0)
dashboardBackend.DashboardService = tt.fields.DashboardService
h := NewDashboardHandler(dashboardBackend)
@ -900,6 +904,7 @@ func TestService_handlePatchDashboard(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
dashboardBackend := NewMockDashboardBackend()
dashboardBackend.HTTPErrorHandler = ErrorHandler(0)
dashboardBackend.DashboardService = tt.fields.DashboardService
h := NewDashboardHandler(dashboardBackend)
@ -1080,6 +1085,7 @@ func TestService_handlePostDashboardCell(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
dashboardBackend := NewMockDashboardBackend()
dashboardBackend.HTTPErrorHandler = ErrorHandler(0)
dashboardBackend.DashboardService = tt.fields.DashboardService
h := NewDashboardHandler(dashboardBackend)
buf := new(bytes.Buffer)
@ -1163,6 +1169,7 @@ func TestService_handleDeleteDashboardCell(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
dashboardBackend := NewMockDashboardBackend()
dashboardBackend.HTTPErrorHandler = ErrorHandler(0)
dashboardBackend.DashboardService = tt.fields.DashboardService
h := NewDashboardHandler(dashboardBackend)
@ -1277,6 +1284,7 @@ func TestService_handlePatchDashboardCell(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
dashboardBackend := NewMockDashboardBackend()
dashboardBackend.HTTPErrorHandler = ErrorHandler(0)
dashboardBackend.DashboardService = tt.fields.DashboardService
h := NewDashboardHandler(dashboardBackend)
@ -1371,6 +1379,7 @@ func initDashboardService(f platformtesting.DashboardFields, t *testing.T) (plat
}
dashboardBackend := NewMockDashboardBackend()
dashboardBackend.HTTPErrorHandler = ErrorHandler(0)
dashboardBackend.DashboardService = svc
h := NewDashboardHandler(dashboardBackend)
server := httptest.NewServer(h)
@ -1455,6 +1464,7 @@ func TestService_handlePostDashboardLabel(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
dashboardBackend := NewMockDashboardBackend()
dashboardBackend.HTTPErrorHandler = ErrorHandler(0)
dashboardBackend.LabelService = tt.fields.LabelService
h := NewDashboardHandler(dashboardBackend)

View File

@ -16,6 +16,7 @@ import (
// the DocumentHandler.
type DocumentBackend struct {
Logger *zap.Logger
influxdb.HTTPErrorHandler
DocumentService influxdb.DocumentService
LabelService influxdb.LabelService
@ -24,9 +25,10 @@ type DocumentBackend struct {
// NewDocumentBackend returns a new instance of DocumentBackend.
func NewDocumentBackend(b *APIBackend) *DocumentBackend {
return &DocumentBackend{
Logger: b.Logger.With(zap.String("handler", "document")),
DocumentService: b.DocumentService,
LabelService: b.LabelService,
HTTPErrorHandler: b.HTTPErrorHandler,
Logger: b.Logger.With(zap.String("handler", "document")),
DocumentService: b.DocumentService,
LabelService: b.LabelService,
}
}
@ -35,6 +37,7 @@ type DocumentHandler struct {
*httprouter.Router
Logger *zap.Logger
influxdb.HTTPErrorHandler
DocumentService influxdb.DocumentService
LabelService influxdb.LabelService
@ -51,8 +54,9 @@ const (
// TODO(desa): this should probably take a namespace
func NewDocumentHandler(b *DocumentBackend) *DocumentHandler {
h := &DocumentHandler{
Router: NewRouter(),
Logger: b.Logger,
Router: NewRouter(b.HTTPErrorHandler),
HTTPErrorHandler: b.HTTPErrorHandler,
Logger: b.Logger,
DocumentService: b.DocumentService,
LabelService: b.LabelService,
@ -109,18 +113,18 @@ func (h *DocumentHandler) handlePostDocument(w http.ResponseWriter, r *http.Requ
req, err := decodePostDocumentRequest(ctx, r)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
s, err := h.DocumentService.FindDocumentStore(ctx, req.Namespace)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
a, err := pcontext.GetAuthorizer(ctx)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
@ -136,7 +140,7 @@ func (h *DocumentHandler) handlePostDocument(w http.ResponseWriter, r *http.Requ
}
if err := s.CreateDocument(ctx, req.Document, opts...); err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
@ -191,25 +195,25 @@ func (h *DocumentHandler) handleGetDocuments(w http.ResponseWriter, r *http.Requ
req, err := decodeGetDocumentsRequest(ctx, r)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
s, err := h.DocumentService.FindDocumentStore(ctx, req.Namespace)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
a, err := pcontext.GetAuthorizer(ctx)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
opts := []influxdb.DocumentFindOptions{influxdb.IncludeLabels}
if req.Org != "" && req.OrgID != nil {
EncodeError(ctx, &influxdb.Error{
h.HandleHTTPError(ctx, &influxdb.Error{
Code: influxdb.EInvalid,
Msg: "Please provide either org or orgID, not both",
}, w)
@ -224,7 +228,7 @@ func (h *DocumentHandler) handleGetDocuments(w http.ResponseWriter, r *http.Requ
ds, err := s.FindDocuments(ctx, opts...)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
@ -274,28 +278,28 @@ func (h *DocumentHandler) handlePostDocumentLabel(w http.ResponseWriter, r *http
ctx := r.Context()
_, _, err := h.getDocument(w, r)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
req, err := decodePostLabelMappingRequest(ctx, r, influxdb.DocumentsResourceType)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
if err := req.Mapping.Validate(); err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
if err := h.LabelService.CreateLabelMapping(ctx, &req.Mapping); err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
label, err := h.LabelService.FindLabelByID(ctx, req.Mapping.LabelID)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
if err := encodeResponse(ctx, w, http.StatusCreated, newLabelResponse(label)); err != nil {
@ -310,18 +314,18 @@ func (h *DocumentHandler) handleDeleteDocumentLabel(w http.ResponseWriter, r *ht
ctx := r.Context()
req, err := decodeDeleteLabelMappingRequest(ctx, r)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
_, _, err = h.getDocument(w, r)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
_, err = h.LabelService.FindLabelByID(ctx, req.LabelID)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
@ -333,7 +337,7 @@ func (h *DocumentHandler) handleDeleteDocumentLabel(w http.ResponseWriter, r *ht
// remove the label
if err := h.LabelService.DeleteLabelMapping(ctx, mapping); err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
@ -344,7 +348,7 @@ func (h *DocumentHandler) handleGetDocumentLabel(w http.ResponseWriter, r *http.
ctx := r.Context()
d, _, err := h.getDocument(w, r)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
if err := encodeResponse(ctx, w, http.StatusOK, newLabelsResponse(d.Labels)); err != nil {
@ -387,7 +391,7 @@ func (h *DocumentHandler) handleGetDocument(w http.ResponseWriter, r *http.Reque
ctx := r.Context()
d, namspace, err := h.getDocument(w, r)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
@ -440,24 +444,24 @@ func (h *DocumentHandler) handleDeleteDocument(w http.ResponseWriter, r *http.Re
req, err := decodeDeleteDocumentRequest(ctx, r)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
s, err := h.DocumentService.FindDocumentStore(ctx, req.Namespace)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
a, err := pcontext.GetAuthorizer(ctx)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
if err := s.DeleteDocuments(ctx, influxdb.AuthorizedWhereID(a, req.ID)); err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
@ -509,24 +513,24 @@ func (h *DocumentHandler) handlePutDocument(w http.ResponseWriter, r *http.Reque
req, err := decodePutDocumentRequest(ctx, r)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
s, err := h.DocumentService.FindDocumentStore(ctx, req.Namespace)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
a, err := pcontext.GetAuthorizer(ctx)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
if err := s.UpdateDocument(ctx, req.Document, influxdb.Authorized(a)); err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
@ -534,7 +538,7 @@ func (h *DocumentHandler) handlePutDocument(w http.ResponseWriter, r *http.Reque
ds, err := s.FindDocuments(ctx, influxdb.WhereID(req.Document.ID), influxdb.IncludeContent)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
@ -543,7 +547,7 @@ func (h *DocumentHandler) handlePutDocument(w http.ResponseWriter, r *http.Reque
Code: influxdb.EInternal,
Msg: fmt.Sprintf("found more than one document with id %s; please report this error", req.ID),
}
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}

View File

@ -291,6 +291,7 @@ func TestService_handleDeleteDocumentLabel(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
documentBackend := NewMockDocumentBackend()
documentBackend.HTTPErrorHandler = ErrorHandler(0)
documentBackend.DocumentService = tt.fields.DocumentService
documentBackend.LabelService = tt.fields.LabelService
h := NewDocumentHandler(documentBackend)
@ -476,6 +477,7 @@ func TestService_handlePostDocumentLabel(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
documentBackend := NewMockDocumentBackend()
documentBackend.HTTPErrorHandler = ErrorHandler(0)
documentBackend.DocumentService = tt.fields.DocumentService
documentBackend.LabelService = tt.fields.LabelService
h := NewDocumentHandler(documentBackend)
@ -580,6 +582,7 @@ func TestService_handleGetDocumentLabels(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
documentBackend := NewMockDocumentBackend()
documentBackend.HTTPErrorHandler = ErrorHandler(0)
documentBackend.DocumentService = tt.fields.DocumentService
documentBackend.LabelService = tt.fields.LabelService
h := NewDocumentHandler(documentBackend)
@ -703,6 +706,7 @@ func TestService_handleGetDocuments(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
documentBackend := NewMockDocumentBackend()
documentBackend.HTTPErrorHandler = ErrorHandler(0)
documentBackend.DocumentService = tt.fields.DocumentService
h := NewDocumentHandler(documentBackend)
r := httptest.NewRequest("GET", "http://any.url", nil)
@ -902,6 +906,7 @@ func TestService_handlePostDocuments(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
documentBackend := NewMockDocumentBackend()
documentBackend.HTTPErrorHandler = ErrorHandler(0)
documentBackend.DocumentService = tt.fields.DocumentService
documentBackend.LabelService = tt.fields.LabelService
h := NewDocumentHandler(documentBackend)

View File

@ -76,11 +76,14 @@ func CheckError(resp *http.Response) (err error) {
return pe
}
// EncodeError encodes err with the appropriate status code and format,
// ErrorHandler is the error handler in http package.
type ErrorHandler int
// HandleHTTPError encodes err with the appropriate status code and format,
// sets the X-Platform-Error-Code headers on the response.
// We're no longer using X-Influx-Error and X-Influx-Reference.
// and sets the response status to the corresponding status code.
func EncodeError(ctx context.Context, err error, w http.ResponseWriter) {
func (h ErrorHandler) HandleHTTPError(ctx context.Context, err error, w http.ResponseWriter) {
if err == nil {
return
}
@ -112,8 +115,8 @@ func EncodeError(ctx context.Context, err error, w http.ResponseWriter) {
}
// UnauthorizedError encodes a error message and status code for unauthorized access.
func UnauthorizedError(ctx context.Context, w http.ResponseWriter) {
EncodeError(ctx, &platform.Error{
func UnauthorizedError(ctx context.Context, h platform.HTTPErrorHandler, w http.ResponseWriter) {
h.HandleHTTPError(ctx, &platform.Error{
Code: platform.EUnauthorized,
Msg: "unauthorized access",
}, w)

View File

@ -15,7 +15,7 @@ func TestEncodeError(t *testing.T) {
w := httptest.NewRecorder()
http.EncodeError(ctx, nil, w)
http.ErrorHandler(0).HandleHTTPError(ctx, nil, w)
if w.Code != 200 {
t.Errorf("expected status code 200, got: %d", w.Code)
@ -28,7 +28,7 @@ func TestEncodeErrorWithError(t *testing.T) {
w := httptest.NewRecorder()
http.EncodeError(ctx, err, w)
http.ErrorHandler(0).HandleHTTPError(ctx, err, w)
if w.Code != 500 {
t.Errorf("expected status code 500, got: %d", w.Code)

View File

@ -10,14 +10,14 @@ import (
"go.uber.org/zap"
influxdb "github.com/influxdata/influxdb"
"github.com/influxdata/influxdb"
"github.com/julienschmidt/httprouter"
)
// LabelHandler represents an HTTP API handler for labels
type LabelHandler struct {
*httprouter.Router
influxdb.HTTPErrorHandler
Logger *zap.Logger
LabelService influxdb.LabelService
@ -29,11 +29,12 @@ const (
)
// NewLabelHandler returns a new instance of LabelHandler
func NewLabelHandler(s influxdb.LabelService) *LabelHandler {
func NewLabelHandler(s influxdb.LabelService, he influxdb.HTTPErrorHandler) *LabelHandler {
h := &LabelHandler{
Router: NewRouter(),
Logger: zap.NewNop(),
LabelService: s,
Router: NewRouter(he),
HTTPErrorHandler: he,
Logger: zap.NewNop(),
LabelService: s,
}
h.HandlerFunc("POST", labelsPath, h.handlePostLabel)
@ -52,12 +53,12 @@ func (h *LabelHandler) handlePostLabel(w http.ResponseWriter, r *http.Request) {
req, err := decodePostLabelRequest(ctx, r)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
if err := h.LabelService.CreateLabel(ctx, req.Label); err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
@ -111,19 +112,19 @@ func (h *LabelHandler) handleGetLabels(w http.ResponseWriter, r *http.Request) {
req, err := decodeGetLabelsRequest(ctx, r)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
labels, err := h.LabelService.FindLabels(ctx, req.filter)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
err = encodeResponse(ctx, w, http.StatusOK, newLabelsResponse(labels))
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
}
@ -153,13 +154,13 @@ func (h *LabelHandler) handleGetLabel(w http.ResponseWriter, r *http.Request) {
req, err := decodeGetLabelRequest(ctx, r)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
l, err := h.LabelService.FindLabelByID(ctx, req.LabelID)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
@ -200,12 +201,12 @@ func (h *LabelHandler) handleDeleteLabel(w http.ResponseWriter, r *http.Request)
req, err := decodeDeleteLabelRequest(ctx, r)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
if err := h.LabelService.DeleteLabel(ctx, req.LabelID); err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
@ -243,13 +244,13 @@ func (h *LabelHandler) handlePatchLabel(w http.ResponseWriter, r *http.Request)
req, err := decodePatchLabelRequest(ctx, r)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
l, err := h.LabelService.UpdateLabel(ctx, req.LabelID, req.Update)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
@ -330,7 +331,8 @@ func newLabelsResponse(ls []*influxdb.Label) *labelsResponse {
// LabelBackend is all services and associated parameters required to construct
// label handlers.
type LabelBackend struct {
Logger *zap.Logger
Logger *zap.Logger
influxdb.HTTPErrorHandler
LabelService influxdb.LabelService
ResourceType influxdb.ResourceType
}
@ -342,13 +344,13 @@ func newGetLabelsHandler(b *LabelBackend) http.HandlerFunc {
req, err := decodeGetLabelMappingsRequest(ctx, r, b.ResourceType)
if err != nil {
EncodeError(ctx, err, w)
b.HandleHTTPError(ctx, err, w)
return
}
labels, err := b.LabelService.FindResourceLabels(ctx, req.filter)
if err != nil {
EncodeError(ctx, err, w)
b.HandleHTTPError(ctx, err, w)
return
}
@ -392,23 +394,23 @@ func newPostLabelHandler(b *LabelBackend) http.HandlerFunc {
req, err := decodePostLabelMappingRequest(ctx, r, b.ResourceType)
if err != nil {
EncodeError(ctx, err, w)
b.HandleHTTPError(ctx, err, w)
return
}
if err := req.Mapping.Validate(); err != nil {
EncodeError(ctx, err, w)
b.HandleHTTPError(ctx, err, w)
return
}
if err := b.LabelService.CreateLabelMapping(ctx, &req.Mapping); err != nil {
EncodeError(ctx, err, w)
b.HandleHTTPError(ctx, err, w)
return
}
label, err := b.LabelService.FindLabelByID(ctx, req.Mapping.LabelID)
if err != nil {
EncodeError(ctx, err, w)
b.HandleHTTPError(ctx, err, w)
return
}
@ -467,7 +469,7 @@ func newDeleteLabelHandler(b *LabelBackend) http.HandlerFunc {
req, err := decodeDeleteLabelMappingRequest(ctx, r)
if err != nil {
EncodeError(ctx, err, w)
b.HandleHTTPError(ctx, err, w)
return
}
@ -478,7 +480,7 @@ func newDeleteLabelHandler(b *LabelBackend) http.HandlerFunc {
}
if err := b.LabelService.DeleteLabelMapping(ctx, mapping); err != nil {
EncodeError(ctx, err, w)
b.HandleHTTPError(ctx, err, w)
return
}

View File

@ -108,7 +108,7 @@ func TestService_handleGetLabels(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
h := NewLabelHandler(tt.fields.LabelService)
h := NewLabelHandler(tt.fields.LabelService, ErrorHandler(0))
r := httptest.NewRequest("GET", "http://any.url", nil)
@ -216,7 +216,7 @@ func TestService_handleGetLabel(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
h := NewLabelHandler(tt.fields.LabelService)
h := NewLabelHandler(tt.fields.LabelService, ErrorHandler(0))
r := httptest.NewRequest("GET", "http://any.url", nil)
@ -311,7 +311,7 @@ func TestService_handlePostLabel(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
h := NewLabelHandler(tt.fields.LabelService)
h := NewLabelHandler(tt.fields.LabelService, ErrorHandler(0))
l, err := json.Marshal(tt.args.label)
if err != nil {
@ -402,7 +402,7 @@ func TestService_handleDeleteLabel(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
h := NewLabelHandler(tt.fields.LabelService)
h := NewLabelHandler(tt.fields.LabelService, ErrorHandler(0))
r := httptest.NewRequest("GET", "http://any.url", nil)
@ -541,7 +541,7 @@ func TestService_handlePatchLabel(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
h := NewLabelHandler(tt.fields.LabelService)
h := NewLabelHandler(tt.fields.LabelService, ErrorHandler(0))
upd := platform.LabelUpdate{}
if len(tt.args.properties) > 0 {

View File

@ -14,6 +14,7 @@ import (
// SetupBackend is all services and associated parameters required to construct
// the SetupHandler.
type SetupBackend struct {
platform.HTTPErrorHandler
Logger *zap.Logger
OnboardingService platform.OnboardingService
}
@ -21,6 +22,7 @@ type SetupBackend struct {
// NewSetupBackend returns a new instance of SetupBackend.
func NewSetupBackend(b *APIBackend) *SetupBackend {
return &SetupBackend{
HTTPErrorHandler: b.HTTPErrorHandler,
Logger: b.Logger.With(zap.String("handler", "setup")),
OnboardingService: b.OnboardingService,
}
@ -29,7 +31,7 @@ func NewSetupBackend(b *APIBackend) *SetupBackend {
// SetupHandler represents an HTTP API handler for onboarding setup.
type SetupHandler struct {
*httprouter.Router
platform.HTTPErrorHandler
Logger *zap.Logger
OnboardingService platform.OnboardingService
@ -42,7 +44,8 @@ const (
// NewSetupHandler returns a new instance of SetupHandler.
func NewSetupHandler(b *SetupBackend) *SetupHandler {
h := &SetupHandler{
Router: NewRouter(),
Router: NewRouter(b.HTTPErrorHandler),
HTTPErrorHandler: b.HTTPErrorHandler,
Logger: b.Logger,
OnboardingService: b.OnboardingService,
}
@ -60,7 +63,7 @@ func (h *SetupHandler) isOnboarding(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
result, err := h.OnboardingService.IsOnboarding(ctx)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
if err := encodeResponse(ctx, w, http.StatusOK, isOnboardingResponse{result}); err != nil {
@ -75,12 +78,12 @@ func (h *SetupHandler) handlePostSetup(w http.ResponseWriter, r *http.Request) {
req, err := decodePostSetupRequest(ctx, r)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
results, err := h.OnboardingService.Generate(ctx, req)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
if err := encodeResponse(ctx, w, http.StatusCreated, newOnboardingResponse(results)); err != nil {

View File

@ -37,6 +37,7 @@ func initOnboardingService(f platformtesting.OnboardingFields, t *testing.T) (pl
}
setupBackend := NewMockSetupBackend()
setupBackend.HTTPErrorHandler = ErrorHandler(0)
setupBackend.OnboardingService = svc
handler := NewSetupHandler(setupBackend)
server := httptest.NewServer(handler)

View File

@ -18,6 +18,7 @@ import (
// OrgBackend is all services and associated parameters required to construct
// the OrgHandler.
type OrgBackend struct {
influxdb.HTTPErrorHandler
Logger *zap.Logger
OrganizationService influxdb.OrganizationService
@ -31,7 +32,8 @@ type OrgBackend struct {
// NewOrgBackend is a datasource used by the org handler.
func NewOrgBackend(b *APIBackend) *OrgBackend {
return &OrgBackend{
Logger: b.Logger.With(zap.String("handler", "org")),
HTTPErrorHandler: b.HTTPErrorHandler,
Logger: b.Logger.With(zap.String("handler", "org")),
OrganizationService: b.OrganizationService,
OrganizationOperationLogService: b.OrganizationOperationLogService,
@ -45,7 +47,7 @@ func NewOrgBackend(b *APIBackend) *OrgBackend {
// OrgHandler represents an HTTP API handler for orgs.
type OrgHandler struct {
*httprouter.Router
influxdb.HTTPErrorHandler
Logger *zap.Logger
OrganizationService influxdb.OrganizationService
@ -74,8 +76,9 @@ const (
// NewOrgHandler returns a new instance of OrgHandler.
func NewOrgHandler(b *OrgBackend) *OrgHandler {
h := &OrgHandler{
Router: NewRouter(),
Logger: zap.NewNop(),
Router: NewRouter(b.HTTPErrorHandler),
HTTPErrorHandler: b.HTTPErrorHandler,
Logger: zap.NewNop(),
OrganizationService: b.OrganizationService,
OrganizationOperationLogService: b.OrganizationOperationLogService,
@ -93,6 +96,7 @@ func NewOrgHandler(b *OrgBackend) *OrgHandler {
h.HandlerFunc("DELETE", organizationsIDPath, h.handleDeleteOrg)
memberBackend := MemberBackend{
HTTPErrorHandler: b.HTTPErrorHandler,
Logger: b.Logger.With(zap.String("handler", "member")),
ResourceType: influxdb.OrgsResourceType,
UserType: influxdb.Member,
@ -104,6 +108,7 @@ func NewOrgHandler(b *OrgBackend) *OrgHandler {
h.HandlerFunc("DELETE", organizationsIDMembersIDPath, newDeleteMemberHandler(memberBackend))
ownerBackend := MemberBackend{
HTTPErrorHandler: b.HTTPErrorHandler,
Logger: b.Logger.With(zap.String("handler", "member")),
ResourceType: influxdb.OrgsResourceType,
UserType: influxdb.Owner,
@ -120,9 +125,10 @@ func NewOrgHandler(b *OrgBackend) *OrgHandler {
h.HandlerFunc("POST", organizationsIDSecretsDeletePath, h.handleDeleteSecrets)
labelBackend := &LabelBackend{
Logger: b.Logger.With(zap.String("handler", "label")),
LabelService: b.LabelService,
ResourceType: influxdb.OrgsResourceType,
HTTPErrorHandler: b.HTTPErrorHandler,
Logger: b.Logger.With(zap.String("handler", "label")),
LabelService: b.LabelService,
ResourceType: influxdb.OrgsResourceType,
}
h.HandlerFunc("GET", organizationsIDLabelsPath, newGetLabelsHandler(labelBackend))
h.HandlerFunc("POST", organizationsIDLabelsPath, newPostLabelHandler(labelBackend))
@ -200,12 +206,12 @@ func (h *OrgHandler) handlePostOrg(w http.ResponseWriter, r *http.Request) {
req, err := decodePostOrgRequest(ctx, r)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
if err := h.OrganizationService.CreateOrganization(ctx, req.Org); err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
@ -236,13 +242,13 @@ func (h *OrgHandler) handleGetOrg(w http.ResponseWriter, r *http.Request) {
req, err := decodeGetOrgRequest(ctx, r)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
b, err := h.OrganizationService.FindOrganizationByID(ctx, req.OrgID)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
@ -284,13 +290,13 @@ func (h *OrgHandler) handleGetOrgs(w http.ResponseWriter, r *http.Request) {
req, err := decodeGetOrgsRequest(ctx, r)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
orgs, _, err := h.OrganizationService.FindOrganizations(ctx, req.filter)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
@ -329,12 +335,12 @@ func (h *OrgHandler) handleDeleteOrg(w http.ResponseWriter, r *http.Request) {
req, err := decodeDeleteOrganizationRequest(ctx, r)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
if err := h.OrganizationService.DeleteOrganization(ctx, req.OrganizationID); err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
@ -376,13 +382,13 @@ func (h *OrgHandler) handlePatchOrg(w http.ResponseWriter, r *http.Request) {
req, err := decodePatchOrgRequest(ctx, r)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
o, err := h.OrganizationService.UpdateOrganization(ctx, req.OrgID, req.Update)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
@ -429,13 +435,13 @@ func (h *OrgHandler) handleGetSecrets(w http.ResponseWriter, r *http.Request) {
req, err := decodeGetSecretsRequest(ctx, r)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
ks, err := h.SecretService.GetSecretKeys(ctx, req.orgID)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
@ -475,12 +481,12 @@ func (h *OrgHandler) handlePatchSecrets(w http.ResponseWriter, r *http.Request)
req, err := decodePatchSecretsRequest(ctx, r)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
if err := h.SecretService.PatchSecrets(ctx, req.orgID, req.secrets); err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
@ -523,12 +529,12 @@ func (h *OrgHandler) handleDeleteSecrets(w http.ResponseWriter, r *http.Request)
req, err := decodeDeleteSecretsRequest(ctx, r)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
if err := h.SecretService.DeleteSecret(ctx, req.orgID, req.Secrets...); err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
@ -818,13 +824,13 @@ func (h *OrgHandler) handleGetOrgLog(w http.ResponseWriter, r *http.Request) {
req, err := decodeGetOrganizationLogRequest(ctx, r)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
log, _, err := h.OrganizationOperationLogService.GetOrganizationOperationLog(ctx, req.OrganizationID, req.opts)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}

View File

@ -49,6 +49,7 @@ func initOrganizationService(f platformtesting.OrganizationFields, t *testing.T)
}
orgBackend := NewMockOrgBackend()
orgBackend.HTTPErrorHandler = ErrorHandler(0)
orgBackend.OrganizationService = svc
handler := NewOrgHandler(orgBackend)
server := httptest.NewServer(handler)
@ -144,6 +145,7 @@ func TestSecretService_handleGetSecrets(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
orgBackend := NewMockOrgBackend()
orgBackend.HTTPErrorHandler = ErrorHandler(0)
orgBackend.SecretService = tt.fields.SecretService
h := NewOrgHandler(orgBackend)
@ -219,6 +221,7 @@ func TestSecretService_handlePatchSecrets(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
orgBackend := NewMockOrgBackend()
orgBackend.HTTPErrorHandler = ErrorHandler(0)
orgBackend.SecretService = tt.fields.SecretService
h := NewOrgHandler(orgBackend)
@ -300,6 +303,7 @@ func TestSecretService_handleDeleteSecrets(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
orgBackend := NewMockOrgBackend()
orgBackend.HTTPErrorHandler = ErrorHandler(0)
orgBackend.SecretService = tt.fields.SecretService
h := NewOrgHandler(orgBackend)

View File

@ -24,7 +24,7 @@ func setCORSResponseHeaders(w http.ResponseWriter, r *http.Request) {
// NewPlatformHandler returns a platform handler that serves the API and associated assets.
func NewPlatformHandler(b *APIBackend) *PlatformHandler {
h := NewAuthenticationHandler()
h := NewAuthenticationHandler(b.HTTPErrorHandler)
h.Handler = NewAPIHandler(b)
h.AuthorizationService = b.AuthorizationService
h.SessionService = b.SessionService

View File

@ -37,6 +37,7 @@ const (
// FluxBackend is all services and associated parameters required to construct
// the FluxHandler.
type FluxBackend struct {
platform.HTTPErrorHandler
Logger *zap.Logger
QueryEventRecorder metric.EventRecorder
@ -47,6 +48,7 @@ type FluxBackend struct {
// NewFluxBackend returns a new instance of FluxBackend.
func NewFluxBackend(b *APIBackend) *FluxBackend {
return &FluxBackend{
HTTPErrorHandler: b.HTTPErrorHandler,
Logger: b.Logger.With(zap.String("handler", "query")),
QueryEventRecorder: b.QueryEventRecorder,
@ -63,7 +65,7 @@ type HTTPDialect interface {
// FluxHandler implements handling flux queries.
type FluxHandler struct {
*httprouter.Router
platform.HTTPErrorHandler
Logger *zap.Logger
Now func() time.Time
@ -76,9 +78,10 @@ type FluxHandler struct {
// NewFluxHandler returns a new handler at /api/v2/query for flux queries.
func NewFluxHandler(b *FluxBackend) *FluxHandler {
h := &FluxHandler{
Router: NewRouter(),
Now: time.Now,
Logger: b.Logger,
Router: NewRouter(b.HTTPErrorHandler),
Now: time.Now,
HTTPErrorHandler: b.HTTPErrorHandler,
Logger: b.Logger,
ProxyQueryService: b.ProxyQueryService,
OrganizationService: b.OrganizationService,
@ -124,7 +127,7 @@ func (h *FluxHandler) handleQuery(w http.ResponseWriter, r *http.Request) {
Op: op,
Err: err,
}
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
@ -136,7 +139,7 @@ func (h *FluxHandler) handleQuery(w http.ResponseWriter, r *http.Request) {
Op: op,
Err: err,
}
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
orgID = req.Request.OrganizationID
@ -152,7 +155,7 @@ func (h *FluxHandler) handleQuery(w http.ResponseWriter, r *http.Request) {
Msg: fmt.Sprintf("unsupported dialect over HTTP: %T", req.Dialect),
Op: op,
}
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
hd.SetHeaders(w)
@ -167,7 +170,7 @@ func (h *FluxHandler) handleQuery(w http.ResponseWriter, r *http.Request) {
Op: op,
Err: err,
}
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
h.Logger.Info("Error writing response to client",
@ -195,7 +198,7 @@ func (h *FluxHandler) postFluxAST(w http.ResponseWriter, r *http.Request) {
err := json.NewDecoder(r.Body).Decode(&request)
if err != nil {
EncodeError(ctx, &platform.Error{
h.HandleHTTPError(ctx, &platform.Error{
Code: platform.EInvalid,
Msg: "invalid json",
Err: err,
@ -206,7 +209,7 @@ func (h *FluxHandler) postFluxAST(w http.ResponseWriter, r *http.Request) {
pkg := parser.ParseSource(request.Query)
if ast.Check(pkg) > 0 {
err := ast.GetError(pkg)
EncodeError(ctx, &platform.Error{
h.HandleHTTPError(ctx, &platform.Error{
Code: platform.EInvalid,
Msg: "invalid AST",
Err: err,
@ -233,7 +236,7 @@ func (h *FluxHandler) postQueryAnalyze(w http.ResponseWriter, r *http.Request) {
var req QueryRequest
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
EncodeError(ctx, &platform.Error{
h.HandleHTTPError(ctx, &platform.Error{
Code: platform.EInvalid,
Msg: "invalid json",
Err: err,
@ -243,7 +246,7 @@ func (h *FluxHandler) postQueryAnalyze(w http.ResponseWriter, r *http.Request) {
a, err := req.Analyze()
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
if err := encodeResponse(ctx, w, http.StatusOK, a); err != nil {
@ -278,7 +281,7 @@ func (h *FluxHandler) getFluxSuggestions(w http.ResponseWriter, r *http.Request)
for _, name := range names {
suggestion, err := completer.FunctionSuggestion(name)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
@ -315,7 +318,7 @@ func (h *FluxHandler) getFluxSuggestion(w http.ResponseWriter, r *http.Request)
suggestion, err := completer.FunctionSuggestion(name)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}

View File

@ -229,7 +229,9 @@ func TestFluxHandler_postFluxAST(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
h := &FluxHandler{}
h := &FluxHandler{
HTTPErrorHandler: ErrorHandler(0),
}
h.postFluxAST(tt.w, tt.r)
if got := tt.w.Body.String(); got != tt.want {
t.Errorf("http.postFluxAST = got\n%vwant\n%v", got, tt.want)
@ -293,6 +295,7 @@ var _ metric.EventRecorder = noopEventRecorder{}
func TestFluxHandler_PostQuery_Errors(t *testing.T) {
i := inmem.NewService()
b := &FluxBackend{
HTTPErrorHandler: ErrorHandler(0),
Logger: zaptest.NewLogger(t),
QueryEventRecorder: noopEventRecorder{},
OrganizationService: i,

View File

@ -15,27 +15,32 @@ import (
)
// NewRouter returns a new router with a 404 handler, a 405 handler, and a panic handler.
func NewRouter() *httprouter.Router {
func NewRouter(h platform.HTTPErrorHandler) *httprouter.Router {
b := baseHandler{HTTPErrorHandler: h}
router := httprouter.New()
router.NotFound = http.HandlerFunc(notFoundHandler)
router.MethodNotAllowed = http.HandlerFunc(methodNotAllowedHandler)
router.PanicHandler = panicHandler
router.NotFound = http.HandlerFunc(b.notFound)
router.MethodNotAllowed = http.HandlerFunc(b.methodNotAllowed)
router.PanicHandler = b.panic
return router
}
// notFoundHandler represents a 404 handler that return a JSON response.
func notFoundHandler(w http.ResponseWriter, r *http.Request) {
type baseHandler struct {
platform.HTTPErrorHandler
}
// notFound represents a 404 handler that return a JSON response.
func (h baseHandler) notFound(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
pe := &platform.Error{
Code: platform.ENotFound,
Msg: "path not found",
}
EncodeError(ctx, pe, w)
h.HandleHTTPError(ctx, pe, w)
}
// methodNotAllowedHandler represents a 405 handler that return a JSON response.
func methodNotAllowedHandler(w http.ResponseWriter, r *http.Request) {
// methodNotAllowed represents a 405 handler that return a JSON response.
func (h baseHandler) methodNotAllowed(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
allow := w.Header().Get("Allow")
pe := &platform.Error{
@ -43,12 +48,12 @@ func methodNotAllowedHandler(w http.ResponseWriter, r *http.Request) {
Msg: fmt.Sprintf("allow: %s", allow),
}
EncodeError(ctx, pe, w)
h.HandleHTTPError(ctx, pe, w)
}
// panicHandler handles panics recovered from http handlers.
// panic handles panics recovered from http handlers.
// It returns a json response with http status code 500 and the recovered error message.
func panicHandler(w http.ResponseWriter, r *http.Request, rcv interface{}) {
func (h baseHandler) panic(w http.ResponseWriter, r *http.Request, rcv interface{}) {
ctx := r.Context()
pe := &platform.Error{
Code: platform.EInternal,
@ -62,7 +67,7 @@ func panicHandler(w http.ResponseWriter, r *http.Request, rcv interface{}) {
entry.Write(zap.Error(pe.Err))
}
EncodeError(ctx, pe, w)
h.HandleHTTPError(ctx, pe, w)
}
var panicLogger *zap.Logger

View File

@ -82,7 +82,7 @@ func TestRouter_NotFound(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
router := NewRouter()
router := NewRouter(ErrorHandler(0))
router.HandlerFunc(tt.fields.method, tt.fields.path, tt.fields.handlerFn)
r := httptest.NewRequest(tt.args.method, tt.args.path, nil)
@ -190,7 +190,7 @@ func TestRouter_Panic(t *testing.T) {
tw := newTestLogWriter(t)
panicLogger = zaptest.NewLogger(tw)
router := NewRouter()
router := NewRouter(ErrorHandler(0))
router.HandlerFunc(tt.fields.method, tt.fields.path, tt.fields.handlerFn)
r := httptest.NewRequest(tt.args.method, tt.args.path, nil)
@ -289,7 +289,7 @@ func TestRouter_MethodNotAllowed(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
router := NewRouter()
router := NewRouter(ErrorHandler(0))
router.HandlerFunc(tt.fields.method, tt.fields.path, tt.fields.handlerFn)
r := httptest.NewRequest(tt.args.method, tt.args.path, nil)

View File

@ -17,6 +17,7 @@ import (
// ScraperBackend is all services and associated parameters required to construct
// the ScraperHandler.
type ScraperBackend struct {
influxdb.HTTPErrorHandler
Logger *zap.Logger
ScraperStorageService influxdb.ScraperTargetStoreService
@ -30,7 +31,8 @@ type ScraperBackend struct {
// NewScraperBackend returns a new instance of ScraperBackend.
func NewScraperBackend(b *APIBackend) *ScraperBackend {
return &ScraperBackend{
Logger: b.Logger.With(zap.String("handler", "scraper")),
HTTPErrorHandler: b.HTTPErrorHandler,
Logger: b.Logger.With(zap.String("handler", "scraper")),
ScraperStorageService: b.ScraperTargetStoreService,
BucketService: b.BucketService,
@ -44,6 +46,7 @@ func NewScraperBackend(b *APIBackend) *ScraperBackend {
// ScraperHandler represents an HTTP API handler for scraper targets.
type ScraperHandler struct {
*httprouter.Router
influxdb.HTTPErrorHandler
Logger *zap.Logger
UserService influxdb.UserService
UserResourceMappingService influxdb.UserResourceMappingService
@ -66,7 +69,8 @@ const (
// NewScraperHandler returns a new instance of ScraperHandler.
func NewScraperHandler(b *ScraperBackend) *ScraperHandler {
h := &ScraperHandler{
Router: NewRouter(),
Router: NewRouter(b.HTTPErrorHandler),
HTTPErrorHandler: b.HTTPErrorHandler,
Logger: b.Logger,
UserService: b.UserService,
UserResourceMappingService: b.UserResourceMappingService,
@ -82,6 +86,7 @@ func NewScraperHandler(b *ScraperBackend) *ScraperHandler {
h.HandlerFunc("DELETE", targetsPath+"/:id", h.handleDeleteScraperTarget)
memberBackend := MemberBackend{
HTTPErrorHandler: b.HTTPErrorHandler,
Logger: b.Logger.With(zap.String("handler", "member")),
ResourceType: influxdb.ScraperResourceType,
UserType: influxdb.Member,
@ -93,6 +98,7 @@ func NewScraperHandler(b *ScraperBackend) *ScraperHandler {
h.HandlerFunc("DELETE", targetsIDMembersIDPath, newDeleteMemberHandler(memberBackend))
ownerBackend := MemberBackend{
HTTPErrorHandler: b.HTTPErrorHandler,
Logger: b.Logger.With(zap.String("handler", "member")),
ResourceType: influxdb.ScraperResourceType,
UserType: influxdb.Owner,
@ -104,9 +110,10 @@ func NewScraperHandler(b *ScraperBackend) *ScraperHandler {
h.HandlerFunc("DELETE", targetsIDOwnersIDPath, newDeleteMemberHandler(ownerBackend))
labelBackend := &LabelBackend{
Logger: b.Logger.With(zap.String("handler", "label")),
LabelService: b.LabelService,
ResourceType: influxdb.ScraperResourceType,
HTTPErrorHandler: b.HTTPErrorHandler,
Logger: b.Logger.With(zap.String("handler", "label")),
LabelService: b.LabelService,
ResourceType: influxdb.ScraperResourceType,
}
h.HandlerFunc("GET", targetsIDLabelsPath, newGetLabelsHandler(labelBackend))
h.HandlerFunc("POST", targetsIDLabelsPath, newPostLabelHandler(labelBackend))
@ -120,23 +127,23 @@ func (h *ScraperHandler) handlePostScraperTarget(w http.ResponseWriter, r *http.
ctx := r.Context()
req, err := decodeScraperTargetAddRequest(ctx, r)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
auth, err := pctx.GetAuthorizer(ctx)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
if err := h.ScraperStorageService.AddTarget(ctx, req, auth.GetUserID()); err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
resp, err := h.newTargetResponse(ctx, *req)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
if err := encodeResponse(ctx, w, http.StatusCreated, resp); err != nil {
@ -151,12 +158,12 @@ func (h *ScraperHandler) handleDeleteScraperTarget(w http.ResponseWriter, r *htt
id, err := decodeScraperTargetIDRequest(ctx, r)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
if err := h.ScraperStorageService.RemoveTarget(ctx, *id); err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
@ -169,25 +176,25 @@ func (h *ScraperHandler) handlePatchScraperTarget(w http.ResponseWriter, r *http
update, err := decodeScraperTargetUpdateRequest(ctx, r)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
auth, err := pctx.GetAuthorizer(ctx)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
target, err := h.ScraperStorageService.UpdateTarget(ctx, update, auth.GetUserID())
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
resp, err := h.newTargetResponse(ctx, *target)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
@ -202,18 +209,18 @@ func (h *ScraperHandler) handleGetScraperTarget(w http.ResponseWriter, r *http.R
id, err := decodeScraperTargetIDRequest(ctx, r)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
target, err := h.ScraperStorageService.GetTargetByID(ctx, *id)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
resp, err := h.newTargetResponse(ctx, *target)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
@ -263,18 +270,18 @@ func (h *ScraperHandler) handleGetScraperTargets(w http.ResponseWriter, r *http.
ctx := r.Context()
req, err := decodeScraperTargetsRequest(ctx, r)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
targets, err := h.ScraperStorageService.ListTargets(ctx, req.filter)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
resp, err := h.newListTargetsResponse(ctx, targets)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}

View File

@ -207,6 +207,7 @@ func TestService_handleGetScraperTargets(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
scraperBackend := NewMockScraperBackend()
scraperBackend.HTTPErrorHandler = ErrorHandler(0)
scraperBackend.ScraperStorageService = tt.fields.ScraperTargetStoreService
scraperBackend.OrganizationService = tt.fields.OrganizationService
scraperBackend.BucketService = tt.fields.BucketService
@ -343,6 +344,7 @@ func TestService_handleGetScraperTarget(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
scraperBackend := NewMockScraperBackend()
scraperBackend.HTTPErrorHandler = ErrorHandler(0)
scraperBackend.ScraperStorageService = tt.fields.ScraperTargetStoreService
scraperBackend.OrganizationService = tt.fields.OrganizationService
scraperBackend.BucketService = tt.fields.BucketService
@ -450,6 +452,7 @@ func TestService_handleDeleteScraperTarget(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
scraperBackend := NewMockScraperBackend()
scraperBackend.HTTPErrorHandler = ErrorHandler(0)
scraperBackend.ScraperStorageService = tt.fields.Service
h := NewScraperHandler(scraperBackend)
@ -580,6 +583,7 @@ func TestService_handlePostScraperTarget(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
scraperBackend := NewMockScraperBackend()
scraperBackend.HTTPErrorHandler = ErrorHandler(0)
scraperBackend.ScraperStorageService = tt.fields.ScraperTargetStoreService
scraperBackend.OrganizationService = tt.fields.OrganizationService
scraperBackend.BucketService = tt.fields.BucketService
@ -757,6 +761,7 @@ func TestService_handlePatchScraperTarget(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
scraperBackend := NewMockScraperBackend()
scraperBackend.HTTPErrorHandler = ErrorHandler(0)
scraperBackend.ScraperStorageService = tt.fields.ScraperTargetStoreService
scraperBackend.OrganizationService = tt.fields.OrganizationService
scraperBackend.BucketService = tt.fields.BucketService
@ -832,6 +837,7 @@ func initScraperService(f platformtesting.TargetFields, t *testing.T) (influxdb.
}
scraperBackend := NewMockScraperBackend()
scraperBackend.HTTPErrorHandler = ErrorHandler(0)
scraperBackend.ScraperStorageService = svc
scraperBackend.OrganizationService = svc
scraperBackend.BucketService = &mock.BucketService{

View File

@ -13,6 +13,7 @@ import (
// the SessionHandler.
type SessionBackend struct {
Logger *zap.Logger
platform.HTTPErrorHandler
PasswordsService platform.PasswordsService
SessionService platform.SessionService
@ -21,7 +22,8 @@ type SessionBackend struct {
// NewSessionBackend creates a new SessionBackend with associated logger.
func NewSessionBackend(b *APIBackend) *SessionBackend {
return &SessionBackend{
Logger: b.Logger.With(zap.String("handler", "session")),
HTTPErrorHandler: b.HTTPErrorHandler,
Logger: b.Logger.With(zap.String("handler", "session")),
PasswordsService: b.PasswordsService,
SessionService: b.SessionService,
@ -31,6 +33,7 @@ func NewSessionBackend(b *APIBackend) *SessionBackend {
// SessionHandler represents an HTTP API handler for authorizations.
type SessionHandler struct {
*httprouter.Router
platform.HTTPErrorHandler
Logger *zap.Logger
PasswordsService platform.PasswordsService
@ -40,8 +43,9 @@ type SessionHandler struct {
// NewSessionHandler returns a new instance of SessionHandler.
func NewSessionHandler(b *SessionBackend) *SessionHandler {
h := &SessionHandler{
Router: NewRouter(),
Logger: b.Logger,
Router: NewRouter(b.HTTPErrorHandler),
HTTPErrorHandler: b.HTTPErrorHandler,
Logger: b.Logger,
PasswordsService: b.PasswordsService,
SessionService: b.SessionService,
@ -58,19 +62,19 @@ func (h *SessionHandler) handleSignin(w http.ResponseWriter, r *http.Request) {
req, err := decodeSigninRequest(ctx, r)
if err != nil {
UnauthorizedError(ctx, w)
UnauthorizedError(ctx, h, w)
return
}
if err := h.PasswordsService.ComparePassword(ctx, req.Username, req.Password); err != nil {
// Don't log here, it should already be handled by the service
UnauthorizedError(ctx, w)
UnauthorizedError(ctx, h, w)
return
}
s, e := h.SessionService.CreateSession(ctx, req.Username)
if e != nil {
UnauthorizedError(ctx, w)
UnauthorizedError(ctx, h, w)
return
}
@ -104,12 +108,12 @@ func (h *SessionHandler) handleSignout(w http.ResponseWriter, r *http.Request) {
req, err := decodeSignoutRequest(ctx, r)
if err != nil {
UnauthorizedError(ctx, w)
UnauthorizedError(ctx, h, w)
return
}
if err := h.SessionService.ExpireSession(ctx, req.Key); err != nil {
UnauthorizedError(ctx, w)
UnauthorizedError(ctx, h, w)
return
}

View File

@ -78,6 +78,7 @@ func newSourcesResponse(srcs []*platform.Source) *sourcesResponse {
// SourceBackend is all services and associated parameters required to construct
// the SourceHandler.
type SourceBackend struct {
platform.HTTPErrorHandler
Logger *zap.Logger
SourceService platform.SourceService
@ -89,7 +90,8 @@ type SourceBackend struct {
// NewSourceBackend returns a new instance of SourceBackend.
func NewSourceBackend(b *APIBackend) *SourceBackend {
return &SourceBackend{
Logger: b.Logger.With(zap.String("handler", "source")),
HTTPErrorHandler: b.HTTPErrorHandler,
Logger: b.Logger.With(zap.String("handler", "source")),
SourceService: b.SourceService,
LabelService: b.LabelService,
@ -101,6 +103,7 @@ func NewSourceBackend(b *APIBackend) *SourceBackend {
// SourceHandler is a handler for sources
type SourceHandler struct {
*httprouter.Router
platform.HTTPErrorHandler
Logger *zap.Logger
SourceService platform.SourceService
LabelService platform.LabelService
@ -114,8 +117,9 @@ type SourceHandler struct {
// NewSourceHandler returns a new instance of SourceHandler.
func NewSourceHandler(b *SourceBackend) *SourceHandler {
h := &SourceHandler{
Router: NewRouter(),
Logger: b.Logger,
Router: NewRouter(b.HTTPErrorHandler),
HTTPErrorHandler: b.HTTPErrorHandler,
Logger: b.Logger,
SourceService: b.SourceService,
LabelService: b.LabelService,
@ -188,31 +192,31 @@ func (h *SourceHandler) handlePostSourceQuery(w http.ResponseWriter, r *http.Req
ctx := r.Context()
gsr, err := decodeGetSourceRequest(ctx, r)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
req, err := decodeSourceQueryRequest(r)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
s, err := h.SourceService.FindSourceByID(ctx, gsr.SourceID)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
querySvc, err := h.NewQueryService(s)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
_, err = querySvc.Query(ctx, w, req)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
}
@ -223,19 +227,19 @@ func (h *SourceHandler) handleGetSourcesBuckets(w http.ResponseWriter, r *http.R
req, err := decodeGetSourceBucketsRequest(ctx, r)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
_, err = h.SourceService.FindSourceByID(ctx, req.getSourceRequest.SourceID)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
bs, _, err := h.BucketService.FindBuckets(ctx, req.getBucketsRequest.filter)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
@ -271,12 +275,12 @@ func (h *SourceHandler) handlePostSource(w http.ResponseWriter, r *http.Request)
req, err := decodePostSourceRequest(ctx, r)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
if err := h.SourceService.CreateSource(ctx, req.Source); err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
@ -309,13 +313,13 @@ func (h *SourceHandler) handleGetSource(w http.ResponseWriter, r *http.Request)
req, err := decodeGetSourceRequest(ctx, r)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
s, err := h.SourceService.FindSourceByID(ctx, req.SourceID)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
@ -336,11 +340,11 @@ func (h *SourceHandler) handleGetSourceHealth(w http.ResponseWriter, r *http.Req
req, err := decodeGetSourceRequest(ctx, r)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
if _, err := h.SourceService.FindSourceByID(ctx, req.SourceID); err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
// todo(leodido) > check source is actually healthy and reply with 503 if not
@ -382,12 +386,12 @@ func (h *SourceHandler) handleDeleteSource(w http.ResponseWriter, r *http.Reques
req, err := decodeDeleteSourceRequest(ctx, r)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
if err := h.SourceService.DeleteSource(ctx, req.SourceID); err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
@ -425,13 +429,13 @@ func (h *SourceHandler) handleGetSources(w http.ResponseWriter, r *http.Request)
req, err := decodeGetSourcesRequest(ctx, r)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
srcs, _, err := h.SourceService.FindSources(ctx, req.findOptions)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
@ -458,13 +462,13 @@ func (h *SourceHandler) handlePatchSource(w http.ResponseWriter, r *http.Request
req, err := decodePatchSourceRequest(ctx, r)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
b, err := h.SourceService.UpdateSource(ctx, req.SourceID, req.Update)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}

View File

@ -16,6 +16,7 @@ var _ http.Handler = (*swaggerLoader)(nil)
// swaggerLoader manages loading the swagger asset and serving it as JSON.
type swaggerLoader struct {
influxdb.HTTPErrorHandler
logger *zap.Logger
// Ensure we only call initialize once.
@ -28,8 +29,8 @@ type swaggerLoader struct {
loadErr error
}
func newSwaggerLoader(logger *zap.Logger) *swaggerLoader {
return &swaggerLoader{logger: logger}
func newSwaggerLoader(logger *zap.Logger, h influxdb.HTTPErrorHandler) *swaggerLoader {
return &swaggerLoader{logger: logger, HTTPErrorHandler: h}
}
func (s *swaggerLoader) initialize() {
@ -51,7 +52,7 @@ func (s *swaggerLoader) ServeHTTP(w http.ResponseWriter, r *http.Request) {
s.once.Do(s.initialize)
if s.loadErr != nil {
EncodeError(r.Context(), &influxdb.Error{
s.HandleHTTPError(r.Context(), &influxdb.Error{
Err: s.loadErr,
Msg: "this developer binary not built with assets",
Code: influxdb.EInternal,

View File

@ -30,6 +30,7 @@ import (
// TaskBackend is all services and associated parameters required to construct
// the TaskHandler.
type TaskBackend struct {
platform.HTTPErrorHandler
Logger *zap.Logger
TaskService platform.TaskService
@ -44,6 +45,7 @@ type TaskBackend struct {
// NewTaskBackend returns a new instance of TaskBackend.
func NewTaskBackend(b *APIBackend) *TaskBackend {
return &TaskBackend{
HTTPErrorHandler: b.HTTPErrorHandler,
Logger: b.Logger.With(zap.String("handler", "task")),
TaskService: b.TaskService,
AuthorizationService: b.AuthorizationService,
@ -58,6 +60,7 @@ func NewTaskBackend(b *APIBackend) *TaskBackend {
// TaskHandler represents an HTTP API handler for tasks.
type TaskHandler struct {
*httprouter.Router
platform.HTTPErrorHandler
logger *zap.Logger
TaskService platform.TaskService
@ -88,8 +91,9 @@ const (
// NewTaskHandler returns a new instance of TaskHandler.
func NewTaskHandler(b *TaskBackend) *TaskHandler {
h := &TaskHandler{
Router: NewRouter(),
logger: b.Logger,
Router: NewRouter(b.HTTPErrorHandler),
HTTPErrorHandler: b.HTTPErrorHandler,
logger: b.Logger,
TaskService: b.TaskService,
AuthorizationService: b.AuthorizationService,
@ -111,6 +115,7 @@ func NewTaskHandler(b *TaskBackend) *TaskHandler {
h.HandlerFunc("GET", tasksIDRunsIDLogsPath, h.handleGetLogs)
memberBackend := MemberBackend{
HTTPErrorHandler: b.HTTPErrorHandler,
Logger: b.Logger.With(zap.String("handler", "member")),
ResourceType: platform.TasksResourceType,
UserType: platform.Member,
@ -122,6 +127,7 @@ func NewTaskHandler(b *TaskBackend) *TaskHandler {
h.HandlerFunc("DELETE", tasksIDMembersIDPath, newDeleteMemberHandler(memberBackend))
ownerBackend := MemberBackend{
HTTPErrorHandler: b.HTTPErrorHandler,
Logger: b.Logger.With(zap.String("handler", "member")),
ResourceType: platform.TasksResourceType,
UserType: platform.Owner,
@ -139,9 +145,10 @@ func NewTaskHandler(b *TaskBackend) *TaskHandler {
h.HandlerFunc("DELETE", tasksIDRunsIDPath, h.handleCancelRun)
labelBackend := &LabelBackend{
Logger: b.Logger.With(zap.String("handler", "label")),
LabelService: b.LabelService,
ResourceType: platform.TasksResourceType,
HTTPErrorHandler: b.HTTPErrorHandler,
Logger: b.Logger.With(zap.String("handler", "label")),
LabelService: b.LabelService,
ResourceType: platform.TasksResourceType,
}
h.HandlerFunc("GET", tasksIDLabelsPath, newGetLabelsHandler(labelBackend))
h.HandlerFunc("POST", tasksIDLabelsPath, newPostLabelHandler(labelBackend))
@ -275,7 +282,7 @@ func (h *TaskHandler) handleGetTasks(w http.ResponseWriter, r *http.Request) {
Code: platform.EInvalid,
Msg: "failed to decode request",
}
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
@ -285,7 +292,7 @@ func (h *TaskHandler) handleGetTasks(w http.ResponseWriter, r *http.Request) {
Err: err,
Msg: "failed to find tasks",
}
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
@ -467,7 +474,7 @@ func (h *TaskHandler) handlePostTask(w http.ResponseWriter, r *http.Request) {
Code: platform.EUnauthorized,
Msg: "failed to get authorizer",
}
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
@ -478,7 +485,7 @@ func (h *TaskHandler) handlePostTask(w http.ResponseWriter, r *http.Request) {
Code: platform.EInvalid,
Msg: "failed to decode request",
}
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
@ -487,7 +494,7 @@ func (h *TaskHandler) handlePostTask(w http.ResponseWriter, r *http.Request) {
Err: err,
Msg: "could not identify organization",
}
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
@ -496,13 +503,13 @@ func (h *TaskHandler) handlePostTask(w http.ResponseWriter, r *http.Request) {
Code: platform.EInvalid,
Msg: "invalid organization id",
}
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
bootstrapAuthz, err := h.createBootstrapTaskAuthorizationIfNotExists(ctx, auth, &req.TaskCreate)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
@ -515,7 +522,7 @@ func (h *TaskHandler) handlePostTask(w http.ResponseWriter, r *http.Request) {
Err: err,
Msg: "failed to create task",
}
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
@ -528,7 +535,7 @@ func (h *TaskHandler) handlePostTask(w http.ResponseWriter, r *http.Request) {
Msg: fmt.Sprintf("successfully created task with ID %s, but failed to finalize bootstrap token for task", task.ID.String()),
Code: platform.EInternal,
}
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
}
@ -568,7 +575,7 @@ func (h *TaskHandler) handleGetTask(w http.ResponseWriter, r *http.Request) {
Code: platform.EInvalid,
Msg: "failed to decode request",
}
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
@ -579,7 +586,7 @@ func (h *TaskHandler) handleGetTask(w http.ResponseWriter, r *http.Request) {
Code: platform.ENotFound,
Msg: "failed to find task",
}
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
@ -589,7 +596,7 @@ func (h *TaskHandler) handleGetTask(w http.ResponseWriter, r *http.Request) {
Err: err,
Msg: "failed to find resource labels",
}
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
@ -635,7 +642,7 @@ func (h *TaskHandler) handleUpdateTask(w http.ResponseWriter, r *http.Request) {
Code: platform.EInvalid,
Msg: "failed to decode request",
}
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
task, err := h.TaskService.UpdateTask(ctx, req.TaskID, req.Update)
@ -647,7 +654,7 @@ func (h *TaskHandler) handleUpdateTask(w http.ResponseWriter, r *http.Request) {
if err.Err == &influxdb.ErrTaskNotFound {
err.Code = platform.ENotFound
}
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
@ -657,7 +664,7 @@ func (h *TaskHandler) handleUpdateTask(w http.ResponseWriter, r *http.Request) {
Err: err,
Msg: "failed to find resource labels",
}
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
@ -712,7 +719,7 @@ func (h *TaskHandler) handleDeleteTask(w http.ResponseWriter, r *http.Request) {
Code: platform.EInvalid,
Msg: "failed to decode request",
}
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
@ -724,7 +731,7 @@ func (h *TaskHandler) handleDeleteTask(w http.ResponseWriter, r *http.Request) {
if err.Err == &influxdb.ErrTaskNotFound {
err.Code = platform.ENotFound
}
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
@ -765,7 +772,7 @@ func (h *TaskHandler) handleGetLogs(w http.ResponseWriter, r *http.Request) {
Code: platform.EInvalid,
Msg: "failed to decode request",
}
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
@ -776,7 +783,7 @@ func (h *TaskHandler) handleGetLogs(w http.ResponseWriter, r *http.Request) {
Code: platform.EUnauthorized,
Msg: "failed to get authorizer",
}
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
@ -784,7 +791,7 @@ func (h *TaskHandler) handleGetLogs(w http.ResponseWriter, r *http.Request) {
// Get the authorization for the task, if allowed.
authz, err := h.getAuthorizationForTask(ctx, req.filter.Task)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
@ -801,7 +808,7 @@ func (h *TaskHandler) handleGetLogs(w http.ResponseWriter, r *http.Request) {
if err.Err == &influxdb.ErrTaskNotFound || err.Err == &influxdb.ErrNoRunsFound {
err.Code = platform.ENotFound
}
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
@ -857,7 +864,7 @@ func (h *TaskHandler) handleGetRuns(w http.ResponseWriter, r *http.Request) {
Code: platform.EInvalid,
Msg: "failed to decode request",
}
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
@ -868,7 +875,7 @@ func (h *TaskHandler) handleGetRuns(w http.ResponseWriter, r *http.Request) {
Code: platform.EUnauthorized,
Msg: "failed to get authorizer",
}
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
@ -876,7 +883,7 @@ func (h *TaskHandler) handleGetRuns(w http.ResponseWriter, r *http.Request) {
// Get the authorization for the task, if allowed.
authz, err := h.getAuthorizationForTask(ctx, req.filter.Task)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
@ -893,7 +900,7 @@ func (h *TaskHandler) handleGetRuns(w http.ResponseWriter, r *http.Request) {
if err.Err == &influxdb.ErrTaskNotFound || err.Err == &influxdb.ErrNoRunsFound {
err.Code = platform.ENotFound
}
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
@ -984,7 +991,7 @@ func (h *TaskHandler) handleForceRun(w http.ResponseWriter, r *http.Request) {
Code: platform.EInvalid,
Msg: "failed to decode request",
}
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
@ -997,7 +1004,7 @@ func (h *TaskHandler) handleForceRun(w http.ResponseWriter, r *http.Request) {
if err.Err == &influxdb.ErrTaskNotFound {
err.Code = platform.ENotFound
}
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
if err := encodeResponse(ctx, w, http.StatusOK, newRunResponse(*run)); err != nil {
@ -1060,7 +1067,7 @@ func (h *TaskHandler) handleGetRun(w http.ResponseWriter, r *http.Request) {
Code: platform.EInvalid,
Msg: "failed to decode request",
}
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
@ -1071,7 +1078,7 @@ func (h *TaskHandler) handleGetRun(w http.ResponseWriter, r *http.Request) {
Code: platform.EUnauthorized,
Msg: "failed to get authorizer",
}
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
@ -1079,7 +1086,7 @@ func (h *TaskHandler) handleGetRun(w http.ResponseWriter, r *http.Request) {
// Get the authorization for the task, if allowed.
authz, err := h.getAuthorizationForTask(ctx, req.TaskID)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
@ -1096,7 +1103,7 @@ func (h *TaskHandler) handleGetRun(w http.ResponseWriter, r *http.Request) {
if err.Err == &influxdb.ErrTaskNotFound || err.Err == &influxdb.ErrRunNotFound {
err.Code = platform.ENotFound
}
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
@ -1189,7 +1196,7 @@ func (h *TaskHandler) handleCancelRun(w http.ResponseWriter, r *http.Request) {
Code: platform.EInvalid,
Msg: "failed to decode request",
}
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
@ -1202,7 +1209,7 @@ func (h *TaskHandler) handleCancelRun(w http.ResponseWriter, r *http.Request) {
if err.Err == &influxdb.ErrTaskNotFound || err.Err == &influxdb.ErrRunNotFound {
err.Code = platform.ENotFound
}
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
}
@ -1217,7 +1224,7 @@ func (h *TaskHandler) handleRetryRun(w http.ResponseWriter, r *http.Request) {
Code: platform.EInvalid,
Msg: "failed to decode request",
}
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
@ -1228,7 +1235,7 @@ func (h *TaskHandler) handleRetryRun(w http.ResponseWriter, r *http.Request) {
Code: platform.EUnauthorized,
Msg: "failed to get authorizer",
}
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
@ -1236,7 +1243,7 @@ func (h *TaskHandler) handleRetryRun(w http.ResponseWriter, r *http.Request) {
// Get the authorization for the task, if allowed.
authz, err := h.getAuthorizationForTask(ctx, req.TaskID)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
@ -1253,7 +1260,7 @@ func (h *TaskHandler) handleRetryRun(w http.ResponseWriter, r *http.Request) {
if err.Err == &influxdb.ErrTaskNotFound || err.Err == &platform.ErrRunNotFound {
err.Code = platform.ENotFound
}
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
if err := encodeResponse(ctx, w, http.StatusOK, newRunResponse(*run)); err != nil {
@ -1325,7 +1332,7 @@ func (h *TaskHandler) populateTaskCreateOrg(ctx context.Context, tc *platform.Ta
// getAuthorizationForTask looks up the authorization associated with taskID,
// ensuring that the authorizer on ctx is allowed to view the task and the authorization.
//
// This method returns a *platform.Error, suitable for directly passing to EncodeError.
// This method returns a *platform.Error, suitable for directly passing to h.HandleHTTPError.
func (h *TaskHandler) getAuthorizationForTask(ctx context.Context, taskID platform.ID) (*platform.Authorization, *platform.Error) {
// First look up the task, if we're allowed.
// This assumes h.TaskService validates access.

View File

@ -391,6 +391,7 @@ func TestTaskHandler_handleGetTasks(t *testing.T) {
w := httptest.NewRecorder()
taskBackend := NewMockTaskBackend(t)
taskBackend.HTTPErrorHandler = ErrorHandler(0)
taskBackend.TaskService = tt.fields.taskService
taskBackend.LabelService = tt.fields.labelService
h := NewTaskHandler(taskBackend)
@ -502,6 +503,7 @@ func TestTaskHandler_handlePostTasks(t *testing.T) {
w := httptest.NewRecorder()
taskBackend := NewMockTaskBackend(t)
taskBackend.HTTPErrorHandler = ErrorHandler(0)
taskBackend.TaskService = tt.fields.taskService
h := NewTaskHandler(taskBackend)
h.handlePostTask(w, r)
@ -611,6 +613,7 @@ func TestTaskHandler_handleGetRun(t *testing.T) {
r = r.WithContext(pcontext.SetAuthorizer(r.Context(), &platform.Authorization{Permissions: platform.OperPermissions()}))
w := httptest.NewRecorder()
taskBackend := NewMockTaskBackend(t)
taskBackend.HTTPErrorHandler = ErrorHandler(0)
taskBackend.TaskService = tt.fields.taskService
h := NewTaskHandler(taskBackend)
h.handleGetRun(w, r)
@ -724,6 +727,7 @@ func TestTaskHandler_handleGetRuns(t *testing.T) {
r = r.WithContext(pcontext.SetAuthorizer(r.Context(), &platform.Authorization{Permissions: platform.OperPermissions()}))
w := httptest.NewRecorder()
taskBackend := NewMockTaskBackend(t)
taskBackend.HTTPErrorHandler = ErrorHandler(0)
taskBackend.TaskService = tt.fields.taskService
h := NewTaskHandler(taskBackend)
h.handleGetRuns(w, r)
@ -754,6 +758,7 @@ func TestTaskHandler_NotFoundStatus(t *testing.T) {
im := inmem.NewService()
taskBackend := NewMockTaskBackend(t)
taskBackend.HTTPErrorHandler = ErrorHandler(0)
h := NewTaskHandler(taskBackend)
h.UserResourceMappingService = im
h.LabelService = im
@ -1283,7 +1288,8 @@ func TestTaskHandler_Sessions(t *testing.T) {
newHandler := func(t *testing.T, ts *mock.TaskService) *TaskHandler {
return NewTaskHandler(&TaskBackend{
Logger: zaptest.NewLogger(t),
HTTPErrorHandler: ErrorHandler(0),
Logger: zaptest.NewLogger(t),
TaskService: ts,
AuthorizationService: i,

View File

@ -28,9 +28,10 @@ func TestTaskService(t *testing.T) {
t.Fatalf("error initializing urm service: %v", err)
}
h := http.NewAuthenticationHandler()
h := http.NewAuthenticationHandler(http.ErrorHandler(0))
h.AuthorizationService = service
th := http.NewTaskHandler(&http.TaskBackend{
HTTPErrorHandler: http.ErrorHandler(0),
Logger: zaptest.NewLogger(t).With(zap.String("handler", "task")),
TaskService: service,
AuthorizationService: service,

View File

@ -18,6 +18,7 @@ import (
// TelegrafBackend is all services and associated parameters required to construct
// the TelegrafHandler.
type TelegrafBackend struct {
platform.HTTPErrorHandler
Logger *zap.Logger
TelegrafService platform.TelegrafConfigStore
@ -30,7 +31,8 @@ type TelegrafBackend struct {
// NewTelegrafBackend returns a new instance of TelegrafBackend.
func NewTelegrafBackend(b *APIBackend) *TelegrafBackend {
return &TelegrafBackend{
Logger: b.Logger.With(zap.String("handler", "telegraf")),
HTTPErrorHandler: b.HTTPErrorHandler,
Logger: b.Logger.With(zap.String("handler", "telegraf")),
TelegrafService: b.TelegrafService,
UserResourceMappingService: b.UserResourceMappingService,
@ -43,6 +45,7 @@ func NewTelegrafBackend(b *APIBackend) *TelegrafBackend {
// TelegrafHandler is the handler for the telegraf service
type TelegrafHandler struct {
*httprouter.Router
platform.HTTPErrorHandler
Logger *zap.Logger
TelegrafService platform.TelegrafConfigStore
@ -66,8 +69,9 @@ const (
// NewTelegrafHandler returns a new instance of TelegrafHandler.
func NewTelegrafHandler(b *TelegrafBackend) *TelegrafHandler {
h := &TelegrafHandler{
Router: NewRouter(),
Logger: b.Logger,
Router: NewRouter(b.HTTPErrorHandler),
HTTPErrorHandler: b.HTTPErrorHandler,
Logger: b.Logger,
TelegrafService: b.TelegrafService,
UserResourceMappingService: b.UserResourceMappingService,
@ -82,6 +86,7 @@ func NewTelegrafHandler(b *TelegrafBackend) *TelegrafHandler {
h.HandlerFunc("PUT", telegrafsIDPath, h.handlePutTelegraf)
memberBackend := MemberBackend{
HTTPErrorHandler: b.HTTPErrorHandler,
Logger: b.Logger.With(zap.String("handler", "member")),
ResourceType: platform.TelegrafsResourceType,
UserType: platform.Member,
@ -93,6 +98,7 @@ func NewTelegrafHandler(b *TelegrafBackend) *TelegrafHandler {
h.HandlerFunc("DELETE", telegrafsIDMembersIDPath, newDeleteMemberHandler(memberBackend))
ownerBackend := MemberBackend{
HTTPErrorHandler: b.HTTPErrorHandler,
Logger: b.Logger.With(zap.String("handler", "member")),
ResourceType: platform.TelegrafsResourceType,
UserType: platform.Owner,
@ -104,9 +110,10 @@ func NewTelegrafHandler(b *TelegrafBackend) *TelegrafHandler {
h.HandlerFunc("DELETE", telegrafsIDOwnersIDPath, newDeleteMemberHandler(ownerBackend))
labelBackend := &LabelBackend{
Logger: b.Logger.With(zap.String("handler", "label")),
LabelService: b.LabelService,
ResourceType: platform.TelegrafsResourceType,
HTTPErrorHandler: b.HTTPErrorHandler,
Logger: b.Logger.With(zap.String("handler", "label")),
LabelService: b.LabelService,
ResourceType: platform.TelegrafsResourceType,
}
h.HandlerFunc("GET", telegrafsIDLabelsPath, newGetLabelsHandler(labelBackend))
h.HandlerFunc("POST", telegrafsIDLabelsPath, newPostLabelHandler(labelBackend))
@ -232,12 +239,12 @@ func (h *TelegrafHandler) handleGetTelegrafs(w http.ResponseWriter, r *http.Requ
filter, err := decodeTelegrafConfigFilter(ctx, r)
if err != nil {
h.Logger.Debug("failed to decode request", zap.Error(err))
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
tcs, _, err := h.TelegrafService.FindTelegrafConfigs(ctx, *filter)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
if err := encodeResponse(ctx, w, http.StatusOK, newTelegrafResponses(ctx, tcs, h.LabelService)); err != nil {
@ -250,12 +257,12 @@ func (h *TelegrafHandler) handleGetTelegraf(w http.ResponseWriter, r *http.Reque
ctx := r.Context()
id, err := decodeGetTelegrafRequest(ctx, r)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
tc, err := h.TelegrafService.FindTelegrafConfigByID(ctx, id)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
@ -271,7 +278,7 @@ func (h *TelegrafHandler) handleGetTelegraf(w http.ResponseWriter, r *http.Reque
case "application/json":
labels, err := h.LabelService.FindResourceLabels(ctx, platform.LabelMappingFilter{ResourceID: tc.ID})
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
@ -366,17 +373,17 @@ func (h *TelegrafHandler) handlePostTelegraf(w http.ResponseWriter, r *http.Requ
tc, err := decodePostTelegrafRequest(ctx, r)
if err != nil {
h.Logger.Debug("failed to decode request", zap.Error(err))
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
auth, err := pctx.GetAuthorizer(ctx)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
if err := h.TelegrafService.CreateTelegrafConfig(ctx, tc, auth.GetUserID()); err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
@ -392,24 +399,24 @@ func (h *TelegrafHandler) handlePutTelegraf(w http.ResponseWriter, r *http.Reque
tc, err := decodePutTelegrafRequest(ctx, r)
if err != nil {
h.Logger.Debug("failed to decode request", zap.Error(err))
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
auth, err := pctx.GetAuthorizer(ctx)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
tc, err = h.TelegrafService.UpdateTelegrafConfig(ctx, tc.ID, tc, auth.GetUserID())
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
labels, err := h.LabelService.FindResourceLabels(ctx, platform.LabelMappingFilter{ResourceID: tc.ID})
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
@ -423,12 +430,12 @@ func (h *TelegrafHandler) handleDeleteTelegraf(w http.ResponseWriter, r *http.Re
ctx := r.Context()
i, err := decodeGetTelegrafRequest(ctx, r)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
if err = h.TelegrafService.DeleteTelegrafConfig(ctx, i); err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}

View File

@ -14,16 +14,16 @@ import (
// UsageHandler represents an HTTP API handler for usages.
type UsageHandler struct {
*httprouter.Router
platform.HTTPErrorHandler
Logger *zap.Logger
UsageService platform.UsageService
}
// NewUsageHandler returns a new instance of UsageHandler.
func NewUsageHandler() *UsageHandler {
func NewUsageHandler(he platform.HTTPErrorHandler) *UsageHandler {
h := &UsageHandler{
Router: NewRouter(),
Router: NewRouter(he),
Logger: zap.NewNop(),
}
@ -37,13 +37,13 @@ func (h *UsageHandler) handleGetUsage(w http.ResponseWriter, r *http.Request) {
req, err := decodeGetUsageRequest(ctx, r)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
b, err := h.UsageService.GetUsage(ctx, req.filter)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}

View File

@ -56,6 +56,7 @@ func newResourceUsersResponse(opts platform.FindOptions, f platform.UserResource
// MemberBackend is all services and associated parameters required to construct
// member handler.
type MemberBackend struct {
platform.HTTPErrorHandler
Logger *zap.Logger
ResourceType platform.ResourceType
@ -72,13 +73,13 @@ func newPostMemberHandler(b MemberBackend) http.HandlerFunc {
req, err := decodePostMemberRequest(ctx, r)
if err != nil {
EncodeError(ctx, err, w)
b.HandleHTTPError(ctx, err, w)
return
}
user, err := b.UserService.FindUserByID(ctx, req.MemberID)
if err != nil {
EncodeError(ctx, err, w)
b.HandleHTTPError(ctx, err, w)
return
}
@ -90,12 +91,12 @@ func newPostMemberHandler(b MemberBackend) http.HandlerFunc {
}
if err := b.UserResourceMappingService.CreateUserResourceMapping(ctx, mapping); err != nil {
EncodeError(ctx, err, w)
b.HandleHTTPError(ctx, err, w)
return
}
if err := encodeResponse(ctx, w, http.StatusCreated, newResourceUserResponse(user, b.UserType)); err != nil {
EncodeError(ctx, err, w)
b.HandleHTTPError(ctx, err, w)
return
}
}
@ -146,7 +147,7 @@ func newGetMembersHandler(b MemberBackend) http.HandlerFunc {
req, err := decodeGetMembersRequest(ctx, r)
if err != nil {
EncodeError(ctx, err, w)
b.HandleHTTPError(ctx, err, w)
return
}
@ -159,7 +160,7 @@ func newGetMembersHandler(b MemberBackend) http.HandlerFunc {
opts := platform.FindOptions{}
mappings, _, err := b.UserResourceMappingService.FindUserResourceMappings(ctx, filter)
if err != nil {
EncodeError(ctx, err, w)
b.HandleHTTPError(ctx, err, w)
return
}
@ -170,7 +171,7 @@ func newGetMembersHandler(b MemberBackend) http.HandlerFunc {
}
user, err := b.UserService.FindUserByID(ctx, m.UserID)
if err != nil {
EncodeError(ctx, err, w)
b.HandleHTTPError(ctx, err, w)
return
}
@ -178,7 +179,7 @@ func newGetMembersHandler(b MemberBackend) http.HandlerFunc {
}
if err := encodeResponse(ctx, w, http.StatusOK, newResourceUsersResponse(opts, filter, users)); err != nil {
EncodeError(ctx, err, w)
b.HandleHTTPError(ctx, err, w)
return
}
}
@ -218,12 +219,12 @@ func newDeleteMemberHandler(b MemberBackend) http.HandlerFunc {
req, err := decodeDeleteMemberRequest(ctx, r)
if err != nil {
EncodeError(ctx, err, w)
b.HandleHTTPError(ctx, err, w)
return
}
if err := b.UserResourceMappingService.DeleteUserResourceMapping(ctx, req.ResourceID, req.MemberID); err != nil {
EncodeError(ctx, err, w)
b.HandleHTTPError(ctx, err, w)
return
}

View File

@ -17,6 +17,7 @@ import (
// UserBackend is all services and associated parameters required to construct
// the UserHandler.
type UserBackend struct {
influxdb.HTTPErrorHandler
Logger *zap.Logger
UserService influxdb.UserService
UserOperationLogService influxdb.UserOperationLogService
@ -26,6 +27,7 @@ type UserBackend struct {
// NewUserBackend creates a UserBackend using information in the APIBackend.
func NewUserBackend(b *APIBackend) *UserBackend {
return &UserBackend{
HTTPErrorHandler: b.HTTPErrorHandler,
Logger: b.Logger.With(zap.String("handler", "user")),
UserService: b.UserService,
UserOperationLogService: b.UserOperationLogService,
@ -36,6 +38,7 @@ func NewUserBackend(b *APIBackend) *UserBackend {
// UserHandler represents an HTTP API handler for users.
type UserHandler struct {
*httprouter.Router
influxdb.HTTPErrorHandler
Logger *zap.Logger
UserService influxdb.UserService
UserOperationLogService influxdb.UserOperationLogService
@ -54,8 +57,9 @@ const (
// NewUserHandler returns a new instance of UserHandler.
func NewUserHandler(b *UserBackend) *UserHandler {
h := &UserHandler{
Router: NewRouter(),
Logger: b.Logger,
Router: NewRouter(b.HTTPErrorHandler),
HTTPErrorHandler: b.HTTPErrorHandler,
Logger: b.Logger,
UserService: b.UserService,
UserOperationLogService: b.UserOperationLogService,
@ -95,7 +99,7 @@ func (h *UserHandler) handlePutUserPassword(w http.ResponseWriter, r *http.Reque
ctx := r.Context()
_, err := h.putPassword(ctx, w, r)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
@ -140,17 +144,17 @@ func (h *UserHandler) handlePostUser(w http.ResponseWriter, r *http.Request) {
req, err := decodePostUserRequest(ctx, r)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
if err := h.UserService.CreateUser(ctx, req.User); err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
if err := encodeResponse(ctx, w, http.StatusCreated, newUserResponse(req.User)); err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
}
@ -176,7 +180,7 @@ func (h *UserHandler) handleGetMe(w http.ResponseWriter, r *http.Request) {
a, err := icontext.GetAuthorizer(ctx)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
@ -184,13 +188,12 @@ func (h *UserHandler) handleGetMe(w http.ResponseWriter, r *http.Request) {
user, err := h.UserService.FindUserByID(ctx, id)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
if err := encodeResponse(ctx, w, http.StatusOK, newUserResponse(user)); err != nil {
EncodeError(ctx, err, w)
return
h.HandleHTTPError(ctx, err, w)
}
}
@ -200,18 +203,18 @@ func (h *UserHandler) handleGetUser(w http.ResponseWriter, r *http.Request) {
req, err := decodeGetUserRequest(ctx, r)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
b, err := h.UserService.FindUserByID(ctx, req.UserID)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
if err := encodeResponse(ctx, w, http.StatusOK, newUserResponse(b)); err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
}
@ -248,12 +251,12 @@ func (h *UserHandler) handleDeleteUser(w http.ResponseWriter, r *http.Request) {
req, err := decodeDeleteUserRequest(ctx, r)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
if err := h.UserService.DeleteUser(ctx, req.UserID); err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
@ -331,19 +334,19 @@ func (h *UserHandler) handleGetUsers(w http.ResponseWriter, r *http.Request) {
req, err := decodeGetUsersRequest(ctx, r)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
users, _, err := h.UserService.FindUsers(ctx, req.filter)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
err = encodeResponse(ctx, w, http.StatusOK, newUsersResponse(users))
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
}
@ -377,18 +380,18 @@ func (h *UserHandler) handlePatchUser(w http.ResponseWriter, r *http.Request) {
req, err := decodePatchUserRequest(ctx, r)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
b, err := h.UserService.UpdateUser(ctx, req.UserID, req.Update)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
if err := encodeResponse(ctx, w, http.StatusOK, newUserResponse(b)); err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
}
@ -681,18 +684,18 @@ func (h *UserHandler) handleGetUserLog(w http.ResponseWriter, r *http.Request) {
req, err := decodeGetUserLogRequest(ctx, r)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
log, _, err := h.UserOperationLogService.GetUserOperationLog(ctx, req.UserID, req.opts)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
if err := encodeResponse(ctx, w, http.StatusOK, newUserLogResponse(req.UserID, log)); err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
}

View File

@ -35,6 +35,7 @@ func initUserService(f platformtesting.UserFields, t *testing.T) (platform.UserS
}
userBackend := NewMockUserBackend()
userBackend.HTTPErrorHandler = ErrorHandler(0)
userBackend.UserService = svc
handler := NewUserHandler(userBackend)
server := httptest.NewServer(handler)

View File

@ -5,11 +5,12 @@ import (
"context"
"encoding/json"
"fmt"
"net/http"
"path"
platform "github.com/influxdata/influxdb"
"github.com/julienschmidt/httprouter"
"go.uber.org/zap"
"net/http"
"path"
)
const (
@ -19,6 +20,7 @@ const (
// VariableBackend is all services and associated parameters required to construct
// the VariableHandler.
type VariableBackend struct {
platform.HTTPErrorHandler
Logger *zap.Logger
VariableService platform.VariableService
LabelService platform.LabelService
@ -27,9 +29,10 @@ type VariableBackend struct {
// NewVariableBackend creates a backend used by the variable handler.
func NewVariableBackend(b *APIBackend) *VariableBackend {
return &VariableBackend{
Logger: b.Logger.With(zap.String("handler", "variable")),
VariableService: b.VariableService,
LabelService: b.LabelService,
HTTPErrorHandler: b.HTTPErrorHandler,
Logger: b.Logger.With(zap.String("handler", "variable")),
VariableService: b.VariableService,
LabelService: b.LabelService,
}
}
@ -37,6 +40,7 @@ func NewVariableBackend(b *APIBackend) *VariableBackend {
type VariableHandler struct {
*httprouter.Router
platform.HTTPErrorHandler
Logger *zap.Logger
VariableService platform.VariableService
@ -46,8 +50,9 @@ type VariableHandler struct {
// NewVariableHandler creates a new VariableHandler
func NewVariableHandler(b *VariableBackend) *VariableHandler {
h := &VariableHandler{
Router: NewRouter(),
Logger: b.Logger,
Router: NewRouter(b.HTTPErrorHandler),
HTTPErrorHandler: b.HTTPErrorHandler,
Logger: b.Logger,
VariableService: b.VariableService,
LabelService: b.LabelService,
@ -65,9 +70,10 @@ func NewVariableHandler(b *VariableBackend) *VariableHandler {
h.HandlerFunc("DELETE", entityPath, h.handleDeleteVariable)
labelBackend := &LabelBackend{
Logger: b.Logger.With(zap.String("handler", "label")),
LabelService: b.LabelService,
ResourceType: platform.DashboardsResourceType,
HTTPErrorHandler: b.HTTPErrorHandler,
Logger: b.Logger.With(zap.String("handler", "label")),
LabelService: b.LabelService,
ResourceType: platform.DashboardsResourceType,
}
h.HandlerFunc("GET", entityLabelsPath, newGetLabelsHandler(labelBackend))
h.HandlerFunc("POST", entityLabelsPath, newPostLabelHandler(labelBackend))
@ -140,13 +146,13 @@ func (h *VariableHandler) handleGetVariables(w http.ResponseWriter, r *http.Requ
req, err := decodeGetVariablesRequest(ctx, r)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
variables, err := h.VariableService.FindVariables(ctx, req.filter, req.opts)
if err != nil {
EncodeError(ctx, &platform.Error{
h.HandleHTTPError(ctx, &platform.Error{
Code: platform.EInternal,
Msg: "could not read variables",
Err: err,
@ -184,19 +190,19 @@ func (h *VariableHandler) handleGetVariable(w http.ResponseWriter, r *http.Reque
id, err := requestVariableID(ctx)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
variable, err := h.VariableService.FindVariableByID(ctx, id)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
labels, err := h.LabelService.FindResourceLabels(ctx, platform.LabelMappingFilter{ResourceID: variable.ID})
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
@ -240,13 +246,13 @@ func (h *VariableHandler) handlePostVariable(w http.ResponseWriter, r *http.Requ
ctx := r.Context()
req, err := decodePostVariableRequest(ctx, r)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
err = h.VariableService.CreateVariable(ctx, req.variable)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
if err := encodeResponse(ctx, w, http.StatusCreated, newVariableResponse(req.variable, []*platform.Label{})); err != nil {
@ -293,19 +299,19 @@ func (h *VariableHandler) handlePatchVariable(w http.ResponseWriter, r *http.Req
req, err := decodePatchVariableRequest(ctx, r)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
variable, err := h.VariableService.UpdateVariable(ctx, req.id, req.variableUpdate)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
labels, err := h.LabelService.FindResourceLabels(ctx, platform.LabelMappingFilter{ResourceID: variable.ID})
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
@ -361,19 +367,19 @@ func (h *VariableHandler) handlePutVariable(w http.ResponseWriter, r *http.Reque
req, err := decodePutVariableRequest(ctx, r)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
err = h.VariableService.ReplaceVariable(ctx, req.variable)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
labels, err := h.LabelService.FindResourceLabels(ctx, platform.LabelMappingFilter{ResourceID: req.variable.ID})
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
@ -422,13 +428,13 @@ func (h *VariableHandler) handleDeleteVariable(w http.ResponseWriter, r *http.Re
id, err := requestVariableID(ctx)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
err = h.VariableService.DeleteVariable(ctx, id)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}

View File

@ -296,6 +296,7 @@ func TestVariableService_handleGetVariables(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
variableBackend := NewMockVariableBackend()
variableBackend.HTTPErrorHandler = ErrorHandler(0)
variableBackend.LabelService = tt.fields.LabelService
variableBackend.VariableService = tt.fields.VariableService
h := NewVariableHandler(variableBackend)
@ -427,6 +428,7 @@ func TestVariableService_handleGetVariable(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
variableBackend := NewMockVariableBackend()
variableBackend.HTTPErrorHandler = ErrorHandler(0)
variableBackend.VariableService = tt.fields.VariableService
h := NewVariableHandler(variableBackend)
r := httptest.NewRequest("GET", "http://howdy.tld", nil)
@ -565,6 +567,7 @@ func TestVariableService_handlePostVariable(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
variableBackend := NewMockVariableBackend()
variableBackend.HTTPErrorHandler = ErrorHandler(0)
variableBackend.VariableService = tt.fields.VariableService
h := NewVariableHandler(variableBackend)
r := httptest.NewRequest("GET", "http://howdy.tld", bytes.NewReader([]byte(tt.args.variable)))
@ -664,6 +667,7 @@ func TestVariableService_handlePatchVariable(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
variableBackend := NewMockVariableBackend()
variableBackend.HTTPErrorHandler = ErrorHandler(0)
variableBackend.VariableService = tt.fields.VariableService
h := NewVariableHandler(variableBackend)
r := httptest.NewRequest("GET", "http://howdy.tld", bytes.NewReader([]byte(tt.args.update)))
@ -757,6 +761,7 @@ func TestVariableService_handleDeleteVariable(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
variableBackend := NewMockVariableBackend()
variableBackend.HTTPErrorHandler = ErrorHandler(0)
variableBackend.VariableService = tt.fields.VariableService
h := NewVariableHandler(variableBackend)
r := httptest.NewRequest("GET", "http://howdy.tld", nil)
@ -849,6 +854,7 @@ func TestService_handlePostVariableLabel(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
variableBackend := NewMockVariableBackend()
variableBackend.HTTPErrorHandler = ErrorHandler(0)
variableBackend.LabelService = tt.fields.LabelService
h := NewVariableHandler(variableBackend)
@ -900,6 +906,7 @@ func initVariableService(f platformtesting.VariableFields, t *testing.T) (platfo
}
variableBackend := NewMockVariableBackend()
variableBackend.HTTPErrorHandler = ErrorHandler(0)
variableBackend.VariableService = svc
handler := NewVariableHandler(variableBackend)
server := httptest.NewServer(handler)

View File

@ -24,6 +24,7 @@ import (
// WriteBackend is all services and associated parameters required to construct
// the WriteHandler.
type WriteBackend struct {
platform.HTTPErrorHandler
Logger *zap.Logger
WriteEventRecorder metric.EventRecorder
@ -35,6 +36,7 @@ type WriteBackend struct {
// NewWriteBackend returns a new instance of WriteBackend.
func NewWriteBackend(b *APIBackend) *WriteBackend {
return &WriteBackend{
HTTPErrorHandler: b.HTTPErrorHandler,
Logger: b.Logger.With(zap.String("handler", "write")),
WriteEventRecorder: b.WriteEventRecorder,
@ -47,7 +49,7 @@ func NewWriteBackend(b *APIBackend) *WriteBackend {
// WriteHandler receives line protocol and sends to a publish function.
type WriteHandler struct {
*httprouter.Router
platform.HTTPErrorHandler
Logger *zap.Logger
BucketService platform.BucketService
@ -67,8 +69,9 @@ const (
// NewWriteHandler creates a new handler at /api/v2/write to receive line protocol.
func NewWriteHandler(b *WriteBackend) *WriteHandler {
h := &WriteHandler{
Router: NewRouter(),
Logger: b.Logger,
Router: NewRouter(b.HTTPErrorHandler),
HTTPErrorHandler: b.HTTPErrorHandler,
Logger: b.Logger,
PointsWriter: b.PointsWriter,
BucketService: b.BucketService,
@ -108,7 +111,7 @@ func (h *WriteHandler) handleWrite(w http.ResponseWriter, r *http.Request) {
var err error
in, err = gzip.NewReader(r.Body)
if err != nil {
EncodeError(ctx, &platform.Error{
h.HandleHTTPError(ctx, &platform.Error{
Code: platform.EInvalid,
Op: "http/handleWrite",
Msg: errInvalidGzipHeader,
@ -121,13 +124,13 @@ func (h *WriteHandler) handleWrite(w http.ResponseWriter, r *http.Request) {
a, err := pcontext.GetAuthorizer(ctx)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
req, err := decodeWriteRequest(ctx, r)
if err != nil {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
@ -140,7 +143,7 @@ func (h *WriteHandler) handleWrite(w http.ResponseWriter, r *http.Request) {
if err == nil {
org = o
} else if platform.ErrorCode(err) != platform.ENotFound {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
}
@ -148,7 +151,7 @@ func (h *WriteHandler) handleWrite(w http.ResponseWriter, r *http.Request) {
o, err := h.OrganizationService.FindOrganization(ctx, platform.OrganizationFilter{Name: &req.Org})
if err != nil {
logger.Info("Failed to find organization", zap.Error(err))
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
@ -166,7 +169,7 @@ func (h *WriteHandler) handleWrite(w http.ResponseWriter, r *http.Request) {
if err == nil {
bucket = b
} else if platform.ErrorCode(err) != platform.ENotFound {
EncodeError(ctx, err, w)
h.HandleHTTPError(ctx, err, w)
return
}
}
@ -177,7 +180,7 @@ func (h *WriteHandler) handleWrite(w http.ResponseWriter, r *http.Request) {
Name: &req.Bucket,
})
if err != nil {
EncodeError(ctx, &platform.Error{
h.HandleHTTPError(ctx, &platform.Error{
Op: "http/handleWrite",
Err: err,
}, w)
@ -189,7 +192,7 @@ func (h *WriteHandler) handleWrite(w http.ResponseWriter, r *http.Request) {
p, err := platform.NewPermissionAtID(bucket.ID, platform.WriteAction, platform.BucketsResourceType, org.ID)
if err != nil {
EncodeError(ctx, &platform.Error{
h.HandleHTTPError(ctx, &platform.Error{
Code: platform.EInternal,
Op: "http/handleWrite",
Msg: fmt.Sprintf("unable to create permission for bucket: %v", err),
@ -199,7 +202,7 @@ func (h *WriteHandler) handleWrite(w http.ResponseWriter, r *http.Request) {
}
if !a.Allowed(*p) {
EncodeError(ctx, &platform.Error{
h.HandleHTTPError(ctx, &platform.Error{
Code: platform.EForbidden,
Op: "http/handleWrite",
Msg: "insufficient permissions for write",
@ -213,7 +216,7 @@ func (h *WriteHandler) handleWrite(w http.ResponseWriter, r *http.Request) {
data, err := ioutil.ReadAll(in)
if err != nil {
logger.Error("Error reading body", zap.Error(err))
EncodeError(ctx, &platform.Error{
h.HandleHTTPError(ctx, &platform.Error{
Code: platform.EInternal,
Op: "http/handleWrite",
Msg: fmt.Sprintf("unable to read data: %v", err),
@ -228,7 +231,7 @@ func (h *WriteHandler) handleWrite(w http.ResponseWriter, r *http.Request) {
points, err := models.ParsePointsWithPrecision(data, mm, time.Now(), req.Precision)
if err != nil {
logger.Error("Error parsing points", zap.Error(err))
EncodeError(ctx, &platform.Error{
h.HandleHTTPError(ctx, &platform.Error{
Code: platform.EInvalid,
Op: "http/handleWrite",
Msg: fmt.Sprintf("unable to parse points: %v", err),
@ -239,7 +242,7 @@ func (h *WriteHandler) handleWrite(w http.ResponseWriter, r *http.Request) {
if err := h.PointsWriter.WritePoints(ctx, points); err != nil {
logger.Error("Error writing points", zap.Error(err))
EncodeError(ctx, &platform.Error{
h.HandleHTTPError(ctx, &platform.Error{
Code: platform.EInternal,
Op: "http/handleWrite",
Msg: fmt.Sprintf("unable to write points to database: %v", err),