First I tried implementing this solution in such a way that it explicitly clears body and set `Content-Length` header to body's size. But for some reason, if I call the URL from cURL then `Content-Length` header was blank which defeats the very purpose of `HEAD` requests. I then later anticipated that since `HEAD` would be by-default implemented by `HTTP::Server` module, there is no need to explicit clears body and setting `Content-Length` but the way we have written our previous specs were returning body as well. We could have used some TestServer kind of thing but if we go to that route we explicitly need to test non-existent route which I thought would create some inconsistency among specs. Crystal has clearly written specs for HEAD requests to make sure body is not read for them. See https://github.com/manastech/crystal/commit/acd0b6afb5af438a30529c36b11b e7954336f23f. I decided to write simple specs which are easy to maintain in long-run. We are adding identical HEAD route for every GET route which will make HEAD requests available for all defined GET requests. https://github.com/sdogruyol/kemal/issues/19 Added comment for code line which is adding HEAD routes for defined GET routes. |
||
---|---|---|
samples | ||
spec | ||
src | ||
.gitignore | ||
.travis.yml | ||
Guardfile | ||
README.md | ||
shard.yml |
Lightning Fast, Super Simple web framework for Crystal. Inspired by Sinatra
Kemal is under heavy development and currently supports Crystal 0.9.0.
Super Simple <3
require "kemal"
get "/" do
"Hello World!"
end
Build and run!
crystal build --release src/kemal_sample.cr
./kemal_sample
Go to http://localhost:3000
Check samples for more.
Super Fast <3
Numbers speak louder than words.
Framework | Request Per Second | Avg. Response Time |
---|---|---|
Kemal (Production) | 64986 | 170μs |
Sinatra (Thin) | 2274 | 43.82ms |
These results were achieved with wrk
on a Macbook Pro Late 2013. (2Ghz i7 8GB Ram OS X Yosemite)
Installation
Kemal supports Crystal 0.9.0 and up.
You can add Kemal to your project by adding it to shard.yml
name: your-app
dependencies:
kemal:
github: sdogruyol/kemal
branch: master
Routes
In Kemal, a route is an HTTP method paired with a URL-matching pattern. Each route is associated with a block:
get "/" do
.. show something ..
end
post "/" do
.. create something ..
end
put "/" do
.. replace something ..
end
patch "/" do
.. modify something ..
end
delete "/" do
.. annihilate something ..
end
Environment
Accessing the environment (query params, body, content_type, headers, status_code) is super easy. You can use the environment returned from the block:
# Matches /hello/kemal
get "/hello/:name" do |env|
name = env.params["name"]
"Hello back to #{name}"
end
# Matches /resize?width=200&height=200
get "/resize" do |env|
width = env.params["width"]
height = env.params["height"]
end
# Easily access JSON payload from the params.
# The request content type needs to be application/json
# The payload
# {"name": "Serdar", "likes": ["Ruby", "Crystal"]}
post "/json_params" do |env|
name = env.params["name"] as String
likes = env.params["likes"] as Array
"#{name} likes #{likes.each.join(',')}"
end
# Set the content as application/json and return JSON
get "/user.json" do |env|
kemal = {name: "Kemal", language: "Crystal"}
env.content_type = "application/json"
kemal.to_json
end
# Add headers to your response
get "/headers" do |env|
env.add_header "Accept-Language", "tr"
env.add_header "Authorization", "Token 12345"
end
Middlewares
You can create your own middlewares by inheriting from HTTP::Handler
class CustomHandler < HTTP::Handler
def call(request)
puts "Doing some custom stuff here"
call_next request
end
end
Kemal.config.add_handler CustomHandler.new
Static Files
Kemal has built-in support for serving your static files. You need to put your static files under your /public
directory.
E.g: A static file like /public/index.html
will be served with the matching route /index.html
.
Production / Development Mode
By default Kemal starts in development
mode and logs to STDOUT.
You can use production
mode to redirect the output to a file. By default Kemal logs the output to kemal.log
.
You can start Kemal in production mode by:
./your_app -e production
Thanks
Thanks to Manas for their awesome work on Frank.