httputil

package
v0.30.1 Latest Latest
Warning

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

Go to latest
Published: Nov 1, 2024 License: Unlicense Imports: 12 Imported by: 0

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

Examples

Constants

View Source
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

func CopyRequestTo(ctx context.Context, dst, src *http.Request)

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

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

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

type RouterFunc func(pattern string, h http.Handler)

RouterFunc is a functional implementation of the Router interface.

func (RouterFunc) Handle

func (f RouterFunc) Handle(pattern string, h http.Handler)

Handle implements the Router interface for RouterFunc.

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.

Jump to

Keyboard shortcuts

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