Serve files using Rack TryStatic directly?
Question
I'm using Middleman to create a static site.
Middleman generates static html files into ./build
directory.
Here's the config I'm currently using:
require 'rubygems'
require 'middleman'
require 'rack/contrib/try_static'
use Rack::TryStatic, :root => "build", :urls => %w[/], :try => ['.html']
run Middleman::Application.server
So Middleman is serving the static files right now. How can I make Rack::TryStatic
handle the requests directly?
I tried to make it something like
run Rack::TryStatic, :root => "build", :urls => %w[/], :try => ['.html']
But it doesn't work is run only accepts 1 argument. And Rack::TryStatic
requires 2 arguments, app
and options
to initialize, and I don't have any app
.
How can I do this?
(And if it matters, I'm deploying to Heroku)
Solution
As you’ve noticed, a Rack middleware component such as Rack::TryStatic
needs another app to pass requests onto. You could create a simple one to use that for example just returned a 404 response, such as:
app = lambda {|env| [404, {'Content-type' => 'text/plain'}, ['Not found']
run Rack::TryStatic.new app, :root => "build", :urls => %w[/], :try => ['.html']
or equivalently:
use Rack::TryStatic, :root => "build", :urls => %w[/], :try => ['.html']
run lambda {|env| [404, {'Content-type' => 'text/plain'}, ['Not found']]}
If you have your own 404 file, you could use rack-contrib’s Rack::NotFound
instead of a custom end point of your own:
use Rack::TryStatic, :root => "build", :urls => %w[/], :try => ['.html']
run Rack::NotFound.new('path/to/your/404.html')
If you weren’t using the :try
array of file extensions to try and serve, you could use Rack::File
directly. Internally, Rack::TryStatic
uses Rack::Static
, which in turn uses Rack::File
. Unlike TryStatic
and Static
, Rack::File
is a Rack application in its own right, and so doesn’t need a separate app to pass requests to. Your config.ru
would then simply be:
run Rack::File.new './build'
although this wouldn’t allow for “bare” requests to be served with the corresponding .html
file — all requests would need to specify the whole file name.