Sinatra Two Point Oh!

By zzak on Monday, May 15, 2017

Today, I’m pleased to FINALLY announce that Sinatra 2.0 was released!

If you haven’t been following along, the major version bump includes a lot of changes significant to the future of the project.

In this post, you will see the full details including what’s new, what’s gone, and everything packed into the two point oh release.

Before we begin, I have to thank everyone who contributed, helped test pre-releases, and continues to use and support the project.

Releases

Sinatra 2.0 includes the release of the following gems, and associated verions:

  • sinatra: v2.0.0
  • sinatra-contrib: v2.0.0
  • mustermann: v1.0.0
  • mustermann-contrib: v1.0.0
  • rack-protection: v2.0.0

You can download all of these gems from rubygems.org.

Major features

  • Rack 2.0 support, Rack 1.x is no longer supported
  • Ruby 2.2+ support, Ruby < 2.2 is no longer supported
  • Sinatra router replaced with Mustermann
  • Compatible with Rails 5! :trollface:

Sinatra core

Many of you have been waiting since before the Rails 5 release, for a Sinatra 2.0 pre-release.

Before we get into the changes, I want to address something.

Why 2.0 was delayed

First, there was a ridiculous number of tickets asking for a release, so many that I actually lost count to be honest.

Let me just say, thank you everyone for your patience and I hope that this release is worth the wait!

To put it short.

When I took on the challenge of releasing Sinatra 2.0, my goal was to not only bump minimum dependency requirements – but also make sure Sinatra is well maintained and provide the level of class people have come to expect from the project and it’s previous maintainer.

With that said, I hope the following features and changes that went into the release can live up to (not only mine) but everyone’s expectations.

Features

Changes

The following notable changes are also included in this release.

  • Make route params available during error handling PR by Jeremy Evans
  • Unify not_found and error 404 behavior PR by Jeremy Evans
  • Enable Ruby 2.3 frozen_string_literal feature PR by Vladimir Kochnev
  • Add Sinatra::ShowExceptions::TEMPLATE and patched Rack::ShowExceptions to prefer Sinatra template commit by Zachary Scott
  • Sinatra::Runner is used internally for integration tests PR by Nick Sutterer
  • Fix case-sensitivity issue in uri method PR by rennex
  • Use Rack::Utils.status_code to allow status helper to use symbol as well as numeric codes PR by Tobias H. Michaelsen
  • Improved error handling for invalid params through Rack PR by Jordan Owens
  • Ensure template is cached only once PR by Patrik Rak
  • Use same session_secret for classic and modular apps in development PR by Marcus Stollsteimer
  • Improve Session Secret documentation to encourage better security practices PR by Glenn Rempe
  • Exposed global and per-route options for Mustermann route parsing PR by Mike Pastore
  • Capture exception messages of raised NotFound and BadRequest PR by Mike Pastore
  • Add :strict_paths option for managing trailing slashes PR by namusyaka
  • Add full IndifferentHash implementation to params PR by Mike Pastore and PR by John Hope

Now let’s take a look at the peripheral work that went into the release of Sinatra 2.0.

Sinatra::Contrib

This gem provides a bunch of helpful extensions for common patterns that can be applied to your Sinatra application. Take a look at the documentation for a list of what you get.

The biggest change to the sinatra-contrib gem is that it is now bundled in the Sinatra source tree. Ticket by Zachary Scott.

Since the release, if you install the gem though you shouldn’t notice any difference. Alternitively you can install the gem from source, like so:

# Gemfile
github 'sinatra/sinatra' do
  gem 'sinatra-contrib'
end

This will fetch the sinatra git source and install the gem from the tree.

Also, we’ve consolidated the bug trackers, and you can now find sinatra-contrib related issues under this label.

Features

Here are the new features in Sinatra::Contrib.

Changes

And the following notable changes that went into the release.

  • Migrate specs to RSpec 3.4 PR by Jhimy Fernandes Villar
  • Sinatra::ConfigFile allow ERB syntax in YML files PR by Jhimy Fernandes Villar
  • Sinatra::ContentFor renders given block if specified key is not found PR by Micah Redding
  • Sinatra::ContentFor can yield an immediate value, similar to ActionView PR by Ryo Nakamura
  • Sinatra::LinkHeader to use “,\n” (comma, new-line) as delimiter PR by petedmarsh
  • Sinatra::Namespace allow using redirect_to in a namespace PR by Jhimy Fernandes Villar
  • Sinatra::RespondWith swallow exception from Tilt on LoadError for missing template PR by Matt Austin
  • Sinatra::RespondWith now raises a 500 error if formatting fails commit
  • Make Rack::Test a development dependency PR by Mike Pastore
  • Add explicit set method to contrib/cookies to override cookie settings PR by Andrew Allen
  • Avoid executing filters even if prefix matches with other namespace PR by namusyaka

