httph

package module
v0.4.1 Latest Latest
Warning

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

Go to latest
Published: Oct 6, 2026 License: MIT Imports: 13 Imported by: 3

README

httph

GoDoc CI

HTTP helpers and middleware. H is for helpful!

go get maragu.dev/httph

Made with ✨sparkles✨ by maragu: independent software consulting for cloud-native Go apps & AI engineering.

Contact me at markus@maragu.dk for consulting work, or perhaps an invoice to support this project?

Documentation

Overview

Package httph provides HTTP helpers and middleware compatible with net/http.

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func ErrorHandler added in v0.3.6

func ErrorHandler(h func(http.ResponseWriter, *http.Request) error) http.HandlerFunc

ErrorHandler takes a function that is like a regular http.HandlerFunc from the standard library, except it also returns an error. If the error implements the statusCodeGiver interface, it returns that status code. Otherwise, it defaults to HTTP 500.

Example
package main

import (
	"fmt"
	"io"
	"net/http"
	"net/http/httptest"

	_ "embed"
	"maragu.dev/httph"
)

func main() {
	h := httph.ErrorHandler(func(w http.ResponseWriter, r *http.Request) error {
		return httph.HTTPError{Code: http.StatusTeapot}
	})

	// Error case
	w := httptest.NewRecorder()
	h.ServeHTTP(w, httptest.NewRequest(http.MethodGet, "/", nil))
	body, _ := io.ReadAll(w.Result().Body)
	fmt.Println(string(body))
}
Output:
I'm a teapot

func FormHandler

func FormHandler[Req any](h func(http.ResponseWriter, *http.Request, Req)) http.HandlerFunc

FormHandler takes a function that is like a regular http.Handler, except it also receives a struct with values parsed from http.Request.ParseForm. Any parsing errors will result in http.StatusBadRequest. Uses reflection under the hood. If the request struct satisfies the validator interface, also use it to validate the struct.

Example
package main

import (
	"fmt"
	"io"
	"net/http"
	"net/http/httptest"
	"net/url"
	"strings"

	_ "embed"
	"maragu.dev/httph"
)

func main() {
	type Req struct {
		Name string
		Age  int
	}

	h := httph.FormHandler(func(w http.ResponseWriter, r *http.Request, req Req) {
		_, _ = fmt.Fprintf(w, "Hello %v, you are %v years old", req.Name, req.Age)
	})

	w := httptest.NewRecorder()
	vs := url.Values{
		"name": {"World"},
		"age":  {"20"},
	}
	r := httptest.NewRequest(http.MethodPost, "/", strings.NewReader(vs.Encode()))
	r.Header.Set("Content-Type", "application/x-www-form-urlencoded")
	h.ServeHTTP(w, r)

	body, _ := io.ReadAll(w.Result().Body)
	fmt.Println(string(body))
}
Output:
Hello World, you are 20 years old

func JSONHandler added in v0.3.2

func JSONHandler[Req any, Res any](h func(http.ResponseWriter, *http.Request, Req) (Res, error)) http.HandlerFunc

JSONHandler takes a function that is like a regular http.Handler, except it also receives a struct with values parsed from the request body as JSON. The function also returns a struct that will be encoded as JSON in the response. If either the response struct or error satisfy the statusCodeGiver interface, the given HTTP status code is returned.

Example
package main

import (
	"fmt"
	"io"
	"net/http"
	"net/http/httptest"
	"strings"

	_ "embed"
	"maragu.dev/httph"
)

func main() {
	type Req struct {
		Name string
	}

	type Res struct {
		Message string
	}

	h := httph.JSONHandler(func(w http.ResponseWriter, r *http.Request, req Req) (Res, error) {
		return Res{Message: "Hello " + req.Name}, nil
	})

	w := httptest.NewRecorder()
	h.ServeHTTP(w, httptest.NewRequest(http.MethodPost, "/", strings.NewReader(`{"Name":"World"}`)))

	body, _ := io.ReadAll(w.Result().Body)
	fmt.Println(string(body))
}
Output:
{"Message":"Hello World"}

func NoClickjacking

func NoClickjacking(next http.Handler) http.Handler

NoClickjacking is Middleware which sets headers to disallow frame embedding and XSS protection for older browsers. See https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options See https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-XSS-Protection

