webber

package module
v0.0.0-...-44f4b64 Latest Latest
Warning

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

Go to latest
Published: Jul 26, 2026 License: MIT Imports: 15 Imported by: 0

README

webber

PkgGoDev

Stupid simple and pretty useless web framework for Go. It's only used for small personal projects, and is not intended for production use.

It's only published to make "go get" work, and to make it easier to share code between my own projects.

Documentation

Index

Examples

Constants

This section is empty.

Variables

Predefined Methods slices for common HTTP methods.

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

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

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

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

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

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

func NewEmbed(content []byte) *Embed

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

func (e *Embed) SetContentType(ct string)

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

func NewApiKey(key string) Handler

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)
}

func NewApiKeyFunc

func NewApiKeyFunc(check func(string) error) Handler

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

func NewBasicAuth(username, password string) Handler

NewBasicAuth creates a new BasicAuth instance with the given username and password.

func NewBasicAuthFunc

func NewBasicAuthFunc(check func(username, password string) error) Handler

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

func NewProxy(target string) (Handler, error)

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

func NewWrapper(handler http.Handler) Handler

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 Static

func Static(mimetype string, content []byte) Handler

Static returns a Handler that serves the given content with the specified MIME type.

func StaticJSON

func StaticJSON(data any) Handler

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.

const (
	MethodGet     Method = "GET"
	MethodHead    Method = "HEAD"
	MethodPost    Method = "POST"
	MethodPut     Method = "PUT"
	MethodDelete  Method = "DELETE"
	MethodConnect Method = "CONNECT"
	MethodOptions Method = "OPTIONS"
	MethodTrace   Method = "TRACE"
	MethodPatch   Method = "PATCH"
	MethodAny     Method = "*"
)

func (Method) Equal

func (m Method) Equal(other Method) bool

Equal checks if the given Method is equal to the current Method. It returns true if the current Method is MethodAny, or if the two Methods are equal.

func (Method) String

func (m Method) String() string

String returns the string representation of the 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.

func (Methods) Contains

func (m Methods) Contains(method Method) bool

Contains checks if the given Method is in the Methods slice. It returns true if the Method is in the slice or if the slice contains the special MethodAny.

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

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)
}

func (*RequestContext) WriteTo

func (c *RequestContext) WriteTo(w io.Writer) (n int64, err error)

WriteTo writes the request body to an io.Writer. If the HTTP status code has not been set yet, it will default to 200 OK.

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

func NewRouter(handlers ...Handler) *Router

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

func (r *Router) AddDefault(methods Methods, handlers ...Handler) *route

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

func (r *Router) AddExact(methods Methods, exact string, handlers ...Handler) *route

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

func (r *Router) AddPattern(methods Methods, pattern string, handlers ...Handler) *route

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

func (r *Router) AddPrefix(methods Methods, prefix string, handlers ...Handler) *route

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

func NewSSE[T any]() *SSE[T]

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

func (s *SSE[T]) BroadcastEvent(name string, data T) error

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

type StatusError struct {
	Status  int
	Message string
}

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.

Jump to

Keyboard shortcuts

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