DEV Community

Cover image for A Crystal Story: Simple Static File Server!
Franciscello
Franciscello

Posted on • Edited on

A Crystal Story: Simple Static File Server!

Maybe we need to serve the files for our great-awesome new client-side application 😎? Or Maybe we are building a static file server for fun 🍹🌴?

Well, it doesn't matter why, but we need a Static File Server ... and soon! Here we are going to see how easy is to build one using the Crystal language! Yeah!!

A Server object, s'il vous plait ☝️🎩

First we need to create a HTTP Server object. We may initialize this server object with an array of handlers also known as handler chain. When a request arrives to the server then it goes through the handler chain: each handler (having a specific purpose) will process the request and then it will forward the request to the next handler and so on and so on...

For our static file server we are going to create a chain using:

HTTP::LogHandler

As the documentation says this is a handler that logs the request method, resource, status code, and the time used to execute the next handler, to the given IO.

HTTP::ErrorHandler

This handler invokes the next handler and, if that next handler raises an exception, returns with a 500 (Internal Server Error) status code.

HTTP::StaticFileHandler

As the name says this handler is a simple handler that lists directories and serves files under a given public directory. In this case, the directory will be ./public

And here is the code for creating the HTTP::Server object:

server = HTTP::Server.new([
  HTTP::LogHandler.new,
  HTTP::ErrorHandler.new,
  HTTP::StaticFileHandler.new("./public"),
])

Hey, server! Listen! 🤖🎧

Now that we have our server object, we need to specify the port to listen and to start listening! It's as easy as:

server.bind_tcp 8081
server.listen

And the final result is ... 🥁

# file_server.cr
require "http"

path = "./public"
server = HTTP::Server.new([
  HTTP::LogHandler.new,
  HTTP::ErrorHandler.new,
  HTTP::StaticFileHandler.new(path),
])

address = server.bind_tcp 8081
puts "Listening on http://#{address} and serving files in path #{path}"
server.listen

To start the server 🚀

$ crystal file_server.cr
Listening on http://127.0.0.1:8081 and serving files in path ./public

And that's it!!
Now we have a file server running on localhost, port 8081, serving files in the folder ./public.

Told you it was easy!! 😉

Farewell and see you later.

Coming next: We are going to parameterize this static file server!
Stay tuned! 📻

👏 As always thanks to:
@bcardiff and @diegoliberman for reviewing this post and improving the code and text!!

Photo by Jonathan Singer on Unsplash

Top comments (0)