httputil2

package module
v0.0.0-...-1c4b4e4 Latest Latest
Warning

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

Go to latest
Published: Dec 1, 2023 License: ISC Imports: 18 Imported by: 1

README

httputil2 Build Status GoDoc

What should really be in golang's net/http/httputil package.

A collection of net/http utilities and middlewares to build your own stack.

Just pick and choose whatever is useful to you!

From the list of avaiable middlewares, here is the recommended order:

  • RequestIDMiddleware (left-most)
  • LogMiddleware
  • CleanPathMiddleware
  • GzipMiddleware
  • RecoveryMiddleware
  • Application code

License

All files in this projects are licensed under the ISC. See the LICENSE file for more details.

Documentation

Index

Examples

Constants

View Source
const (
	CommonLogFormat  = `%h %l %u %t "%r" %>s %b`
	CommonDateFormat = "02/Jan/2006:15:04:05 -0700"
)
View Source
const (
	HeaderOrigin                        = "Origin"
	HeaderAccessControlAllowCredentials = "Access-Control-Allow-Credentials"
	HeaderAccessControlAllowHeaders     = "Access-Control-Allow-Headers"
	HeaderAccessControlAllowOrigin      = "Access-Control-Allow-Origin"
	HeaderAccessControlAllowMethods     = "Access-Control-Allow-Methods"
	HeaderAccessControlRequestHeaders   = "Access-Control-Request-Headers"
	HeaderAccessControlRequestMethod    = "Access-Control-Request-Method"
	HeaderAccessControlExposeHeaders    = "Access-Control-Expose-Headers"
	HeaderAccessControlMaxAge           = "Access-Control-Max-Age"
)

CORS-specific HTTP header extensions

View Source
const (
	CONNECT = http.MethodConnect
	DELETE  = http.MethodDelete
	GET     = http.MethodGet
	HEAD    = http.MethodHead
	OPTIONS = http.MethodOptions
	PATCH   = http.MethodPatch // RFC 5789
	POST    = http.MethodPost
	PUT     = http.MethodPut
	TRACE   = http.MethodTrace
)

HTTP methods

View Source
const (
	HeaderAccept                  = "Accept"
	HeaderAcceptCharset           = "Accept-Charset"
	HeaderAcceptEncoding          = "Accept-Encoding"
	HeaderAcceptLanguage          = "Accept-Language"
	HeaderAcceptRanges            = "Accept-Ranges"
	HeaderAcceptPatch             = "Accept-Patch" // RFC 5789
	HeaderAge                     = "Age"
	HeaderAllow                   = "Allow"
	HeaderAllowPatch              = "Allow-Patch" // RFC 5741
	HeaderAuthorization           = "Authorization"
	HeaderCacheControl            = "Cache-Control"
	HeaderConnection              = "Connection"
	HeaderContentDisposition      = "Content-Disposition" // RFC 6266
	HeaderContentEncoding         = "Content-Encoding"
	HeaderContentLanguage         = "Content-Language"
	HeaderContentLength           = "Content-Length"
	HeaderContentLocation         = "Content-Location"
	HeaderContentRange            = "Content-Range"
	HeaderContentType             = "Content-Type"
	HeaderCookie                  = "Cookie"
	HeaderDate                    = "Date"
	HeaderETag                    = "ETag"
	HeaderExpect                  = "Expect"
	HeaderExpires                 = "Expires"
	HeaderFrom                    = "From"
	HeaderHost                    = "Host"
	HeaderIfMatch                 = "If-Match"
	HeaderIfModifiedSince         = "If-Modified-Since"
	HeaderIfNoneMatch             = "If-None-Match"
	HeaderIfRange                 = "If-Range"
	HeaderIfUnmodifiedSince       = "If-Unmodified-Since"
	HeaderKeepAlive               = "Keep-Alive"
	HeaderLastModified            = "Last-Modified"
	HeaderLocation                = "Location"
	HeaderMaxForwards             = "Max-Forwards"
	HeaderPragma                  = "Pragma"
	HeaderProxyAuthenticate       = "Proxy-Authenticate"
	HeaderProxyAuthorization      = "Proxy-Authorization"
	HeaderRange                   = "Range"
	HeaderReferer                 = "Referer"
	HeaderRetryAfter              = "Retry-After"
	HeaderServer                  = "Server"
	HeaderSetCookie               = "Set-Cookie"
	HeaderStrictTransportSecurity = "Strict-Transport-Security" // HSTS
	HeaderTE                      = "TE"
	HeaderTrailer                 = "Trailer"
	HeaderTransferEncoding        = "Transfer-Encoding"
	HeaderUpgrade                 = "Upgrade"
	HeaderUserAgent               = "User-Agent"
	HeaderVary                    = "Vary"
	HeaderVia                     = "Via"
	HeaderWWWAuthenticate         = "WWW-Authenticate"
	HeaderWarning                 = "Warning"
	HeaderXForwardedFor           = "X-Forwarded-For"
	HeaderXForwardedProto         = "X-Forwarded-Proto"
	HeaderXFrameOptions           = "X-Frame-Options" // RFC 7034
	HeaderXRequestID              = "X-Request-ID"
)

