Documentation ¶
Overview ¶
Package httputil contains common constants, functions, and types for working with HTTP.
Example ¶
package main import ( "bytes" "context" "fmt" "io" "net/http" "net/http/httptest" "net/url" "time" "github.com/AdguardTeam/golibs/netutil/httputil" ) // must is a helper for tests. func must[T any](v T, err error) (res T) { if err != nil { panic(err) } return v } func main() { mux := http.NewServeMux() httputil.RoutePprof(mux) srv := httptest.NewServer(mux) defer srv.Close() u := must(url.Parse(srv.URL)).JoinPath(httputil.PprofBasePath) req := must(http.NewRequest(http.MethodGet, u.String(), nil)) ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second) defer cancel() req = req.WithContext(ctx) resp := must(http.DefaultClient.Do(req)) respBody := must(io.ReadAll(resp.Body)) lines := bytes.Split(respBody, []byte("\n")) for i := range 15 { fmt.Printf("%s\n", lines[i]) } fmt.Println("…") }
Output: <html> <head> <title>/debug/pprof/</title> <style> .profile-name{ display:inline-block; width:6rem; } </style> </head> <body> /debug/pprof/ <br> <p>Set debug=1 as a query parameter to export in legacy text format</p> <br> …
Index ¶
- Constants
- func CopyRequestTo(ctx context.Context, dst, src *http.Request)
- func RoutePprof(r Router)
- func Wrap(h http.Handler, middlewares ...Middleware) (wrapped http.Handler)
- type CodeRecorderResponseWriter
- func (w *CodeRecorderResponseWriter) Code() (code int)
- func (w *CodeRecorderResponseWriter) Header() (h http.Header)
- func (w *CodeRecorderResponseWriter) Reset(rw http.ResponseWriter)
- func (w *CodeRecorderResponseWriter) SetImplicitSuccess()
- func (w *CodeRecorderResponseWriter) Unwrap() (rw http.ResponseWriter)
- func (w *CodeRecorderResponseWriter) Write(b []byte) (n int, err error)
- func (w *CodeRecorderResponseWriter) WriteHeader(code int)
- type LogMiddleware
- type Middleware
- type PlainTextHandler
- type Router
- type RouterFunc
- type ServerHeaderMiddleware
- type Wrapper
Examples ¶
Constants ¶
const PprofBasePath = "/debug/pprof/"
PprofBasePath is the default base path used by RoutePprof.
Variables ¶
This section is empty.
Functions ¶
func CopyRequestTo ¶ added in v0.27.0
CopyRequestTo is an optimized version of http.Request.WithContext that uses compiler optimizations to allow reducing allocations with a pool. ctx, dst, and src must not be nil.
See https://github.com/golang/go/issues/68501#issuecomment-2234069762.
func RoutePprof ¶
func RoutePprof(r Router)
RoutePprof adds all pprof handlers to r under the paths within PprofBasePath.
func Wrap ¶
func Wrap(h http.Handler, middlewares ...Middleware) (wrapped http.Handler)
Wrap is a helper function that attaches the specified middlewares to the Handler. Middlewares will be called in the same order in which they were specified. That is, the first middleware will be the first to receive the request, and so on.
Example ¶
package main import ( "context" "fmt" "net/http" "net/http/httptest" "time" "github.com/AdguardTeam/golibs/netutil/httputil" ) // testMiddleware is a fake [httputil.Middleware] implementation for tests. type testMiddleware struct { OnWrap func(h http.Handler) (wrapped http.Handler) } // type check var _ httputil.Middleware = (*testMiddleware)(nil) // Wrap implements the [Middleware] interface for *testMiddleware. func (mw *testMiddleware) Wrap(h http.Handler) (wrapped http.Handler) { return mw.OnWrap(h) } func main() { mw1 := &testMiddleware{ OnWrap: func(h http.Handler) (wrapped http.Handler) { f := func(w http.ResponseWriter, r *http.Request) { fmt.Println("first middleware start") h.ServeHTTP(w, r) fmt.Println("first middleware end") } return http.HandlerFunc(f) }, } mw2 := &testMiddleware{ OnWrap: func(h http.Handler) (wrapped http.Handler) { f := func(w http.ResponseWriter, r *http.Request) { fmt.Println("second middleware start") h.ServeHTTP(w, r) fmt.Println("second middleware end") } return http.HandlerFunc(f) }, } var h http.Handler = http.HandlerFunc(func(_ http.ResponseWriter, _ *http.Request) { fmt.Println("handler") }) h = httputil.Wrap(h, mw1, mw2) ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second) defer cancel() w := httptest.NewRecorder() r := httptest.NewRequest(http.MethodGet, testPath, nil).WithContext(ctx) h.ServeHTTP(w, r) }
Output: first middleware start second middleware start handler second middleware end first middleware end
Types ¶
type CodeRecorderResponseWriter ¶
type CodeRecorderResponseWriter struct {
// contains filtered or unexported fields
}
CodeRecorderResponseWriter wraps an http.ResponseWriter allowing to save the response code.
Instances must be initialized either with NewCodeRecorderResponseWriter or by calling CodeRecorderResponseWriter.Reset.
func NewCodeRecorderResponseWriter ¶
func NewCodeRecorderResponseWriter(rw http.ResponseWriter) (w *CodeRecorderResponseWriter)
NewCodeRecorderResponseWriter returns a new *CodeRecorderResponseWriter which uses the given response writer as its base.
func (*CodeRecorderResponseWriter) Code ¶
func (w *CodeRecorderResponseWriter) Code() (code int)
Code returns the status code that was set. It expects that CodeRecorderResponseWriter.SetImplicitSuccess has already been called.
func (*CodeRecorderResponseWriter) Header ¶
func (w *CodeRecorderResponseWriter) Header() (h http.Header)
Header implements http.ResponseWriter for *CodeRecorderResponseWriter.
func (*CodeRecorderResponseWriter) Reset ¶ added in v0.27.0
func (w *CodeRecorderResponseWriter) Reset(rw http.ResponseWriter)
Reset allows reusing w by setting rw as the response writer and setting the code to zero.
func (*CodeRecorderResponseWriter) SetImplicitSuccess ¶
func (w *CodeRecorderResponseWriter) SetImplicitSuccess()
SetImplicitSuccess should be called after the handler has finished to set the status code to http.StatusOK if it hadn't been set explicitly. This can be used to detect panics within handlers, as when a handler panics before calling w.WriteHeader, SetImplicitSuccess isn't reached, and w.Code returns 0 and false.
func (*CodeRecorderResponseWriter) Unwrap ¶
func (w *CodeRecorderResponseWriter) Unwrap() (rw http.ResponseWriter)
Unwrap implements the Wrapper interface for *CodeRecorderResponseWriter.
func (*CodeRecorderResponseWriter) Write ¶
func (w *CodeRecorderResponseWriter) Write(b []byte) (n int, err error)
Write implements http.ResponseWriter for *CodeRecorderResponseWriter.
func (*CodeRecorderResponseWriter) WriteHeader ¶
func (w *CodeRecorderResponseWriter) WriteHeader(code int)
WriteHeader implements http.ResponseWriter for *CodeRecorderResponseWriter.
type LogMiddleware ¶
type LogMiddleware struct {
// contains filtered or unexported fields
}
LogMiddleware adds a logger using slogutil.ContextWithLogger and logs the starts and ends of queries at a given level.
func NewLogMiddleware ¶
func NewLogMiddleware(l *slog.Logger, lvl slog.Level) (mw *LogMiddleware)
NewLogMiddleware returns a new *LogMiddleware with l as the base logger.
func (*LogMiddleware) Wrap ¶
func (mw *LogMiddleware) Wrap(h http.Handler) (wrapped http.Handler)
Wrap implements the Middleware interface for *LogMiddleware.
type Middleware ¶
type Middleware interface { // Wrap returns a new handler that wraps the specified handler. Wrap(handler http.Handler) (wrapped http.Handler) }
Middleware is a common HTTP middleware interface.
type PlainTextHandler ¶
type PlainTextHandler string
PlainTextHandler is a simple handler that returns the value of the underlying string with a "text/plain" content type. If there is an error during the response writing, it gets the logger from the context, if any, and writes the error there at the debug level.
const HealthCheckHandler PlainTextHandler = "OK\n"
HealthCheckHandler is the common healthcheck HTTP handler that writes the text "OK\n" into the response. These are typically used for the GET /health-check HTTP API.
func (PlainTextHandler) ServeHTTP ¶
func (text PlainTextHandler) ServeHTTP(w http.ResponseWriter, r *http.Request)
ServeHTTP implements the http.Handler interface for PlainTextHandler.
type Router ¶
type Router interface { // Handle registers the handler for the given pattern. Handle(pattern string, h http.Handler) }
Router is the interface for HTTP routers, such as *http.ServeMux.
type RouterFunc ¶
RouterFunc is a functional implementation of the Router interface.
type ServerHeaderMiddleware ¶
type ServerHeaderMiddleware string
ServerHeaderMiddleware adds a Server HTTP header to all responses.
func (ServerHeaderMiddleware) Wrap ¶
func (mw ServerHeaderMiddleware) Wrap(h http.Handler) (wrapped http.Handler)
Wrap implements the Middleware interface for *ServerHeaderMiddleware.
type Wrapper ¶
type Wrapper interface {
Unwrap() (rw http.ResponseWriter)
}
Wrapper is a copy of the hidden rwUnwrapper interface from the Go standard library. It is added here for tests, linting, etc.