Documentation
¶
Overview ¶
Package genhttp provides a generics-powered HTTP microframework for handling requests.
The genhttp microframework is really a small pattern around request handling. The pattern is that a request will be parsed, then validated, then executed. This is represented in code by making each endpoint a type, and giving them a `ParseRequest`, `ValidateRequest`, and `ExecuteRequest` method. A `Handle` helper function calls these functions in order, checking for errors in between and short-circuiting when they're found. Thanks to generics, these methods can operate on an endpoint-specific request type that gets created by the `ParseRequest` method and passed directly into subsequent methods.
This pattern is useful for doing unit testing, as it separates the three responsibilities of an HTTP endpoint into discrete functions and makes them accessible through a more constrained interface than an `http.Request` and a more easily-examined interface than an `http.ResponseWriter`. Rather than reducing requests and responses to byte slices, they can be handled as structured Go types.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func Handle ¶
func Handle[Request any, Response Responder](respCreator ResponseCreator[Response], handler Handler[Request, Response]) http.Handler
Handle provides an http.Handler that will call the passed Handler. `rf` is used to create a new instance of the Response type. Then the `ParseRequest` method of `h` will be called, followed by `ValidateRequest` and `ExecuteRequest`. At the end, the Response has its `Send` method called.
If at any point in this process the Response's `HasErrors` method returns `true`, the Response's `Send` method is called and the function returns.
Types ¶
type CookieWriter ¶ added in v0.2.0
type CookieWriter interface { // WriteCookies returns the cookies to write. An attempt is always made // to write cookies. WriteCookies() []*http.Cookie }
CookieWriter is an interface describing a Responder that sometimes responds by writing cookies to the client.
type Handler ¶
type Handler[Request any, Response Responder] interface { // ParseRequest turns an `http.Request` into the Request type passed // in, usually by parsing some encoding. The returned context.Context // will be used as the new request context; if in doubt, return the // context.Context passed as an argument. ParseRequest(context.Context, *http.Request, Response) (Request, context.Context) // ValidateRequest checks that the passed Request is valid, for // whatever definition of valid suits the endpoint. The returned // context.Context will be used as the new request context; if in // doubt, return the context.Context passed as an argument. ValidateRequest(context.Context, Request, Response) context.Context // ExecuteRequest performs the action described by the Request. It can // assume that the Request is valid. The returned context.Context will // be used as the new request context; if in doubt, return the // context.Context passed as an argument. ExecuteRequest(context.Context, Request, Response) context.Context }
Handler is an endpoint that is going to parse, validate, and execute an HTTP request. Its Request type parameter should be a type that can describe the request, usually a struct with JSON tags or something similar. The Response type parameter should be an implementation of the Responder interface, usually a pointer that can be modified in the ParseRequest, ValidateRequest, and ExecuteRequest methods.
type Redirecter ¶ added in v0.2.0
type Redirecter interface { // RedirectTo returns the URL to redirect to and the HTTP status code // to use when redirecting. If the status code returned is between 300 // and 399, inclusive, genhttp will call http.Redirect with the // returned URL and status code instead of calling Send. RedirectTo() (url string, status int) }
Redirecter is an interface describing a Responder that sometimes responds by redirecting the client.
type Responder ¶
type Responder interface { // HasErrors should return true if the response is considered an error // response and processing should not proceed. HasErrors() bool // Send writes the response to the http.ResponseWriter. Send(context.Context, http.ResponseWriter) // HandlePanic updates the Response in the face of a panic while // processing the request. HandlePanic(ctx context.Context, recoverArg any) }
Responder is an interface describing a response type.
type ResponseCreator ¶
type ResponseCreator[Response Responder] interface { NewResponse(context.Context, *http.Request) Response }
ResponseCreator is a factory type that is capable of generating new Responder instances that are ready to be used.
We use a type parameter here instead of using the interface directly because we want the response types to be able to be structs with encoding tags or whatever, and to have their fields be directly accessible without a type assertion, which the Responder interface isn't able to provide.