HTTP headers

Everything is from RFC2616 + CORS + RFC 5741 + De-facto extensions

View Source
const (
	StatusContinue           = 100
	StatusSwitchingProtocols = 101

	StatusOK                   = 200
	StatusCreated              = 201
	StatusAccepted             = 202
	StatusNonAuthoritativeInfo = 203
	StatusNoContent            = 204
	StatusResetContent         = 205
	StatusPartialContent       = 206

	StatusMultipleChoices   = 300
	StatusMovedPermanently  = 301
	StatusFound             = 302
	StatusSeeOther          = 303
	StatusNotModified       = 304
	StatusUseProxy          = 305
	StatusTemporaryRedirect = 307

	StatusBadRequest                   = 400
	StatusUnauthorized                 = 401
	StatusPaymentRequired              = 402
	StatusForbidden                    = 403
	StatusNotFound                     = 404
	StatusMethodNotAllowed             = 405
	StatusNotAcceptable                = 406
	StatusProxyAuthRequired            = 407
	StatusRequestTimeout               = 408
	StatusConflict                     = 409
	StatusGone                         = 410
	StatusLengthRequired               = 411
	StatusPreconditionFailed           = 412
	StatusRequestEntityTooLarge        = 413
	StatusRequestURITooLong            = 414
	StatusUnsupportedMediaType         = 415
	StatusRequestedRangeNotSatisfiable = 416
	StatusExpectationFailed            = 417
	StatusTeapot                       = 418
	StatusPreconditionRequired         = 428
	StatusTooManyRequests              = 429
	StatusRequestHeaderFieldsTooLarge  = 431
	StatusUnavailableForLegalReasons   = 451

	StatusInternalServerError           = 500
	StatusNotImplemented                = 501
	StatusBadGateway                    = 502
	StatusServiceUnavailable            = 503
	StatusGatewayTimeout                = 504
	StatusHTTPVersionNotSupported       = 505
	StatusNetworkAuthenticationRequired = 511
)
View Source
const JSONContentType = "application/json"

Variables

See http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html#sec13.5.1

Functions

func CommonLog

func CommonLog(w io.Writer) *commonLog

Implements the Apache Common Log Format formatting for the LogMiddleware See: https://httpd.apache.org/docs/1.3/logs.html Example:

CommonLog(os.Stdout)

FIXME: Tokenize the string upfront

func DefaultCallback

func DefaultCallback(err error)

func HeaderHas

func HeaderHas(h http.Header, key string, value string) bool

Checks each value of a header if it matches the value

func MemDir

func MemDir(path string) http.FileSystem

Returns a new http.FileSystem that is first loaded into memory.

Great when Disk IO is very slow.

func NewTraceFileSystem

func NewTraceFileSystem(f http.FileSystem) http.FileSystem

Used to debug http.FileSystem interfaces.

func NewTrackingListener

func NewTrackingListener(l net.Listener, wg sync.WaitGroup) net.Listener

A net.Listener that tracks the livelyhood of the connections such that the wg internal counter will go back to it's initial value once the listener and all it's issued net.Conn are closed.

This is useful for gracefully shutting down a server where first new connections are stoppped being accepted and then all the client connections are being shutdown as requests terminate.

Note that net/http.Server only provides HTTP/2 when ListenAndServeTLS is called directly (whereas here you would use the Serve(l) function).

Example
package main

import (
	"net"
	"net/http"
	"os"
	"os/signal"
	"sync"

	"github.com/zimbatm/httputil2"
)

func main() {
	// This WaitGroup is passed around and can be used to make sure everything
	// is finished.
	var done sync.WaitGroup

	// Setup the server
	s := http.Server{
		Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			w.Write([]byte("hello"))
		}),
	}

	// Listen to connections
	l, err := net.Listen("tcp", ":8080")
	if err != nil {
		panic(err)
	}
	// And track them
	l = httputil2.NewTrackingListener(l, done)

	// Setup signal handling
	c := make(chan os.Signal)
	signal.Notify(c, os.Interrupt, os.Kill)
	// Close the listener on signal
	go func() {
		<-c
		l.Close()
	}()

	err = s.Serve(l)
	if err != nil {
		panic(err)
	}

	done.Wait()
}
Output:

func WriteJSON

func WriteJSON(w http.ResponseWriter, v interface{}) (int, error)

func WriteJSONWithStatus

func WriteJSONWithStatus(w http.ResponseWriter, code int, v interface{}) (int, error)

Types

type BasicAuthChecker

type BasicAuthChecker func(user string, pass string, req *http.Request) bool

