Blogging with jekyll, rack and heroku for free!

gmarik 3 min

I’m not going to talk about setup and configuration cuz it’s trivial! Instead lets see how jekyll is served from heroku.

Jekyll generated site is a static site, so having something serving static files is just fine. There’s Rack::Static middleware shipped with Rack and you can use it for this purpose, ie with sample config.ru:

use ::Rack::Static,
  :root => "public",    # or _site/ where *.html are generated
  :urls => %w[/]        # match all requests
# otherwise 404 NotFound
run lambda { [404, {'Content-Type' => 'text/plain'}, ['whoops! Not Found']]}

starting rackup and pointing browser to http://localhost:9292/index.html should yield a jekyll homepage! Pretty cool, huh?

But there’s a problem: noone types /index.html these days!

rack/contrib/try_static

TryStatic is part of the rack-contrib-1.1.0 gem since this commit

With rack-contrib gem it’s even more simple! So now my config.ru looks like:

require 'rack'
require 'rack/contrib/try_static'

use Rack::TryStatic, 
    :root => "public",  # static files root dir
    :urls => %w[/],     # match all requests 
    :try => ['.html', 'index.html', '/index.html'] # try these postfixes sequentially
    # otherwise 404 NotFound
    run lambda { [404, {'Content-Type' => 'text/html'}, ['whoops! Not Found']]}

# vi: ft=ruby

And all we need to add a heroku gem manifest: .gems file, with content

rack-contrib

that’s it! Now you can push your app to heroku.

Obsolete

Solutions below are obsolete and for reference only! Use rack-contrib gem instead as described above.

rack-try_static gem

Using gem it’s even more simple! So now my config.ru looks like:

require 'rack'
require 'rack/contrib/try_static'

use Rack::TryStatic, 
    :root => "public",  # static files root dir
    :urls => %w[/],     # match all requests 
    :try => ['.html', 'index.html', '/index.html'] # try these postfixes sequentially
# otherwise 404 NotFound
run lambda { [404, {'Content-Type' => 'text/html'}, ['whoops! Not Found']]}

# vi: ft=ruby

And all we need to add a heroku gem manifest: .gems file, with content

rack-try_static

that’s it! Now you can push your app to heroku.

my initial quick solution:

module ::Rack
  class TryStatic < Static

    def initialize(app, options)
      super
      @try = ([''] + Array(options.delete(:try)) + [''])
    end

    def call(env)
      @next = 0
      while @next < @try.size && 404 == (resp = super(try_next(env)))[0] 
        @next += 1
      end
      404 == resp[0] ? @app.call : resp
    end

    private
    def try_next(env)
      env.merge('PATH_INFO' => env['PATH_INFO'] + @try[@next])
    end
  end
end

use Rack::TryStatic, 
    :root => "public",                              # static files root dir
    :urls => %w[/],                                 # match all requests 
    :try => ['.html', 'index.html', '/index.html']  # try these postfixes sequentially
# otherwise 404 NotFound
run lambda { [404, {'Content-Type' => 'text/plain'}, ['whoops! Not Found']]}

# vi: ft=ruby

I’ve called it Rack::TryStatic as it sequentially tries to serve a static file according :try option.

TODO

Read More
tracking Dotfiles with Git
rack-mail-exceptions-notification-middleware
Comments
read or add one↓