FAQ
How do I get JSON data from the body of a request (e.g., POST, PUT)?
With nova
, you can use the rc.Bind()
method on the ResponseContext
to automatically decode JSON from the request body into your struct. This avoids manual decoding and error handling boilerplate.
Here is a complete example using PostFunc
and rc.Bind()
:
package main
import (
"log"
"net/http"
"github.com/xlc-dev/nova/nova"
)
// MyData defines the structure of our expected JSON payload.
type MyData struct {
Name string `json:"name"`
Value int `json:"value"`
}
// handleJsonRequest uses nova's ResponseContext to simplify data binding and response.
func handleJsonRequest(rc *nova.ResponseContext) error {
var data MyData
// Bind the incoming JSON request body to the 'data' struct.
if err := rc.BindJSON(&data); err != nil {
// If binding fails (e.g., malformed JSON), return a 400 Bad Request.
log.Printf("Error binding JSON: %v", err)
return rc.JSONError(http.StatusBadRequest, "Invalid JSON payload")
}
log.Printf("Received data: Name=%s, Value=%d\n", data.Name, data.Value)
// Send a success response using the JSON helper.
response := map[string]any{
"status": "success",
"received_name": data.Name,
}
return rc.JSON(http.StatusOK, response)
}
func main() {
router := nova.NewRouter()
router.PostFunc("/data", handleJsonRequest)
log.Println("Server starting on :8080")
if err := http.ListenAndServe(":8080", router); err != nil {
log.Fatalf("Server failed to start: %v", err)
}
}
How do I get data from a GET request?
GET requests typically pass data in two ways: URL query parameters (e.g., ?id=123
) or path parameters (e.g., /items/123
). nova
makes handling both easy.
1. Reading Query Parameters
For query parameters, you can access the standard http.Request
object via rc.Request()
and use its URL.Query()
method.
// handleGetWithQuery processes data from URL query parameters.
// Example request: GET /items?name=widget&id=123
func handleGetWithQuery(rc *nova.ResponseContext) error {
// Access the underlying request to get query parameters.
queryParams := rc.Request().URL.Query()
name := queryParams.Get("name")
idStr := queryParams.Get("id")
if name == "" || idStr == "" {
return rc.JSONError(http.StatusBadRequest, "Missing 'name' or 'id' query parameter")
}
log.Printf("Processed query: name=%s, id=%s\n", name, idStr)
response := map[string]string{
"item_name": name,
"item_id": idStr,
}
return rc.JSON(http.StatusOK, response)
}
// In main():
// router.GetFunc("/items", handleGetWithQuery)
2. Reading Path Parameters
For path parameters defined in your route (e.g., /{id}
), nova
provides the much cleaner rc.URLParam()
helper.
// handleGetWithPathVar processes data from a URL path parameter.
// Example request: GET /users/42
func handleGetWithPathVar(rc *nova.ResponseContext) error {
// Use the URLParam helper to get the 'id' from the path.
userID := rc.URLParam("id")
log.Printf("Processed request for user ID: %s\n", userID)
response := map[string]string{
"status": "found",
"user_id": userID,
}
return rc.JSON(http.StatusOK, response)
}
// In main():
// router.GetFunc("/users/{id}", handleGetWithPathVar)
How do I validate incoming request data?
Nova has powerful, built-in validation. Instead of rc.Bind()
, use rc.BindValidated()
. It automatically binds the data and then runs validations based on the struct tags you’ve defined (required
, minlength
, format
, etc.).
If validation fails, it returns a detailed error, which you can send back to the client.
package main
import (
"log"
"net/http"
"github.com/xlc-dev/nova/nova"
)
// UserSignup defines a struct with validation tags.
type UserSignup struct {
Username string `json:"username" minlength:"3" maxlength:"20" format:"alphanumeric"`
Email string `json:"email" format:"email"`
// omitempty is not used, so this field is required by default.
Password string `json:"password" format:"password"`
}
// handleUserSignup binds and validates the request body in one step.
func handleUserSignup(rc *nova.ResponseContext) error {
var user UserSignup
// Bind AND validate the incoming JSON.
if err := rc.BindValidated(&user); err != nil {
// e.g., "validation failed: Field 'username' must contain only alphanumeric characters"
log.Printf("Validation failed: %v", err)
return rc.JSONError(http.StatusBadRequest, err.Error())
}
log.Printf("Successfully validated and created user: %s", user.Username)
response := map[string]string{
"status": "user_created",
"username": user.Username,
}
return rc.JSON(http.StatusCreated, response)
}
func main() {
router := nova.NewRouter()
router.PostFunc("/signup", handleUserSignup)
log.Println("Server starting on :8080")
if err := http.ListenAndServe(":8080", router); err != nil {
log.Fatalf("Server failed to start: %v", err)
}
}