influxdb/http
Mark Rushakoff faf5408a7b fix(http): increase errorHeaderMaxLength
The limit was introduced in 510325ea5c but
it didn't specify why 64 was chosen.

According to https://stackoverflow.com/a/6160643, we should be able to
assume at least 8kb of space for HTTP headers, so I'm assuming 256 bytes
should be sufficient to avoid truncating most error messages, without
being likely to hit the total HTTP header limit.

Fixes #530.
2018-08-01 16:04:36 -07:00
..
README.md migrate(platform): move public dependencies into platform 2018-05-14 17:12:53 -04:00
assets.go fix(http): fix chronograf build asset paths 2018-07-24 14:25:06 -04:00
auth_service.go revert #442 2018-08-01 14:54:32 -04:00
bucket_service.go revert #442 2018-08-01 14:54:32 -04:00
chronograf_handler.go chore(chronograf): Get Chronograf to "work" as in 1.6.x (w/o Kapacitor) 2018-07-24 15:13:08 -07:00
client.go migrate(platform): move public dependencies into platform 2018-05-14 17:12:53 -04:00
dashboard_service.go revert #442 2018-08-01 14:54:32 -04:00
errors.go fix(http): increase errorHeaderMaxLength 2018-08-01 16:04:36 -07:00
errors_test.go fix(http): increase errorHeaderMaxLength 2018-08-01 16:04:36 -07:00
handler.go feat: add errors to http logging 2018-07-31 14:34:55 -06:00
org_service.go revert #442 2018-08-01 14:54:32 -04:00
platform_handler.go feat(chronograf): all chronograf api handler to platform 2018-07-24 15:55:49 -04:00
query_service.go revert #442 2018-08-01 14:54:32 -04:00
server.go fix(http): use a duration literal for the server's shutdown timeout 2018-06-11 12:39:06 -05:00
status.go feat: Add optional http logging to handler 2018-07-30 16:16:37 -06:00
swagger.yml feat(http): Add /ping endpoint to fluxd 2018-07-25 12:21:59 -07:00
task_service.go revert #442 2018-08-01 14:54:32 -04:00
token_parse_test.go fix(http): fix auth header 2018-06-04 15:26:50 -07:00
token_parser.go fix(http): fix auth header 2018-06-04 15:26:50 -07:00
transpiler_handler.go revert #442 2018-08-01 14:54:32 -04:00
usage_service.go fix(errors): Update Fluxd errors 2018-06-28 16:56:35 -06:00
user_service.go revert #442 2018-08-01 14:54:32 -04:00

README.md

HTTP Handler Style Guide

HTTP Handler

  • Each handler should implement http.Handler
    • This can be done by embedding a httprouter.Router (a light weight HTTP router that supports variables in the routing pattern and matches against the request method)
  • Required services should be exported on the struct
// ThingHandler represents an HTTP API handler for things.
type ThingHandler struct {
	// embedded httprouter.Router as a lazy way to implement http.Handler
	*httprouter.Router

	ThingService         platform.ThingService
	AuthorizationService platform.AuthorizationService

	Logger               *zap.Logger
}

HTTP Handler Constructor

  • Routes should be declared in the constructor
// NewThingHandler returns a new instance of ThingHandler.
func NewThingHandler() *ThingHandler {
	h := &ThingHandler{
		Router: httprouter.New(),
		Logger: zap.Nop(),
	}

	h.HandlerFunc("POST", "/v1/things", h.handlePostThing)
	h.HandlerFunc("GET", "/v1/things", h.handleGetThings)

	return h
}

Route handlers (http.HandlerFuncs)

  • Each route handler should have an associated request struct and decode function
  • The decode function should take a context.Context and an *http.Request and return the associated route request struct
type postThingRequest struct {
	Thing *platform.Thing
}

func decodePostThingRequest(ctx context.Context, r *http.Request) (*postThingRequest, error) {
	t := &platform.Thing{}
	if err := json.NewDecoder(r.Body).Decode(t); err != nil {
		return nil, err
	}

	return &postThingRequest{
		Thing: t,
	}, nil
}
  • Route http.HandlerFuncs should separate the decoding and encoding of HTTP requests/response from actual handler logic
// handlePostThing is the HTTP handler for the POST /v1/things route.
func (h *ThingHandler) handlePostThing(w http.ResponseWriter, r *http.Request) {
	ctx := r.Context()

	req, err := decodePostThingRequest(ctx, r)
	if err != nil {
		errors.EncodeHTTP(ctx, err, w)
		return
	}

	// Do stuff here
	if err := h.ThingService.CreateThing(ctx, req.Thing); err != nil {
		errors.EncodeHTTP(ctx, err, w)
		return
	}

	if err := encodeResponse(ctx, w, http.StatusCreated, req.Thing); err != nil {
		h.Logger.Info("encoding response failed", zap.Error(err))
		return
	}
}
  • http.HandlerFunc's that require particular encoding of http responses should implement an encode response function