Response Handling
Okapi provides a rich set of response methods to send various types of responses back to the client with appropriate HTTP status codes and content types.
Quick Start
The simplest way to send a response is using convenience methods:
o.Get("/books/:id", func(c *okapi.Context) error {
book := Book{
ID: 1,
Name: "The Great Go Book",
Price: 20,
}
return c.Ok(book) // Sends 200 OK with JSON
})
Response Methods
JSON Responses
Send JSON data with a specific status code:
o.Get("/books", func(c *okapi.Context) error {
books := []Book
return c.JSON(http.StatusOK, books)
})
Text Responses
Send plain text:
o.Get("/hello", func(c *okapi.Context) error {
return c.String(http.StatusOK, "Hello, World!")
})
HTML Responses
Send HTML content:
o.Get("/page", func(c *okapi.Context) error {
html := "<h1>Welcome</h1>"
return c.HTML(http.StatusOK, html)
})
XML Responses
Send XML data:
o.Get("/books", func(c *okapi.Context) error {
books := []Book
return c.XML(http.StatusOK, books)
})
File Responses
Serve files for download:
o.Get("/download", func(c *okapi.Context) error {
return c.ServeFile("path/to/file.pdf")
})
Convenience Methods
Okapi provides shorthand methods for common HTTP status codes.
Success Responses
// 200 OK
return c.Ok(data)
// 201 Created
return c.Created(data)
// 204 No Content
return c.NoContent()
Client Error Responses
// 400 Bad Request
return c.ErrorBadRequest(err)
// 401 Unauthorized
return c.ErrorUnauthorized(err)
// 403 Forbidden
return c.ErrorForbidden(err)
// 404 Not Found
return c.ErrorNotFound(err)
Server Error Responses
// 500 Internal Server Error
return c.ErrorInternalServerError(err)
Advanced Response Handling
Response Struct Binding
When using c.Respond()/c.Return(), Okapi automatically serializes the response struct into the HTTP response.
It inspects struct tags to determine:
- the HTTP status code
- response headers
- cookies
- and the response body (encoded according to the
Acceptheader).
type BookResponse struct {
// HTTP status code (default: 200)
Status int `status:"true" json:"status"`
// Response body
Body struct {
ID int `json:"id"`
Name string `json:"name"`
Price int `json:"price"`
} `json:"body"`
// Custom headers
XRequestID string `header:"X-Request-ID" json:"x_request_id"`
// Cookies
SessionID string `cookie:"session_id" json:"session_id"`
}
o.Get("/books/:id", func(c *okapi.Context) error {
response := BookResponse{
Status: http.StatusOK,
Body: struct {
ID int `json:"id"`
Name string `json:"name"`
Price int `json:"price"`
}{
ID: 1,
Name: "The Great Go Book",
Price: 20,
},
XRequestID: "req-12345",
SessionID: "sess-67890",
}
return c.Respond(response)
})
Supported struct tags:
status:"true"- Sets the HTTP status code for the responsejson:"body"- Sets the response bodyheader:"Header-Name"- Sets a response headercookie:"cookie_name"- Sets a cookie value
Setting Headers Manually
o.Get("/", func(c *okapi.Context) error {
c.SetHeader("X-Custom-Header", "value")
c.SetHeader("Cache-Control", "max-age=3600")
return c.Ok(okapi.M{"message": "Success"})
})
Setting Cookies
o.Get("/login", func(c *okapi.Context) error {
c.SetCookie(&http.Cookie{
Name: "session",
Value: "abc123",
Path: "/",
MaxAge: 3600,
HttpOnly: true,
Secure: true,
SameSite: http.SameSiteStrictMode,
})
return c.Ok(okapi.M{"message": "Logged in"})
})
Abort Methods
Abort methods immediately stop request processing and send an error response. They’re useful in middleware or when you need to halt execution:
o.Use(func(c *okapi.Context) error {
token := c.GetHeader("Authorization")
if token == "" {
return c.AbortUnauthorized("Missing authorization token", nil)
}
return c.Next()
})
Available abort methods:
// 400 Bad Request
return c.AbortBadRequest("Invalid input", err)
// 401 Unauthorized
return c.AbortUnauthorized("Not authenticated", err)
// 403 Forbidden
return c.AbortForbidden("Access denied", err)
// 404 Not Found
return c.AbortNotFound("Resource not found", err)
// 500 Internal Server Error
return c.AbortInternalServerError("Server error", err)
Template Rendering
Render HTML templates with data:
o.Get("/", func(c *okapi.Context) error {
return c.Render(http.StatusOK, "welcome", okapi.M{
"title": "Welcome Page",
"message": "Hello from Okapi!",
})
})
See the Templating section for details on configuring template engines.
Examples
Complete CRUD Endpoint
type Book struct {
ID int `json:"id"`
Name string `json:"name"`
Price int `json:"price"`
}
// List books
o.Get("/books", func(c *okapi.Context) error {
books := []Book
return c.Ok(books)
})
// Get single book
o.Get("/books/:id", func(c *okapi.Context) error {
id := c.Param("id")
book := Book{ID: 1, Name: "Go Programming", Price: 50}
return c.Ok(book)
})
// Create book
o.Post("/books", func(c *okapi.Context) error {
var book Book
if err := c.BindJSON(&book); err != nil {
return c.ErrorBadRequest(err)
}
// Save book...
return c.Created(book)
})
// Delete book
o.Delete("/books/:id", func(c *okapi.Context) error {
id := c.Param("id")
// Delete book...
return c.NoContent()
})