Documentation
¶
Overview ¶
Package noy adds typed, request-local state to applications built on net/http.
The core idea is that an application defines one state type for values that live for a single request. Middleware can populate that state with data such as authenticated users, request IDs, or loaded domain objects, and handlers can read those values through ordinary Go fields.
noy keeps routing and handler composition close to the standard library. The additional convention is explicit state passing, which keeps request-local data visible to the compiler instead of hiding it behind context keys.
Index ¶
- type HandlerFunc
- type ServeMux
- func (m *ServeMux[State]) Handle(pattern string, handler http.Handler)
- func (m *ServeMux[State]) HandleFunc(pattern string, handler HandlerFunc[State])
- func (m *ServeMux[State]) HandleStdFunc(pattern string, handler http.HandlerFunc)
- func (m *ServeMux[State]) ServeHTTP(w http.ResponseWriter, r *http.Request)
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type HandlerFunc ¶
type HandlerFunc[State any] func(state *State, w http.ResponseWriter, r *http.Request)
HandlerFunc is a typed HTTP handler.
The state pointer is request-local and is passed before the ordinary http.ResponseWriter and *http.Request arguments.
type ServeMux ¶
type ServeMux[State any] struct { // contains filtered or unexported fields }
ServeMux is a typed wrapper around http.ServeMux.
Handlers registered with HandleFunc receive a new *State for every request. The mux still implements http.Handler, so it can be used anywhere a standard net/http handler is accepted.
func NewServeMux ¶
NewServeMux creates a ServeMux whose typed handlers receive request-local state values of type State.
func (*ServeMux[State]) Handle ¶
Handle registers a standard http.Handler for pattern.
Use Handle for handlers that do not need typed state, or for mounting another mux that already owns its handler behavior.
func (*ServeMux[State]) HandleFunc ¶
func (m *ServeMux[State]) HandleFunc(pattern string, handler HandlerFunc[State])
HandleFunc registers a typed handler for pattern.
Each request receives a fresh *State. Middleware and the final handler share that pointer for the lifetime of the request.
Example ¶
package main
import (
"fmt"
"net/http"
"net/http/httptest"
"strings"
"github.com/ras0q/noy"
)
func main() {
type User struct {
Name string
}
type State struct {
CurrentUser *User
}
users := map[string]*User{
"secret": {Name: "Ada"},
}
authenticate := func(next noy.HandlerFunc[State]) noy.HandlerFunc[State] {
return func(state *State, w http.ResponseWriter, r *http.Request) {
token := strings.TrimPrefix(r.Header.Get("Authorization"), "Bearer ")
user, ok := users[token]
if !ok {
http.Error(w, "unauthorized", http.StatusUnauthorized)
return
}
state.CurrentUser = user
next(state, w, r)
}
}
mux := noy.NewServeMux[State]()
mux.HandleFunc("GET /me", authenticate(func(state *State, w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "hello %s", state.CurrentUser.Name)
}))
req := httptest.NewRequest(http.MethodGet, "/me", nil)
req.Header.Set("Authorization", "Bearer secret")
res := httptest.NewRecorder()
mux.ServeHTTP(res, req)
fmt.Println(res.Body.String())
}
Output: hello Ada
func (*ServeMux[State]) HandleStdFunc ¶
func (m *ServeMux[State]) HandleStdFunc(pattern string, handler http.HandlerFunc)
HandleStdFunc registers a standard http.HandlerFunc for pattern.
Use HandleStdFunc for endpoints that should keep the ordinary net/http function signature.