Response objects define how endpoint results are rendered to clients.
struct MyResponse
include Azu::Response
def initialize(@data : MyData)
end
def render
@data.to_json
end
endReturn the response body as a string.
def render : String
{id: @user.id, name: @user.name}.to_json
endReturns: String
JSON response with automatic content type.
struct MyEndpoint
include Azu::Endpoint(EmptyRequest, Azu::Response::Json)
get "/data"
def call
json({message: "Hello", count: 42})
end
endPlain text response.
struct HealthEndpoint
include Azu::Endpoint(EmptyRequest, Azu::Response::Text)
get "/health"
def call
text "OK"
end
endHTML response.
struct PageEndpoint
include Azu::Endpoint(EmptyRequest, Azu::Response::Html)
get "/page"
def call
html "<h1>Welcome</h1>"
end
endNo content response (204).
struct DeleteEndpoint
include Azu::Endpoint(EmptyRequest, Azu::Response::Empty)
delete "/items/:id"
def call
Item.find(params["id"]).destroy
status 204
Azu::Response::Empty.new
end
endBase class for error responses.
class Azu::Response::Error < Exception
getter status : Int32
getter message : String
def initialize(@message : String, @status : Int32 = 500)
end
end| Class | Status | Usage |
|---|---|---|
BadRequest |
400 | Invalid request |
Unauthorized |
401 | Authentication required |
Forbidden |
403 | Access denied |
NotFound |
404 | Resource not found |
MethodNotAllowed |
405 | HTTP method not allowed |
Conflict |
409 | Resource conflict |
UnprocessableEntity |
422 | Validation failed |
TooManyRequests |
429 | Rate limit exceeded |
InternalServerError |
500 | Server error |
ServiceUnavailable |
503 | Service unavailable |
def call
user = User.find?(params["id"])
raise Azu::Response::NotFound.new("/users/#{params["id"]}") unless user
UserResponse.new(user)
endSpecial error for validation failures.
raise Azu::Response::ValidationError.new([
{field: "email", message: "is invalid"},
{field: "name", message: "is required"}
])struct UserResponse
include Azu::Response
def initialize(@user : User)
end
def render
{
id: @user.id,
name: @user.name,
email: @user.email,
created_at: @user.created_at.try(&.to_rfc3339)
}.to_json
end
end
struct UsersResponse
include Azu::Response
def initialize(
@users : Array(User),
@page : Int32,
@total : Int64
)
end
def render
{
data: @users.map { |u| serialize_user(u) },
meta: {
page: @page,
total: @total
}
}.to_json
end
private def serialize_user(user : User)
{id: user.id, name: user.name}
end
endSet custom headers in your endpoint:
def call
response.headers["X-Custom-Header"] = "value"
response.headers["Cache-Control"] = "max-age=3600"
MyResponse.new(data)
endSet custom status codes:
def call
status 201 # Created
UserResponse.new(user)
end
def call
status 202 # Accepted
TaskResponse.new(task)
endFor large responses:
def call
response.content_type = "application/json"
response.headers["Transfer-Encoding"] = "chunked"
response.print "["
users.each_with_index do |user, i|
response.print "," if i > 0
response.print user.to_json
response.flush
end
response.print "]"
endReturn different formats based on Accept header:
def call
case accept_type
when "application/json"
json(data)
when "text/html"
html(render_html(data))
when "text/plain"
text(data.to_s)
else
json(data)
end
end
private def accept_type
headers["Accept"]?.try(&.split(",").first) || "application/json"
end