Hatty
A library for creating HTTP services in Crystal
require "hatty"
get "/" do |request, response|
response.send_text "Hello there!"
end
Hatty.start
Installing
Add this snippet to your shard.yml
file
dependencies:
hatty:
github: semlette/hatty
Usage
require "hatty"
# Define handlers using `get`, `post`, `put`, `delete` and `patch`
get "/users/:id" do |request, response|
user = get_user(request.params["id"])
response.send_json({ data: user })
end
post "/users" do |request, response|
name = response.body["name"]
age = response.body["age"]
new_user = create_user(name, age)
response.send_json({ success: true, data: new_user })
end
delete "/users/:id" do |request, response|
token = request.headers["Authorization"]?
is_admin = is_admin?(token)
if is_admin
delete_user(request.params["id"])
response.send_json({ "success" => true })
else
response.send_status 401
end
end
Hatty.start
Every handler receives a request and a response. The request contains information about the request like the headers, the body, url queries and parameters. The response has properties like the status code, headers and a lot of helper methods for sending stuff back to the client.
Sending stuff
get "/" do |request, response|
# Note: You can only call `#send...` once
response.send "<!DOCTYPE><html><body>I have no Content-Type</body></html>"
response.send_text "I am text/plain"
response.send_json({ "content-type" => "application/json" })
response.send_status 404
response.send_file("../images/logo.png", "our-logo.png")
response.redirect("/homepage")
end
API documentation for Response
Status codes
Setting the status code
get "/admin" do |request, response|
response.status_code = 401
response.send_text "Unauthorized."
end
Using status handlers
Status handlers are handlers that respond to a specific status code. When you call Response#send_status
, the request is passed to the status handler with the same status code. If a handler raises an uncaught error, Hatty sends the request to the 500
status handler. It also passes requests with no handler to the 404
status handler.
get "/private" do |request, response|
response.send_status 404
end
status 404 do |request, response|
response.send_text "Oops, file not found. ¯\_(ツ)_/¯"
end
Global status handler
Instead of defining a status handler for every status code, you can define a Global Status Handler™. The global status handler will receive all status codes not handled by the status handlers. If you create a status handler for 404
and a global status handler, the global status handler will not receive 404
requests.
status do |code, request, response|
response.send_text "Oops! Error code #{code}"
end
API documentation for Response#send_status
Testing
Hatty comes with a testing module which helps you test your routes. Inspired by spec-kemal, requiring hatty/testing
imports methods that allows you to test your routes.
Methods
app.cr
require "hatty"
get "/api" do |request, response|
response.send_json({ "data" => "insert data here" })
end
Hatty.start
app_spec.cr
require "./app"
require "hatty/testing"
describe "GET /api" do
it "returns json" do
# `get` along with other methods are provided by `hatty/testing`
response = get "/api"
response.status_code.should eq 200
response.json?.should be_true
end
end