middleware

package module
v1.1.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 25, 2022 License: Apache-2.0 Imports: 10 Imported by: 0

Documentation

Overview

Package middleware has HTTP server middleware that provides access to a shared logger and simplifies writing canonical log lines with a shared entry per request. It also automates basic request parameter logging.

NewHTTPServer binds a logger to an HTTP server so that it will be present in every request context:

// Create a logger.
logger, err := log.Open("zerolog", nil)

// Generate a new HTTP server with the logger.
srv, logCloser = middleware.NewHTTPServer(logger, log.INFO)
defer logCloser.Close()

// Now every request will have access to the logger in the context.
srv.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    logger := log.LoggerFromCtx(r.Context())
})
srv.ListenAndServe()

NewHTTPRequestMiddleware injects an entry into the context of the the request that it writes after the succeeding handlers process it. This entry has certain aspects of the request logged by default, but can be configured to include more. Subsequent handlers can also extract the entry and update it to allow for canonical log line logging.

// Create a logger.
logger, err := log.Open("zerolog", nil)

// Define request attributes to log.
attrs := middleware.HTTPRequestLogAttributes{
    Headers: []string{"X-Trace-Id", "X-Request-Id"},
    Synthetics: map[string]func(*http.Request) string{
        "req.unmod-uri": func(r *http.Request) string { return r.RequestURI },
    },
}

// Generate the middleware and then wrap subsequent handlers.
middlewareFn := middleware.NewHTTPRequestMiddleware(logger, log.INFO, attrs)
handler := middlewareFn(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    w.WriteHeader(http.StatusOK)
}))
handler.ServeHTTP(resp, req)

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func NewHTTPRequestMiddleware

func NewHTTPRequestMiddleware(logger log.Logger, lvl log.Level, attrs *HTTPRequestLogAttributes) func(http.Handler) http.Handler

NewHTTPRequestMiddleware returns net/http compatible middleware for logging requests that pass through it at the provided level. It will also insert an Async log.Entry into the request context such that downstream handlers can use it. It will call entry.Send when done, and capture panics. If lvl is invalid, the default level will be used.

func NewHTTPServer

func NewHTTPServer(logger log.Logger, srvLvl log.Level) (*http.Server, io.Closer)

NewHTTPServer returns an http.Server with its BaseContext set to logger as its value. If srvLvl is valid then the http.Server's ErrorLog field will also be set, in which case the returned io.Closer should be closed when finished.

Types

type HTTPRequestLogAttributes

type HTTPRequestLogAttributes struct {
	Headers            []string
	Synthetics         map[string]func(*http.Request) string
	SyntheticsResponse map[string]func(ResponseWriter) string
	SkipDuration       bool
	SkipMethod         bool
	SkipPath           bool
	SkipRemoteAddr     bool
}

HTTPRequestLogAttributes allows us to inject two different ways to automatically log aspects of a request: headers and synthetics. Headers is a list of header names that will be set as fields in the log if they are present in the request; synthetics are fields generated from some combination or process applied to the request.

If desired, the default attributes may also be skipped.

type ResponseWriter added in v1.1.0

type ResponseWriter interface {
	http.ResponseWriter

	// StatusCode returns the status code of the response. If not written
	// yet, this returns 0.
	StatusCode() int

	// Status returns the HTTP/1.1-standard name for the status code. If
	// not written yet, this returns "".
	Status() string

	// BodySize returns the size of the response body.
	BodySize() int
}

ResponseWriter implements an interface that allows logging middleware access to standard information about the underlying response that is unattainable in the default http.ResponseWriter interface.

In order not to break basic net/http interfaces that are commonly implemented (http.Flusher, http.Hijacker, and http.Pusher), we handle these as well, passing to the underlying response writer if it implements them in turn.

One issue is that the available implementations will always fulfill http.Flusher if any of the above "alternate" interfaces is implemented. Even when the underlying response writer is only http.Hijacker or http.Pusher, the wrapper implements http.Flusher. While this mirrors the most common types (the standard HTTP/1.1 and HTTP/2 response writers, eg, all implement flusher), it may lead to false positive http.Flusher type assertions. Since an unimplemented call to Flush is a no-op, this can be regarded as a minor issue.

Does not hold a separate response body buffer. Log in the application for this sort of data.

func NewResponseWriter added in v1.1.0

func NewResponseWriter(w http.ResponseWriter) ResponseWriter

NewResponseWriter returns a logging-specific ResponseWriter that wraps an http.ResponseWriter, for use in logging middleware.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL