[001.4] Web server

Make a project with Kemal, a “Fast, Effective, Simple web framework for Crystal”

Subscribe now

Web server [08.22.2017]

Hi! Welcome back. In this episode we will close the playground and go back to working with the actual Crystal project we created all the way back in the first episode via crystal init.

Let’s start by setting up a simple hello world web service.

[Open src/hello.cr and replace contents]

require "http/server"

server = HTTP::Server.new(5000) do |context|

  context.response.content_type = "text/plain"

  context.response.print "Hello world, got #{context.request.path}!\n"

end

puts "Listening on http://127.0.0.1:5000"

server.listen

If this code looks familiar, it’s because it is the first snippet in the Crystal home page. Let’s go through it. The HTTP server constructor accepts a block that is executed every time a request hits the server. Each request is served by a separate green thread called a Fiber; without going into too much detail in Crystal’s concurrency model, let’s just say that Fibers are a sort of collaborative threads managed by Crystal, that yield control to other fibers on every I/O operation, thus being able to concurrently serve multiple requests.

Let’s run it and test it via a simple curl.

[In the console]

crystal src/hello.cr

[In another tab]

curl [http://localhost:5000](http://localhost:5000)

curl [http://localhost:5000/foo](http://localhost:5000/fooo)

You will probably want to review the API documentation for the HTTP server, where you will find examples on building more complex web servers by chaining handlers, and check out the available properties on the Context of each request.

[Open https://crystal-lang.org/api/latest/HTTP/Server.html]

Now, in order to build a more interesting web application, with routing and templating support out of the box, we’ll add Kemal as a dependency. Kemal is one of the (if not the most) popular web frameworks for Crystal, and is inspired by Ruby’s Sinatra.

[Open http://kemalcr.com/]

So, let’s add Kemal as a dependency in our shard.yml file and install it.

[On shard.yml]

dependencies:

  kemal:

    github: kemalcr/kemal

[On console]

crystal deps

Let’s rewrite our previous example using Kemal now:

require "kemal"

get "/:path" do |env|

  "Hello world, got #{env.params.url["path"]}!\n"

end

Kemal.run(5000)

Kemal allows us to provide route matchers via methods named after HTTP verbs, and access the request parameters from the URL path, query string, POST body, etc.

Let’s allow the server to receive a POST of a JSON with a name property, and make it respond by greeting that name:

post "/" do |env|

  env.response.content_type = "application/json"

  name = env.params.json["name"].as(String)

  {greeting: "Hello #{name}"}.to_json

end

And try it from the command line:

curl -XPOST -d '{"name": "world"}' -H "Content-Type: application/json" http://127.0.0.1:5000/

We have just built our (simple) JSON response by using Hash’s to_json method, but Crystal also has JSON builders and mappings built-in that we’ll cover in the next episode.

As a final touch, let’s upload this app to Heroku. We’ll make use of the Heroku Crystal buildpack, so let’s first register the application by running heroku CLI to create a heroku app with crystal's custom buildpack

heroku create --buildpack https://github.com/crystal-lang/heroku-buildpack-crystal.git

Heroku requires our web application to handle the -p option to specify the port. Fortunately, Kemal handles this out of the box, so we don’t need to make any changes; but keep this in mind if you are using a different framework.

Let’s now commit our latest changes and upload the application to Heroku.

git add .

git commit -m "Initial commit"

git push heroku master

We can now navigate to the generated URL, where we can find our Crystal app.

[Open heroku app URL in browser]

Of course, you can deploy your Crystal app to any server of your choice, by simply compiling the binary and copying it over. Just remember to build with the release flag, and on the same architecture and OS as your server.

This covers the basics of building a simple web application in Crystal. Feel free to browse Kemal’s documentation for more information on how to use it, or look into other frameworks such as Amethyst, Kemalyst, or Amber. Links to all these frameworks will be in the description. See you next time.