type Chain

type Chain []Middleware

A chain of middlewares

func NewChain

func NewChain(chain ...Middleware) Chain

func (Chain) Append

func (c Chain) Append(m ...Middleware) Chain

func (Chain) Handle

func (c Chain) Handle(h http.Handler) http.Handler

func (Chain) HandleFunc

func (c Chain) HandleFunc(h http.HandlerFunc) http.Handler

type ErrorCallback

type ErrorCallback func(error)

type HTTPLogger

type HTTPLogger interface {
	LogRequest(r *http.Request, start time.Time)
	LogResponse(r *http.Request, start time.Time, status int, bytes int)
}

type JSONData

type JSONData []byte

Data that's already been encoded to JSON

func (JSONData) MarshalJSON

func (b JSONData) MarshalJSON() ([]byte, error)

This is a NOOP

type MemRef

type MemRef struct {
	*bytes.Reader
	// contains filtered or unexported fields
}

func (*MemRef) Close

func (self *MemRef) Close() error

func (*MemRef) Readdir

func (self *MemRef) Readdir(n int) (files []os.FileInfo, err error)

Readdir reads the contents of the directory associated with file and returns a slice of up to n FileInfo values, as would be returned by Lstat, in directory order. Subsequent calls on the same file will yield further FileInfos.

If n > 0, Readdir returns at most n FileInfo structures. In this case, if Readdir returns an empty slice, it will return a non-nil error explaining why. At the end of a directory, the error is io.EOF.

If n <= 0, Readdir returns all the FileInfo from the directory in a single slice. In this case, if Readdir succeeds (reads all the way to the end of the directory), it returns the slice and a nil error. If it encounters an error before the end of the directory, Readdir returns the FileInfo read until that point and a non-nil error.

func (*MemRef) Stat

func (self *MemRef) Stat() (os.FileInfo, error)

type MemoryFile

type MemoryFile struct {
	// contains filtered or unexported fields
}

func (*MemoryFile) IsDir

func (self *MemoryFile) IsDir() bool

func (*MemoryFile) ModTime

func (self *MemoryFile) ModTime() time.Time

func (*MemoryFile) Mode

func (self *MemoryFile) Mode() os.FileMode

func (*MemoryFile) Name

func (self *MemoryFile) Name() string

func (*MemoryFile) Size

func (self *MemoryFile) Size() int64

func (*MemoryFile) Sys

func (self *MemoryFile) Sys() interface{}

type MemoryFileSystem

type MemoryFileSystem map[string]*MemoryFile

func NewMemoryFileSystem

func NewMemoryFileSystem() MemoryFileSystem

func (MemoryFileSystem) Add

func (self MemoryFileSystem) Add(name string, fi os.FileInfo, data []byte, err error)

func (MemoryFileSystem) AddDir

func (self MemoryFileSystem) AddDir(path string) (err error)

func (MemoryFileSystem) Open

func (self MemoryFileSystem) Open(name string) (http.File, error)

type Middleware

type Middleware func(http.Handler) http.Handler

func BasicAuthMiddleware

func BasicAuthMiddleware(h http.Handler, realm string, c BasicAuthChecker) Middleware

func CORSMiddleware

func CORSMiddleware(origin string, maxAge int) Middleware

func CleanPathMiddleware

func CleanPathMiddleware() Middleware

func GzipMiddleware

func GzipMiddleware(level int) Middleware

You can use gzip.DefaultCompression (-1) or any number between 0 (no compression) and 9 (best compression)

func LogMiddleware

func LogMiddleware(f HTTPLogger) Middleware

func RecoveryMiddleware

func RecoveryMiddleware(callback ErrorCallback) Middleware

Recovers when a panic happens on a request

func RequestIDMiddleware

func RequestIDMiddleware(g RequestIDGenerator) Middleware

Tags a request X-Request-ID header with a given ID from a RequestIDGenerator.

To be used with the uuid lib for example

If g is nil it will use a RandomIDGenerator(32)

type MiddlewareList

type MiddlewareList struct {
	Handler http.Handler
	// contains filtered or unexported fields
}

Deprecated, use httputil2.Chain instead

func (*MiddlewareList) Chain

func (ml *MiddlewareList) Chain() http.Handler

Puts the list of middleware together, with the last one being the provided ml.Handler.

func (*MiddlewareList) Use

func (ml *MiddlewareList) Use(ms ...Middleware)

Appends more middlewares to the stack

type RequestIDGenerator

type RequestIDGenerator func() string

func RandomIDGenerator

func RandomIDGenerator(size int) RequestIDGenerator

To be used with the IdHandler

size must be a power of 2

may fail if the random pool is exhausted

Directories

Path Synopsis
The package sse implements a http.Handler for the Server-Send-Event spec
The package sse implements a http.Handler for the Server-Send-Event spec

Jump to

Keyboard shortcuts

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