DEV Community

Cover image for A Crystal Story: oh! so many options!
Franciscello
Franciscello

Posted on

A Crystal Story: oh! so many options!

Previously on ...

In case you missed it, we are building a Simple Static File Server using the Crystal language. And in this 2nd episode of the trilogy we are going to add options to our File Server.

Adding options is like making a cake ... mmm, ok ... wait, it has nothing to do with that 😅. Maybe it's more like buying a cake: most of the time we are presented with options 🤔. I know: it's a really bad analogy 🙈 but let's continue ...

What to parameterize?

When creating our server we need to set the path with the files we want to serve and the port where our server will listen. Let's go and set these two attributes as command line options to our server.

Command line options in Crystal

Adding the ability to pass options via command line is really easy and intuitive.

wait wait! I got it: adding options is like adding sprinkles to a cake 😏

We may read all about it in the section entitled Command Line Interface Application in Crystal's language reference (it's worth mentioning that there are examples based on the The Beatles! 😆)

Here's the first example shown in the previous reference:

# file: help.cr
require "option_parser"

OptionParser.parse do |parser|
  parser.banner = "Welcome to The Beatles App!"

  parser.on "-v", "--version", "Show version" do
    puts "version 1.0"
    exit
  end
  parser.on "-h", "--help", "Show help" do
    puts parser
    exit
  end
end

So, it looks like we need to use the method parse defined in OptionParser. Inside the block passed to OptionParser#parse we will define the options we want our application to have (for example, -v or -h). Easy!

Adding options to our Static File Server

As we mention before, we need to define three options:

  • -f: to set the files path
  • -p: to set the server port
  • -h: show help

The code will look like this:

OptionParser.parse do |parser|
  parser.banner = "A Simple Static File Server!"

  parser.on "-f PATH", "--files=PATH", "Files path (default: #{path})" do |files_path|
    path = files_path
  end
  parser.on "-p PORT", "--port=PORT", "Port to listen (default: #{port})" do |server_port|
    port = server_port.to_i
  end
  parser.on "-h", "--help", "Show help" do
    puts parser
    exit
  end
end

Let's not forget the default values!

path = "./public"
port = 8081

And that's it! Let's put all together and ...

... here is the cake 🍰

After all, maybe it is like making a cake 😉

# file_server_option.cr
require "http"
require "option_parser"

path = "./public"
port = 8081

OptionParser.parse do |parser|
  parser.banner = "A Simple Static File Server!"

  parser.on "-f PATH", "--files=PATH", "Files path (default: #{path})" do |files_path|
    path = files_path
  end
  parser.on "-p PORT", "--port=PORT", "Port to listen (default: #{port})" do |server_port|
    port = server_port.to_i
  end
  parser.on "-h", "--help", "Show help" do
    puts parser
    exit
  end
end

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

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

Is it working? 🤔

First, let's try showing the help:

$ crystal file_server_option.cr -- -h
A Simple Static Cake Server!
    -f PATH, --files=PATH            Files path (default: ./public)
    -p PORT, --port=PORT             Port to listen (default: 8081)
    -h, --help                       Show help

Now, let's start our server with different path and port:

$ crystal file_server_option.cr -- -f"." -p8080

Note: we use -- to pass parameters to our application because we are using the crystal command line to run the application. If we use -f"." -p8080 directly then we would be passing the parameter to crystal instead 🙃

The application replies:

Listening on http://127.0.0.1:8080 and serving files in path .

Now, if we navigate to http://localhost:8080/ then the content of the current folder will be displayed in the browser window.

All done! Piece of cake!🧁

Farewell and see you later.

Coming next: We are going to dockerize our cake static file server! 🐳

Thanks, thanks, thanks to:
@bcardiff , @diegoliberman and @petti for reviewing this post and improving the code and text!! 👏🤓

Photo by Hanh Nguyen on Unsplash

Top comments (0)