Removals

  • Sinatra::Decompile is no longer necessary after added Mustermann support commit by Zachary Scott

For full details, compare the pre-merged diff and milestone.

Rack::Protection

This gem is designed to provide several middleware for protecting your applications against common web attacks. Take a look at the documentation for more information.

The biggest change to the rack-protection gem is that it is now bundled in the Sinatra source tree. PR by Zachary Scott.

Although I must admit, this change wasn’t without pitfalls, I apologize to everyone affected during the transition time.

Since the release, if you install the gem though you shouldn’t notice. Alternitively you can install the gem from source, like so:

# Gemfile
github 'sinatra/sinatra' do
  gem 'rack-protection'
end

This will fetch the sinatra git source and install the gem from the tree.

Also, we’ve consolidated the bug trackers, and you can now find rack-protection related issues under this label.

Features

Here are the new features in Rack::Protection

  • Rack::Protection::ContentSecurityPolicy PR by Christian Meier with Level 2 and 3 Directives in PR by Glenn Rempe
  • Rack::Protection::HttpOrigin and AuthenticityToken added :allow_if option to specify allowable urls PR by Nathan Stitt
  • Rack::Protection::CookieTossing PR by Jordan Owens
  • Rack::Protection::AuthenticityToken prevent BREACH attack PR by Jordan Owens
  • Added :without_session option to initializer to easily skip session-based protections commit by Zachary Scott

Changes

Along with the following notable changes that went into the release.

For full details, compare the pre-merged diff.

Mustermann

Mustermann is a powerful library with many features and compatible params parsing interface. It will replace the existing router in Sinatra for version 2.0.

Take a look at the documentation for more information.

Apart from the features and changes to the core of Mustermann, which I will list below, the biggest change in the first stable release is organizational.

  • mustermann-everything gem is deprecated
  • mustermann-contrib has replaced it, including all non-core extensions

Please check the PR for the full list of included plugins, but I hope this change will make maintaining and releasing Mustermann much simpler from now on.

Features

Here are the latest features in Mustermann version 1.0.

Changes

Along with the following notable changes that went into the release.

For the full details, compare the diff.

Wrapping up

In the end, there’s still more work to be done on the project and a bright future ahead.

At the time of writing this, there are almost 30 open issues and about 10 pull requests.

There are a number of places where Sinatra could improve, and although I’ve added a number of tickets for features, I’d like to end this by briefly listing some of these areas specifically.

Logging

Currently, Sinatra uses Rack::Logger middleware under the hood with a little bit extra.

This logger is barebones, and I’m sure we could build a much nicer logging API by ourselves that would prove more useful for dealing with production services.

Streaming

There have been a number of discussions on streaming, but I feel this is something that could definitely be improved.

While, there are some missing features mentioned, when this API was originally implemented Rack’s hijack api was still unfinished.

I don’t exactly know the best route for this, but probably start with something in the Rack layer – like is already being discussed. Then we can provide an API on top of that inside Sinatra’s DSL. For added bonus, we could wrap something like Sinatra::Streaming to make it really nice.

Exception Handling

The current implementation for error handling comes down to “handle_exception!”.

This method to me looks like it’s begging for a refactor, and just the cause of a bad API design (sorry).

What I mean is, it could definitely be improved, and maybe it’s “bad design” but hey it works! Right!

Also take a look at “error_block!” and “dump_errors!”.. what!

All of this along with a middleware, called “ShowExceptions”, for displaying errors both/either in plain-text and/or html.

Wait there’s more!

Without going into too much detail, route dispatch (including before/after filters) needs work. As well, @rkh has mentioned wanting to improve the Template API.

There is also stuff like an implementation of “indifferent_params” and “indifferent_hash”, that could be upstreamed in Ruby.

At any rate, there’s more than a few things here as well as a number of great ideas from @rkh himself that should keep us busy for a while.

Briefly about deprecations

One thing I want to say before I end this post, please please please pleeeease:

Do not send PRs to remove deprecations or unfactored code without good reason.

I won’t consider any changes like this until we start thinking about version 2.1.

Thank you

At any rate, I hope that Sinatra 2.0 is everything you hoped for and more, and apologize if your patch or bug wasn’t included in the release.

Thank you everyone who has contributed over the years to this project, and continues to ensure it lives on.

In the words of the great Nat King Cole, you’re unforgettable.