Blogging with jekyll, rack and heroku for free!

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

Comments