func NonceFromContext added in v0.4.0

func NonceFromContext(ctx context.Context) string

NonceFromContext returns the CSP nonce generated by the ContentSecurityPolicy Middleware for this request, or "" if none was generated.

func VersionedAssets added in v0.3.1

func VersionedAssets(next http.Handler) http.Handler

VersionedAssets is Middleware to help serve versioned assets without the version. It basically strips the version from the asset path and forwards the request, probably to a static file handler.

Types

type ContentSecurityPolicyOptions

type ContentSecurityPolicyOptions struct {
	ChildSrc       string
	ConnectSrc     string
	DefaultSrc     string
	FontSrc        string
	FrameSrc       string
	ImgSrc         string
	ManifestSrc    string
	MediaSrc       string
	ObjectSrc      string
	ScriptSrc      string
	ScriptSrcElem  string
	ScriptSrcAttr  string
	StyleSrc       string
	StyleSrcElem   string
	StyleSrcAttr   string
	WorkerSrc      string
	BaseURI        string
	Sandbox        string
	FormAction     string
	FrameAncestors string
	ReportTo       string

	// ScriptNonce generates a per-request nonce and appends 'nonce-<value>' to script-src,
	// or sets script-src to just the nonce if the directive is otherwise empty.
	// A non-empty ScriptSrcElem gets the nonce as well, while an empty one is left empty.
	// The nonce is available to handlers through [NonceFromContext].
	// Note that a nonce makes browsers ignore 'unsafe-inline' in the same directive, and that it doesn't
	// authorize inline event handler attributes, which ScriptSrcAttr governs.
	ScriptNonce bool

	// StyleNonce is like [ContentSecurityPolicyOptions.ScriptNonce], but for style-src and StyleSrcElem,
	// and doesn't authorize inline style attributes, which StyleSrcAttr governs.
	StyleNonce bool
}

ContentSecurityPolicyOptions for the ContentSecurityPolicy Middleware. The field names match policy directives, and only values should be supplied, so no directive names and delimiters. Only non-experimental, non-deprecated directives are included. Fields with a Nonce suffix are not directives, but switch on nonce generation for the matching directive. See https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy

type GoGetOptions

type GoGetOptions struct {
	Domain    string   // Domain to serve URLs for, for example: "maragu.dev"
	Modules   []string // Lit of module names, for example: "httph", "foo"
	URLPrefix string   // URL prefix to serve the module from, for example: "https://github.com/maragudk"
}

type HTTPError added in v0.3.5

type HTTPError struct {
	Code int
	Err  error
}

HTTPError is an [error] that can be used to return an HTTP status code with an error message.

func (HTTPError) Error added in v0.3.5

func (h HTTPError) Error() string

func (HTTPError) StatusCode added in v0.3.5

func (h HTTPError) StatusCode() int

func (HTTPError) Unwrap added in v0.4.1

func (h HTTPError) Unwrap() error

Unwrap returns the wrapped error, so errors.Is and errors.As can see it.

type Middleware

type Middleware = func(next http.Handler) http.Handler

Middleware is a function that takes an http.Handler and returns an http.Handler. This is a common middleware pattern in net/http.

func ContentSecurityPolicy

func ContentSecurityPolicy(optsFunc func(opts *ContentSecurityPolicyOptions)) Middleware

ContentSecurityPolicy is Middleware to set CSP headers. By default this is a strict policy, disallowing everything but images, styles, scripts, and fonts from 'self'. With ContentSecurityPolicyOptions.ScriptNonce or ContentSecurityPolicyOptions.StyleNonce, one per-request nonce is added to the enabled directives and passed to the next handler through NonceFromContext. Send responses carrying a nonce with Cache-Control: no-store, because a cache may refresh a stored response's headers from a 304 and pair an old body with a new nonce. See https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP See https://infosec.mozilla.org/guidelines/web_security#content-security-policy

func GoGet

func GoGet(opts GoGetOptions) Middleware

GoGet is Middleware to support redirecting go get requests to module VCS URLs, popularly known as vanity URLs. See https://www.maragu.dev/blog/til-http-middleware-for-custom-go-module-paths

Jump to

Keyboard shortcuts

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