Documentation
¶
Overview ¶
Package web provides muxing router, middleware, for handling HTTP requests.
Index ¶
- func Decode[T any](r *http.Request, val *T) error
- func DecodeAllowUnknownFields[T any](r *http.Request, val *T) error
- func Param(r *http.Request, key string) (string, error)
- func ParamInt(r *http.Request, key string) (int, error)
- func ParamInt64(r *http.Request, key string) (int64, error)
- func QueryBool(r *http.Request, key string) (bool, error)
- func QueryInt(r *http.Request, key string) (int, error)
- func QueryInt64(r *http.Request, key string) (int64, error)
- func QueryString(r *http.Request, key string) (string, error)
- func Redirect(w http.ResponseWriter, r *http.Request, url string, code int) error
- func RespondError(ctx context.Context, w http.ResponseWriter, err *errs.Error) error
- func RespondJSON(ctx context.Context, w http.ResponseWriter, statusCode int, data any) error
- func Validate(val any) error
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func Decode ¶
Decode reads the body of an HTTP request looking for a JSON document. The body is decoded into the provided value. If the provided value is a struct then it is checked for validation tags. If the value implements a validate function, it is executed.
Example ¶
package main
import (
"fmt"
"net/http"
"net/http/httptest"
"strings"
"github.com/adamwoolhether/httper/web"
)
func main() {
type Input struct {
Name string `json:"name" validate:"required"`
}
body := strings.NewReader(`{"name":"alice"}`)
r := httptest.NewRequest(http.MethodPost, "/", body)
var input Input
if err := web.Decode(r, &input); err != nil {
fmt.Println("error:", err)
return
}
fmt.Println(input.Name)
}
Output: alice
func DecodeAllowUnknownFields ¶
DecodeAllowUnknownFields is the same as Decode, but won't reject unknown fields.
Example ¶
package main
import (
"fmt"
"net/http"
"net/http/httptest"
"strings"
"github.com/adamwoolhether/httper/web"
)
func main() {
type Input struct {
Name string `json:"name" validate:"required"`
}
body := strings.NewReader(`{"name":"alice","extra":"ignored"}`)
r := httptest.NewRequest(http.MethodPost, "/", body)
var input Input
if err := web.DecodeAllowUnknownFields(r, &input); err != nil {
fmt.Println("error:", err)
return
}
fmt.Println(input.Name)
}
Output: alice
func Param ¶
Param extracts a path parameter by key and returns its string value.
Example ¶
package main
import (
"fmt"
"net/http"
"net/http/httptest"
"github.com/adamwoolhether/httper/web"
)
func main() {
r := httptest.NewRequest(http.MethodGet, "/users/alice", nil)
r.SetPathValue("name", "alice")
name, err := web.Param(r, "name")
if err != nil {
fmt.Println("error:", err)
return
}
fmt.Println(name)
}
Output: alice
func ParamInt ¶
ParamInt extracts a path parameter by key and parses it as an int.
Example ¶
package main
import (
"fmt"
"net/http"
"net/http/httptest"
"github.com/adamwoolhether/httper/web"
)
func main() {
r := httptest.NewRequest(http.MethodGet, "/items/42", nil)
r.SetPathValue("id", "42")
id, err := web.ParamInt(r, "id")
if err != nil {
fmt.Println("error:", err)
return
}
fmt.Println(id)
}
Output: 42
func ParamInt64 ¶
ParamInt64 extracts a path parameter by key and parses it as an int64.
Example ¶
package main
import (
"fmt"
"net/http"
"net/http/httptest"
"github.com/adamwoolhether/httper/web"
)
func main() {
r := httptest.NewRequest(http.MethodGet, "/orders/9000000000", nil)
r.SetPathValue("id", "9000000000")
id, err := web.ParamInt64(r, "id")
if err != nil {
fmt.Println("error:", err)
return
}
fmt.Println(id)
}
Output: 9000000000
func QueryBool ¶
QueryBool extracts a query parameter by key and parses it as a bool.
Example ¶
package main
import (
"fmt"
"net/http"
"net/http/httptest"
"github.com/adamwoolhether/httper/web"
)
func main() {
r := httptest.NewRequest(http.MethodGet, "/items?active=true", nil)
active, err := web.QueryBool(r, "active")
if err != nil {
fmt.Println("error:", err)
return
}
fmt.Println(active)
}
Output: true
func QueryInt ¶
QueryInt extracts a query parameter by key and parses it as an int.
Example ¶
package main
import (
"fmt"
"net/http"
"net/http/httptest"
"github.com/adamwoolhether/httper/web"
)
func main() {
r := httptest.NewRequest(http.MethodGet, "/items?page=3", nil)
page, err := web.QueryInt(r, "page")
if err != nil {
fmt.Println("error:", err)
return
}
fmt.Println(page)
}
Output: 3
func QueryInt64 ¶
QueryInt64 extracts a query parameter by key and parses it as an int64.
Example ¶
package main
import (
"fmt"
"net/http"
"net/http/httptest"
"github.com/adamwoolhether/httper/web"
)
func main() {
r := httptest.NewRequest(http.MethodGet, "/items?cursor=8000000000", nil)
cursor, err := web.QueryInt64(r, "cursor")
if err != nil {
fmt.Println("error:", err)
return
}
fmt.Println(cursor)
}
Output: 8000000000
func QueryString ¶
QueryString extracts a query parameter by key and returns its string value.
Example ¶
package main
import (
"fmt"
"net/http"
"net/http/httptest"
"github.com/adamwoolhether/httper/web"
)
func main() {
r := httptest.NewRequest(http.MethodGet, "/search?q=golang", nil)
q, err := web.QueryString(r, "q")
if err != nil {
fmt.Println("error:", err)
return
}
fmt.Println(q)
}
Output: golang
func Redirect ¶
Redirect issues an HTTP redirect to the given URL. The status code must be in the 3xx range or an error is returned.
Example ¶
package main
import (
"fmt"
"net/http"
"net/http/httptest"
"github.com/adamwoolhether/httper/web"
)
func main() {
w := httptest.NewRecorder()
r := httptest.NewRequest(http.MethodGet, "/old", nil)
if err := web.Redirect(w, r, "/new", http.StatusMovedPermanently); err != nil {
fmt.Println("error:", err)
return
}
fmt.Println(w.Code)
fmt.Println(w.Header().Get("Location"))
}
Output: 301 /new
func RespondError ¶
RespondError writes a structured JSON error response using the status code and message from the given *errs.Error.
Example ¶
package main
import (
"context"
"fmt"
"net/http"
"net/http/httptest"
"github.com/adamwoolhether/httper/web"
"github.com/adamwoolhether/httper/web/errs"
)
func main() {
w := httptest.NewRecorder()
appErr := errs.New(http.StatusNotFound, fmt.Errorf("user not found"))
if err := web.RespondError(context.Background(), w, appErr); err != nil {
fmt.Println("error:", err)
return
}
fmt.Println(w.Code)
fmt.Println(w.Body.String())
}
Output: 404 {"code":404,"message":"user not found"}
func RespondJSON ¶
RespondJSON to an HTTP request, setting the status code and body if any.
Example ¶
package main
import (
"context"
"fmt"
"net/http"
"net/http/httptest"
"github.com/adamwoolhether/httper/web"
)
func main() {
w := httptest.NewRecorder()
data := map[string]string{"status": "ok"}
if err := web.RespondJSON(context.Background(), w, http.StatusOK, data); err != nil {
fmt.Println("error:", err)
return
}
fmt.Println(w.Code)
fmt.Println(w.Body.String())
}
Output: 200 {"status":"ok"}
func Validate ¶
Validate that the provided model against its declared tags.
Example ¶
package main
import (
"fmt"
"github.com/adamwoolhether/httper/web"
)
func main() {
type Input struct {
Name string `json:"name" validate:"required"`
Email string `json:"email" validate:"required,email"`
}
input := Input{
Name: "alice",
Email: "alice@example.com",
}
err := web.Validate(&input)
fmt.Println(err)
}
Output: <nil>
Example (Errors) ¶
package main
import (
"fmt"
"github.com/adamwoolhether/httper/web"
"github.com/adamwoolhether/httper/web/errs"
)
func main() {
type Input struct {
Name string `json:"name" validate:"required"`
}
err := web.Validate(&Input{})
fe := errs.GetFieldErrors(err)
for _, f := range fe {
fmt.Printf("%s: %s\n", f.Field, f.Err)
}
}
Output: name: This field is required
Types ¶
This section is empty.
Directories
¶
| Path | Synopsis |
|---|---|
|
Package errs enables error handling and definition at the http/app level.
|
Package errs enables error handling and definition at the http/app level. |
|
Package middleware provides common HTTP middleware for the web application.
|
Package middleware provides common HTTP middleware for the web application. |
|
Package mux provides helpers for middleware and route handling.
|
Package mux provides helpers for middleware and route handling. |
|
Package server manages the HTTP server lifecycle with graceful shutdown.
|
Package server manages the HTTP server lifecycle with graceful shutdown. |