Sinatra is a F/OSS DSL, also referred to as a micro-framework, for quickly creating web applications in Ruby with minimal effort.
Sinatra is tiny – its source code is less than 2000 lines. Small, but mighty, and very influential. Since its release in 2007, a partial list of other web frameworks that Sinatra has inspired and are currently active at the time of writing, includes Compojure, Express.js, Fiber, Finatra, Flask, Javalin, Padrino, Pedestal, Play Framework, Roda, Scalatra, Scotty, Spark, Spring Boot, and Trot.
Sinatra is the second most popular web framework in the Ruby ecosystem, after Ruby on Rails.
Sinatra and Ruby on Rails are somewhat similar,
because they both extend Rack.
This means that middleware that conforms to the
read the rack
specification
works with all web frameworks that extend rack
.
Sinatra is a good choice for system integration, because it is simple, maleable, has few dependencies and is reasonably efficient. Sinatra webapps are a good mechanism for integrating web servers such as nginx and Apache httpd with other services, such as e-commerce payment gateways.
The following build on this Sinatra webapp:
If you want to learn Sinatra, here are two good references:
Sinatra applications can automatically be restarted when their source code changes.
This requires a helper application, such as rerun;
other projects also do similar things.
To install rerun
on Ubuntu:
$ sudo apt install rerun
Rerun is not currently compatible with WSL or WSL2.
Future versions of WSL2 will likely work with rerun
.
Previously, I wrote about how to Setting Up a Ruby Development Environment. Follow those instructions first if you want to type along with this blog post.
Get the project:
$ git clone https://github.com/mslinn/SinatraRequestExplorer.git $ cd SinatraRequestExplorer
Install the SinatraRequestExplorer
gems:
$ bundle install
$ rerun ruby main.rb 9:39:55 [rerun] Sinatrarequestexplorer launched 09:39:55 [rerun] Rerun (760521) running Sinatrarequestexplorer (760542) == Sinatra (v3.0.3) has taken the stage on 9876 for development with backup from Puma Puma starting in single mode... * Puma version: 6.0.0 (ruby 3.1.0-p0) ("Sunflower") * Min threads: 0 * Max threads: 5 * Environment: development * PID: 760542 * Listening on http://127.0.0.1:9876 * Listening on http://[::1]:9876 Use Ctrl-C to stop 09:39:57 [rerun] Watching . for **/*.{rb,js,coffee,css,scss,sass,erb,html,haml,ru,yml,slim,md,feature,c,h} with Linux adapter
Visit the SinatraRequestExplorer
webapp at port 9876.
The web page displayed in response to the GET Test link above is:
HTTP_USER_AGENT=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36 Method: GET request.accept: */* application/signed-exchange application/xhtml+xml application/xml image/apng image/avif image/webp text/html request.url=http://localhost:9876/dump?a=b&c=d request.fullpath=/dump?a=b&c=d request.path_info=/dump request.params: a=b c=d Computed Content-Type: plain
The web page displayed in response to the POST Test button above is:
HTTP_USER_AGENT=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36 Method: POST request.accept: */* application/signed-exchange application/xhtml+xml application/xml image/apng image/avif image/webp text/html request.url=http://localhost:9876/dump request.fullpath=/dump request.path_info=/dump request.params: Computed Content-Type: plain
The web page displayed in response to the JSON Test button above is:
HTTP_USER_AGENT=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36 Method: POST request.accept: */* application/signed-exchange application/xhtml+xml application/xml image/apng image/avif image/webp text/html request.url=http://localhost:9876/dump request.fullpath=/dump request.path_info=/dump request.params: field1=value1 field2=value2 Computed Content-Type: plain
Use curl
to invoke the SinatraRequestExplorer
webapp:
$ URL=http://localhost:9876/dump $ curl -d "param1=value1¶m2=value2" -X POST "$URL" <title>SinatraRequestExplorer dump</title> <h2>Post Method</h2> <p>Generated by the post /dump handler.</p> <p>Go to <a href="/">Root</a>.</p> <h2>Request Parameters</h2> <pre> request.url=http://localhost:9876/dump request.fullpath=/dump request.path_info=/dump request.params= param1=value1 param2=value2 HTTP_USER_AGENT=curl/7.85.0 </pre>
The test
script in SinatraRequestExplorer
automates the above invocation and includes others.
#!/bin/bash # Curl, and most browsers, default to sending Content-Type: application/x-www-form-urlencoded for a POST. # Get requests should not specify Content-type because they do not have a body. # Curl defaults to Accept: */*, however each browser defaults to a different default value. # Chrome defaults to Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8 # See https://developer.mozilla.org/en-US/docs/Web/HTTP/Content_negotiation/List_of_default_Accept_values shopt -s expand_aliases alias curl='curl -L --silent --show-error' function label { printf "\n\n=== $@ ===\n" } URL=http://localhost:9876/dump label "Send GET, accept any type of response" curl "$URL?a=b&c=d" label "Send GET, expect a JSON response" curl -H "Accept: application/json" "$URL?a=b&c=d" label "Send POST, accept any type of response" curl -d "param1=value1¶m2=value2" "$URL" label "Send POST with a form-urlencoded body and a query string, accept any type of response" curl -d "param1=value1¶m2=value2" "$URL?a=b&c=d" label "Send POST with a form-urlencoded body, expect a JSON response" curl -d "param1=value1¶m2=value2" \ -H "Accept: application/json" \ $URL label "Send POST with a JSON body, expect a JSON response" curl -d '{"param3":"value3", "param4":"value4"}' \ -H "Accept: application/json" \ -H "Content-Type: application/json" \ $URL
Rerun
is not something you would want or need in production.
Instead, you could launch Sinatra
webapps such as SinatraRequestExplorer
when the system boots with an entry in crontab
, like this:
@reboot ruby /work/ruby/sinatra/SinatraRequestExplorer/main.rb