Kemal is a web framework written in Crystal. It's simple yet powerful DSL combined with lightning fast performance will make you want more!
These are the slides for the talk that i gave at PolyConf 16
8. @sdogruyol 8
def fibonacci(n)
return n if n <= 1
fibonacci(n - 1) + fibonacci(n - 2)
end
puts fibonacci 40
➜ time ruby fib.rb
102334155
ruby fib.rb 14.68s user 0.18s system 99% cpu 14.893 total
➜ crystal build —release fib.rb && time ./fib
102334155
./fib 0.68s user 0.02s system 99% cpu 0.699 total
12. @sdogruyol
Crystal
• Ruby like (not compatible)
• Compiled
• Type inference
• Concurrency via channels (a la Go)
• Metaprogramming via Macros
• Native Code via LLVM
12
19. @sdogruyol 19
require "kemal"
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
Kemal.run
HTTP Verbs - REST
20. @sdogruyol 20
Built-in WebSocket
# A simple chat server
require "kemal"
messages = [] of String
sockets = [] of HTTP::WebSocket
ws "/chat" do |socket|
sockets.push socket
socket.on_message do |message|
messages.push message
sockets.each do |s|
s.send messages.to_json
end
end
end
Kemal.run
http://kemal-react-chat.herokuapp.com/
21. @sdogruyol 21
require "kemal"
get "/" do |ctx|
loop do
sleep 0.1
ctx.response.puts “Streaming”
end
ctx
end
Kemal.run
Streamable Request / Response Context
22. @sdogruyol 22
require "kemal"
post "/users/:id" do |ctx|
id = ctx.params.url["id"]
name = ctx.params.json["name"] as String
age = ctx.params.json["age"] as Int32
"User #{id} Name #{name} Age #{age}"
end
Kemal.run
Built-in Parameter Parser
require "kemal"
post "/users/:id" do |ctx|
id = ctx.params.url["id"]
name = ctx.params.body["name"] as String
age = ctx.params.body["age"] as Int32
"User #{id} Name #{name} Age #{age}"
end
Kemal.run
Form Body JSON Body
➜ ~ curl --data "name=serdar&age=27"
http://localhost:3000/users/1
User 1 Name serdar Age 27
➜ ~ curl -H "Content-Type: application/json" -X POST -d
'{"name":"serdar","age": 27}'
http://localhost:3000/users/1
User 1 Name serdar Age 27
23. @sdogruyol 23
Middlewares
Middlewares are easy to create and lets you encapsulate your logic.
require "kemal"
class MyHandler < HTTP::Handler
def call(context)
puts "Doing authentication stuff here"
call_next context
end
end
Kemal.config.add_handler MyHandler.new
Kemal.run
26. @sdogruyol 26
Filters
before_get "/foo" do |ctx|
puts "Setting response content type"
ctx.response.content_type = "application/json"
end
get "/foo" do |ctx|
puts ctx.response.content_type # => "application/json"
{"name": "Kemal"}.to_json
end
after_get "/foo" do |ctx|
puts "Doing stuff after the response is sent"
update_cache
end
27. @sdogruyol 27
Generic View Templating
Kemal uses Kilt(a la Tilt) as the view engine.
<h1>This is just like ERB!</h1>
<p>Let's run some Crystal Code</p>
<% some_var = "Serdar %>
<%= Process.pid %>
h1 This is just like HAML!
p Let's run some Crystal code.
- some_var = "Serdar"
= Process.pid
hello.ecr hello.slang
You can render your view like
render "src/views/hello.ecr"
With layout
render "src/views/hello.ecr", "src/views/layouts/layout.ecr"