HTTP Utilities
The utils/ package provides reusable HTTP helpers for use in command and view handlers.
JsonParse
Decodes a JSON request body and validates the result using struct tags.
- Decodes
r.Bodyintovusingencoding/json - Validates
vusinggo-playground/validatorstruct tags - Returns the first error encountered (decode or validation)
Example
var body struct {
Name string `json:"name" validate:"required"`
Email string `json:"email" validate:"required,email"`
}
if err := utils.JsonParse(r, &body); err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
Supported validation tags come from github.com/go-playground/validator/v10. Common tags:
| Tag | Meaning |
|---|---|
required |
Field must be non-zero |
email |
Must be a valid email address |
min=N |
Minimum length / value |
max=N |
Maximum length / value |
oneof=a b |
Must be one of the listed values |
IdempotencyMiddleware
An HTTP middleware that deduplicates requests sharing the same Idempotency-Key header, backed by FoundationDB.
Behaviour
- If no
Idempotency-Keyheader is present, the request passes through unchanged. - If the key is new: the middleware marks it as "processing" in FDB, runs the handler, stores the response (status code + body), and returns it.
- If the key is already processing: the middleware polls FDB (every 50ms, up to 10s) until the result is available, then returns it.
- If the key is already complete: the stored response is returned immediately without running the handler again.
Storage
Responses are stored in <namespace>/idempotency/<key> as a binary-encoded blob:
Example
mux := http.NewServeMux()
// ... register routes ...
handler := utils.IdempotencyMiddleware(db, "myapp", mux)
log.Fatal(http.ListenAndServe(":8080", handler))
Clients use it by including a unique key per logical operation:
curl -X POST http://localhost:8080/api/lists/my-list \
-H "Idempotency-Key: create-list-550e8400" \
-H "Content-Type: application/json" \
-d '{"name": "Shopping"}'
Retrying the same request with the same key returns the original response without re-executing the command.
Timeout
If the first request does not complete within 10 seconds, waiting duplicates receive 504 Gateway Timeout.