Documentation
¶
Overview ¶
Package wrap provides wrappers for [http.Handler]s.
Index ¶
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func Context ¶
func Context(handler http.Handler, f ContextFunc) http.Handler
Context wraps handler, replacing the context of any request using the given function.
Example ¶
package main import ( "context" "fmt" "io" "net/http" "net/http/httptest" "github.com/tkw1536/pkglib/httpx/wrap" ) type responseKeyType struct{} var responseKey = responseKeyType{} func main() { handler := wrap.Context( // Create a new handler that extracts a given context key // and writes it to the response http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { content, ok := r.Context().Value(responseKey).(string) if !ok { return } _, _ = w.Write([]byte(content)) }), // Wrap it using a function that automatically sets the key func(r *http.Request) (context.Context, context.CancelFunc) { return context.WithValue(r.Context(), responseKey, "this response got set in a wrapper"), nil }, ) // create a new request req, err := http.NewRequest(http.MethodGet, "/", nil) if err != nil { panic(err) } // serve the http request rr := httptest.NewRecorder() handler.ServeHTTP(rr, req) if status := rr.Result().StatusCode; status != http.StatusOK { fmt.Println("Expected http.StatusOK") } result, _ := io.ReadAll(rr.Result().Body) fmt.Println(string(result)) }
Output: this response got set in a wrapper
Example (Cancel) ¶
package main import ( "context" "fmt" "io" "net/http" "net/http/httptest" "github.com/tkw1536/pkglib/httpx/wrap" ) func main() { handler := wrap.Context( http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { fmt.Println("calling handler") _, _ = w.Write(nil) }), // Wrap it using a function that automatically sets the key func(r *http.Request) (context.Context, context.CancelFunc) { return r.Context(), func() { fmt.Printf("calling CancelFunc") } }, ) // create a new request req, err := http.NewRequest(http.MethodGet, "/", nil) if err != nil { panic(err) } // serve the http request rr := httptest.NewRecorder() handler.ServeHTTP(rr, req) if status := rr.Result().StatusCode; status != http.StatusOK { fmt.Println("Expected http.StatusOK") } result, _ := io.ReadAll(rr.Result().Body) fmt.Println(string(result)) }
Output: calling handler calling CancelFunc
func Methods ¶
Methods wraps handler, rejecting requests not using any of the provided methods. Requests with rejected methods return a generic "Method Not Allowed" response with appropriate status code.
Example ¶
package main import ( "fmt" "io" "net/http" "net/http/httptest" "github.com/tkw1536/pkglib/httpx/wrap" ) func main() { handler := wrap.Methods( // Create a new handler that echoes the appropriate method http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { _, _ = w.Write([]byte(r.Method)) }), // and permit only the GET and POST methods http.MethodGet, http.MethodPost, ) // A simple function to make a request with a specific method makeRequest := func(method string) { req, err := http.NewRequest(method, "/", nil) if err != nil { panic(err) } rr := httptest.NewRecorder() handler.ServeHTTP(rr, req) result, _ := io.ReadAll(rr.Result().Body) fmt.Printf("%s returned code %d with content %q\n", method, rr.Result().StatusCode, string(result)) } // and do a couple of the requests makeRequest(http.MethodGet) makeRequest(http.MethodPost) makeRequest(http.MethodHead) }
Output: GET returned code 200 with content "GET" POST returned code 200 with content "POST" HEAD returned code 405 with content "Method Not Allowed"
func Time ¶
Time wraps an http.Handler, storing the time a request was started within it. To retrieve stored time, see TimeStart and TimeSince.
Example ¶
package main import ( "encoding/json" "fmt" "net/http" "net/http/httptest" "time" "github.com/tkw1536/pkglib/httpx/wrap" ) func main() { // delay used during this example var delay = 50 * time.Millisecond // Create a new HandlerFunc that sleeps for the delay. handler := wrap.Time(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { time.Sleep(delay) // sleep for a bit took := wrap.TimeSince(r) // record how long it took _ = json.NewEncoder(w).Encode(took) })) // create a new request req, err := http.NewRequest(http.MethodGet, "/", nil) if err != nil { panic(err) } // serve the http request rr := httptest.NewRecorder() handler.ServeHTTP(rr, req) if status := rr.Code; status != http.StatusOK { fmt.Println("Expected http.StatusOK") } // decode the amount of time taken from the request var took time.Duration _ = json.NewDecoder(rr.Result().Body).Decode(&took) if took >= delay { fmt.Println("Handler returned correct delay") } }
Output: Handler returned correct delay
Types ¶
type ContextFunc ¶
ContextFunc is a function that replaces contexts for a given request. A nil ContextFunc leaves the original context intact.
- the returned context, if non-nil, is used to replace the context of the request. - the returned CancelFunc is called once the request ends.