Documentation
¶
Index ¶
- Variables
- type Embed
- type Error
- type Handler
- func NewApiKey(key string) Handler
- func NewApiKeyFunc(check func(string) error) Handler
- func NewBasicAuth(username, password string) Handler
- func NewBasicAuthFunc(check func(username, password string) error) Handler
- func NewHandlerFunc(f func(c *RequestContext) error) Handler
- func NewProxy(target string) (Handler, error)
- func NewWrapper(handler http.Handler) Handler
- func NewWrapperFunc(handlerFunc http.HandlerFunc) Handler
- func NoRobotsPlease() Handler
- func Static(mimetype string, content []byte) Handler
- func StaticJSON(data any) Handler
- type HandlerFunc
- type Handlers
- type Method
- type Methods
- type RequestContext
- func (c *RequestContext) Close() error
- func (c *RequestContext) Context() context.Context
- func (c *RequestContext) Cookie(name string) (*http.Cookie, error)
- func (c *RequestContext) Error(err error) error
- func (c *RequestContext) Flusher() (http.Flusher, bool)
- func (c *RequestContext) Header(name string) string
- func (c *RequestContext) Host() string
- func (c *RequestContext) IsLocal() bool
- func (c *RequestContext) Method() Method
- func (c *RequestContext) Param(name string) string
- func (c *RequestContext) Path() string
- func (c *RequestContext) Printf(format string, args ...any) error
- func (c *RequestContext) Query() url.Values
- func (c *RequestContext) Read(p []byte) (n int, err error)
- func (c *RequestContext) ReadFrom(r io.Reader) (n int64, err error)
- func (c *RequestContext) ReadJSON(target any) error
- func (c *RequestContext) Redirect(url string) error
- func (c *RequestContext) RedirectPermanent(url string) error
- func (c *RequestContext) RedirectTemp(url string) error
- func (c *RequestContext) ServeFile(name string) error
- func (c *RequestContext) SetContext(ctx context.Context)
- func (c *RequestContext) SetCookie(cookie *http.Cookie)
- func (c *RequestContext) SetHeader(key, value string)
- func (c *RequestContext) Status(status int) error
- func (c *RequestContext) StatusPrintf(statusCode int, format string, args ...any) error
- func (c *RequestContext) TLS() *tls.ConnectionState
- func (c *RequestContext) URL() *url.URL
- func (c *RequestContext) Write(body []byte) (n int, err error)
- func (c *RequestContext) WriteBytes(mimetype string, body []byte) error
- func (c *RequestContext) WriteJSON(data any) error
- func (c *RequestContext) WriteTo(w io.Writer) (n int64, err error)
- type Router
- func (r *Router) AddDefault(methods Methods, handlers ...Handler) *route
- func (r *Router) AddDefaultFunc(methods Methods, handlerFunc ...func(*RequestContext) error) *route
- func (r *Router) AddExact(methods Methods, exact string, handlers ...Handler) *route
- func (r *Router) AddExactFunc(methods Methods, exact string, handlerFunc ...func(*RequestContext) error) *route
- func (r *Router) AddPattern(methods Methods, pattern string, handlers ...Handler) *route
- func (r *Router) AddPatternFunc(methods Methods, pattern string, handlerFuncs ...func(*RequestContext) error) *route
- func (r *Router) AddPrefix(methods Methods, prefix string, handlers ...Handler) *route
- func (r *Router) AddPrefixFunc(methods Methods, prefix string, handlerFunc ...func(*RequestContext) error) *route
- func (r *Router) Serve(c *RequestContext) error
- func (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request)
- type SSE
- type StatusError
Examples ¶
Constants ¶
This section is empty.
Variables ¶
var ( GET = Methods{MethodGet} HEAD = Methods{MethodHead} POST = Methods{MethodPost} PUT = Methods{MethodPut} DELETE = Methods{MethodDelete} CONNECT = Methods{MethodConnect} OPTIONS = Methods{MethodOptions} TRACE = Methods{MethodTrace} PATCH = Methods{MethodPatch} ANY = Methods{MethodAny} )
Predefined Methods slices for common HTTP methods.
var ErrBadRequest = NewStatusError(http.StatusBadRequest, "bad request")
ErrBadRequest is an error that indicates that the request was malformed or invalid. Will return a 400 Bad Request status code. This is a generic error that can be used by handlers to indicate that the request was invalid, but it is not very specific. If you want to provide more information about the error, you should use NewStatusError(http.StatusBadRequest, "... %w", err) to create a more specific error.
var ErrForbidden = NewStatusError(http.StatusForbidden, "forbidden")
ErrForbidden is an error that indicates that the client is forbidden from accessing the requested resource. Will return a 403 Forbidden status code.
var ErrMethodNotAllowed = NewStatusError(http.StatusMethodNotAllowed, "method not allowed")
ErrMethodNotAllowed is an error that indicates that the requested method is not allowed for the requested resource. Will return a 405 Method Not Allowed status code.
var ErrNotAuthorized = NewStatusError(http.StatusUnauthorized, "unauthorized")
ErrNotAuthorized is an error that indicates that the client is not authorized to access the requested resource. Will return a 401 Unauthorized status code.
var ErrNotFound = NewStatusError(http.StatusNotFound, "not found")
ErrNotFound is an error that indicates that the requested resource was not found. Will return a 404 Not Found status code.
var ErrStopPropagation = errors.New("stop propagation")
ErrStopPropagation is returned by a handler to indicate that the router should stop processing the request and not continue to the next handler in the chain. This is useful for handlers that want to short-circuit the request processing, such as authentication or authorization handlers.
Functions ¶
This section is empty.
Types ¶
type Embed ¶
type Embed []byte
Embed is a type that represents embedded content. It is a simple wrapper around a byte slice, and it can be used to serve static files that are embedded in the binary using the //go:embed directive.
func NewEmbed ¶
NewEmbed creates a new Embed instance from the given byte slice. This function is useful when you want to serve static content that is generated on startup. If you have static content that is known at compile time, you can use the //go:embed directive to embed the content directly in your binary using the Embed type.
func (*Embed) Serve ¶
func (e *Embed) Serve(c *RequestContext) error
Serve implements the Handler interface. It serves the embedded content with the MIME type "application/octet-stream".
func (*Embed) SetContentType ¶
SetContentType allows you to set a custom Content-Type for the embedded content. This is useful if you want to serve the content with a specific MIME type that cannot be automatically detected.
type Error ¶
type Error interface {
error
// WriteTo writes the error to the response. This is called by
// the Router when an Error is returned by a Handler. The error
// should write the appropriate status code and response body to
// the RequestContext.
WriteTo(*RequestContext) error
}
Error is an error that can be returned by a Handler to show an error to the client. All other errrors than this will be treated as internal server errors and will return a 500 Internal Server StatusError status code and not display the error message in the response body.
type Handler ¶
type Handler interface {
Serve(*RequestContext) error
}
Handler is the interface that wraps the Serve method, which handles an HTTP request and writes a response.
func NewApiKey ¶
NewApiKey creates a new ApiKey middleware that checks for a static API key.
Example ¶
package main
import (
"net/http"
"github.com/abrander/webber"
)
func main() {
// Expose our API protected by an API key.
apiAuth := webber.NewApiKey("secret-key")
api := webber.NewRouter(apiAuth)
api.AddExact(webber.GET, "/demo", nil)
// ... and our UI protected by basic auth.
uiAuth := webber.NewBasicAuth("admin", "secret-password")
ui := webber.NewRouter(uiAuth)
ui.AddExact(webber.GET, "/demo", nil)
r := webber.NewRouter()
r.AddPrefix(webber.GET, "/api", api)
r.AddPrefix(webber.GET, "/ui", ui)
_ = http.ListenAndServe(":8080", r)
}
Output:
func NewApiKeyFunc ¶
NewApiKeyFunc creates a new ApiKey middleware that checks the API key using a custom function. The function should return an error if the key is invalid, or nil if it is valid.
func NewBasicAuth ¶
NewBasicAuth creates a new BasicAuth instance with the given username and password.
func NewBasicAuthFunc ¶
NewBasicAuthFunc creates a new BasicAuth instance with the given check function. The check function should return nil if the username and password are valid, and an error otherwise.
func NewHandlerFunc ¶
func NewHandlerFunc(f func(c *RequestContext) error) Handler
NewHandlerFunc creates a new HandlerFunc from the given function.
func NewProxy ¶
NewProxy creates a new Handler that proxies requests to the given target URL. If the target URL is invalid, an error will be returned.
func NewWrapper ¶
NewWrapper creates a new Handler instance with the given http.Handler.
func NewWrapperFunc ¶
func NewWrapperFunc(handlerFunc http.HandlerFunc) Handler
NewWrapperFunc creates a new Handler instance from an http.HandlerFunc.
func NoRobotsPlease ¶
func NoRobotsPlease() Handler
NoRobotsPlease returns a Handler that serves a robots.txt file that disallows all web crawlers from indexing the site. Please note that this will not prevent any crawlers from accessing the site, but it will signal to well-behaved crawlers that they should not index the site.
func StaticJSON ¶
StaticJSON returns a Handler that serves the given data as JSON. It panics if the data cannot be marshaled to JSON, so it should only be used with static data that is known to be JSON-serializable.
type HandlerFunc ¶
type HandlerFunc func(c *RequestContext) error
HandlerFunc is an adapter type that allows ordinary functions to be used as HTTP handlers.
func (HandlerFunc) Serve ¶
func (f HandlerFunc) Serve(c *RequestContext) error
Serve implements Handler.
type Handlers ¶
type Handlers []Handler
Handlers is a slice of Handler that can be used to chain multiple handlers together.
func (Handlers) Serve ¶
func (h Handlers) Serve(c *RequestContext) error
Serve implements Handler. It calls each handler in the slice in order until one of them returns an error. If a handler returns an error, the remaining handlers will not be called and the error will be returned to the caller.
type Method ¶
type Method string
Method is a type that represents an HTTP method.
type Methods ¶
type Methods []Method
Methods is a slice of Method that can be used to specify which HTTP methods a handler should respond to. The Contains method can be used to check if a Method is in the slice. The special MethodAny can be used to indicate that the handler should respond to all methods.
type RequestContext ¶
type RequestContext struct {
// contains filtered or unexported fields
}
RequestContext provides a convenient interface for handling HTTP requests and responses.
func NewRequestContext ¶
func NewRequestContext(w http.ResponseWriter, r *http.Request) *RequestContext
NewRequestContext creates a new RequestContext for the given http.ResponseWriter and http.Request.
func (*RequestContext) Close ¶
func (c *RequestContext) Close() error
Close closes the request body. This is a no-op if the body has already been closed.
func (*RequestContext) Context ¶
func (c *RequestContext) Context() context.Context
Context returns the context.Context associated with the request.
func (*RequestContext) Cookie ¶
func (c *RequestContext) Cookie(name string) (*http.Cookie, error)
Cookie returns the named cookie provided in the request or http.ErrNoCookie if not found. If multiple cookies match the given name, only one cookie will be returned.
func (*RequestContext) Error ¶
func (c *RequestContext) Error(err error) error
Error handles an error that occurred during request processing. It sets the appropriate HTTP status code and writes the error message to the response body. If the error is a context.Canceled error, it will return a 408 Request Timeout status. If the error is a webber Error, it will use the status code and message from the error. Otherwise, it will return a 500 Internal Server Error status with the error message.
func (*RequestContext) Flusher ¶
func (c *RequestContext) Flusher() (http.Flusher, bool)
Flusher returns the http.Flusher interface if the underlying http.ResponseWriter supports it, along with a boolean indicating whether the interface is supported.
func (*RequestContext) Header ¶
func (c *RequestContext) Header(name string) string
Header returns the value of the specified header from the request.
func (*RequestContext) Host ¶
func (c *RequestContext) Host() string
Host returns the host of the request, including the port if specified. For example, "example.com:8080".
func (*RequestContext) IsLocal ¶
func (c *RequestContext) IsLocal() bool
IsLocal returns true if the request is from a local IP address.
func (*RequestContext) Method ¶
func (c *RequestContext) Method() Method
Method returns the HTTP method of the request.
func (*RequestContext) Param ¶
func (c *RequestContext) Param(name string) string
Param returns the value of a named path parameter captured by pattern routing (e.g. the "{id}" in AddPattern("/sessions/{id}", ...)). Returns an empty string if the parameter was not captured.
func (*RequestContext) Path ¶
func (c *RequestContext) Path() string
Path returns the path of the request, without the query string. For example, if the request URL is "/foo/bar?baz=qux", this will return "/foo/bar". If the request URL is "/", this will return "/".
func (*RequestContext) Printf ¶
func (c *RequestContext) Printf(format string, args ...any) error
Printf writes a formatted string to the response body. If the HTTP status code has not been set yet, it will default to 200 OK.
func (*RequestContext) Query ¶
func (c *RequestContext) Query() url.Values
Query returns the query parameters of the request as a url.Values map. For example, if the request URL is "/foo?bar=baz&qux=quux", this will return url.Values{"bar": {"baz"}, "qux": {"quux"}}. If the request URL does not contain a query string, this will return an empty url.Values map.
func (*RequestContext) Read ¶
func (c *RequestContext) Read(p []byte) (n int, err error)
Read reads bytes from the request body. Implements io.Reader.
func (*RequestContext) ReadFrom ¶
func (c *RequestContext) ReadFrom(r io.Reader) (n int64, err error)
ReadFrom reads data from an io.Reader and writes it to the response body. Implements io.ReaderFrom.
func (*RequestContext) ReadJSON ¶
func (c *RequestContext) ReadJSON(target any) error
ReadJSON reads JSON from the request body and unmarshals it into the provided target. It returns an error if the JSON is invalid or if there are unknown fields in the JSON that do not match the target struct. The target must be a pointer to a struct or a map.
func (*RequestContext) Redirect ¶
func (c *RequestContext) Redirect(url string) error
Redirect sends a redirect response to the client, with the given URL as the Location header. The status code will be 302 Found.
func (*RequestContext) RedirectPermanent ¶
func (c *RequestContext) RedirectPermanent(url string) error
RedirectPermanent sends a permanent redirect response to the client, with the given URL as the Location header.
func (*RequestContext) RedirectTemp ¶
func (c *RequestContext) RedirectTemp(url string) error
RedirectTemp sends a temporary redirect response to the client, with the given URL as the Location header.
func (*RequestContext) ServeFile ¶
func (c *RequestContext) ServeFile(name string) error
ServeFile serves a file from the given path. If the file does not exist, it will return a 404 Not Found status. If there is an error opening or reading the file, it will return a 500 Internal Server Error status.
func (*RequestContext) SetContext ¶
func (c *RequestContext) SetContext(ctx context.Context)
SetContext sets the context.Context associated with the request.
func (*RequestContext) SetCookie ¶
func (c *RequestContext) SetCookie(cookie *http.Cookie)
SetCookie adds a Set-Cookie header to the provided RequestContext's headers. The provided cookie must have a valid Name. Invalid cookies may be silently dropped.
func (*RequestContext) SetHeader ¶
func (c *RequestContext) SetHeader(key, value string)
SetHeader sets a header key and value for the response.
func (*RequestContext) Status ¶
func (c *RequestContext) Status(status int) error
Status sets the HTTP status code for the response. It returns an error if the status code has already been sent.
func (*RequestContext) StatusPrintf ¶
func (c *RequestContext) StatusPrintf(statusCode int, format string, args ...any) error
StatusPrintf sets the HTTP status code and writes a formatted string to the response body. It will behave like Status followed by Printf. If the status code has already been written, this will *not* return an error, but simply write the formatted string to the body.
func (*RequestContext) TLS ¶
func (c *RequestContext) TLS() *tls.ConnectionState
TLS returns the TLS connection state of the request, or nil if the request is not using HTTPS.
func (*RequestContext) URL ¶
func (c *RequestContext) URL() *url.URL
URL returns the URL of the request.
func (*RequestContext) Write ¶
func (c *RequestContext) Write(body []byte) (n int, err error)
Write writes bytes to the response body. If the HTTP status code has not been set yet, it will default to 200 OK. Implements io.Writer.
func (*RequestContext) WriteBytes ¶
func (c *RequestContext) WriteBytes(mimetype string, body []byte) error
WriteBytes writes bytes to the response body with the given MIME type. If the HTTP status code has not been set yet, it will default to 200 OK.
func (*RequestContext) WriteJSON ¶
func (c *RequestContext) WriteJSON(data any) error
WriteJSON writes the given data as JSON to the response body. It sets the Content-Type header to "application/json". If the data cannot be marshaled to JSON, it will return an error. If the HTTP status code has not been set yet, it will default to 200 OK.
Example ¶
package main
import (
"net/http"
"github.com/abrander/webber"
)
func main() {
type User struct {
UID int `json:"uid"`
Name string `json:"name"`
}
r := webber.NewRouter()
r.AddExact(webber.GET, "/test", webber.HandlerFunc(func(c *webber.RequestContext) error {
user := User{
UID: 123,
Name: "Alice",
}
return c.WriteJSON(user)
}))
_ = http.ListenAndServe(":8080", r)
}
Output:
type Router ¶
type Router struct {
// contains filtered or unexported fields
}
Router is a Handler that routes requests to different handlers based on the request path and method. It supports exact matches, prefix matches, and pattern matches with named parameters.
func NewRouter ¶
NewRouter creates a new Router with the given handlers. The handlers will be executed in order for every request before the router attempts to match the request to a route.
func (*Router) AddDefault ¶
AddDefault adds a route that matches any path, which is useful for fall-back handlers that should run if no other routes match. If multiple default routes are added, it is undefined which one will be used.
func (*Router) AddDefaultFunc ¶
func (r *Router) AddDefaultFunc(methods Methods, handlerFunc ...func(*RequestContext) error) *route
AddDefaultFunc is a convenience wrapper around AddDefault that accepts handler functions instead of Handler interfaces.
func (*Router) AddExact ¶
AddExact adds a route that matches exactly the given path. For example, an exact path of "/api/foo" would match only "/api/foo", and not "/api/foo/bar" or "/api/foo/".
func (*Router) AddExactFunc ¶
func (r *Router) AddExactFunc(methods Methods, exact string, handlerFunc ...func(*RequestContext) error) *route
AddExactFunc is a convenience wrapper around AddExact that accepts handler functions instead of Handler interfaces.
func (*Router) AddPattern ¶
AddPattern adds a route with the given pattern, which may include named parameters in the form "{param}". For example, the pattern "/route/{id}/blah" would match paths like "/route/123/blah", capturing "123" as the "id" parameter. The pattern is parsed into segments, and the most specific patterns are matched first.
func (*Router) AddPatternFunc ¶
func (r *Router) AddPatternFunc(methods Methods, pattern string, handlerFuncs ...func(*RequestContext) error) *route
AddPatternFunc is a convenience wrapper around AddPattern that accepts handler functions instead of Handler interfaces.
func (*Router) AddPrefix ¶
AddPrefix adds a route that matches any path with the given prefix. For example, a prefix of "/api" would match "/api", "/api/foo", "/api/bar/baz", etc. Longer prefixes are matched before shorter ones, so a route with prefix "/api/foo" would be matched before a route with prefix "/api".
func (*Router) AddPrefixFunc ¶
func (r *Router) AddPrefixFunc(methods Methods, prefix string, handlerFunc ...func(*RequestContext) error) *route
AddPrefixFunc is a convenience wrapper around AddPrefix that accepts handler functions instead of Handler interfaces.
func (*Router) Serve ¶
func (r *Router) Serve(c *RequestContext) error
Serve implements the Handler interface. It executes the router's handlers, then attempts to match the request to a route. If a matching route is found, it executes the route's handlers. If no matching route is found, it returns a 404 Not Found status. If a matching route is found but the method is not allowed, it returns a 405 Method Not Allowed status.
func (*Router) ServeHTTP ¶
func (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request)
ServeHTTP implements the http.Handler interface. It creates a new RequestContext for the request and passes it to the router's Serve method. If an error occurs, it writes the appropriate HTTP status code and error message to the response.
type SSE ¶
type SSE[T any] struct { // contains filtered or unexported fields }
SSE is a generic type that implements Server-Sent Events (SSE) for broadcasting events to multiple clients. It allows you to send events of any type T to all connected clients. The type T must be JSON-serializable, as the events are sent in JSON format.
func NewSSE ¶
NewSSE creates a new SSE instance for broadcasting events of type T. The type T must be JSON-serializable, as the events are sent in JSON format. If T is not JSON-serializable, this function will panic.
func (*SSE[T]) BroadcastEvent ¶
BroadcastEvent broadcasts an event with the given name and data to all connected clients. The data is marshaled to JSON format before being sent. If the data cannot be marshaled to JSON, an error is returned. If a client's channel is full, the event will be skipped for that client to avoid blocking.
func (*SSE[T]) Serve ¶
func (s *SSE[T]) Serve(c *RequestContext) error
Serve implements the Handler interface. It serves the SSE stream to clients. It checks the "Accept" header to ensure that the client supports SSE, and it sets the appropriate headers for the SSE response. It listens for events and sends them to the client in real-time. If the client disconnects, it cleans up the listener.
type StatusError ¶
StatusError is an error that can be returned by a Handler to indicate that an error occurred. It contains an HTTP status code and a message that will be sent in the response body.
func NewStatusError ¶
func NewStatusError(status int, format string, args ...any) *StatusError
NewStatusError creates a new Error with the given status code and message. This should only be used by handlers to create errors that will be returned to the client.
func (*StatusError) Error ¶
func (e *StatusError) Error() string
Error implements the error interface.
func (*StatusError) WriteTo ¶
func (e *StatusError) WriteTo(c *RequestContext) error
WriteTo implements the Error interface.