How to Serve Static Files via Rack

How to serve static files via Rack?

To redirect every request to a particular path, use Rack::File (for some reason this class is absent in recent documentation, but it is still part of the latest Rack):

run Rack::File.new("/my/path")

To redirect every request, and add an HTML index of all files in the target dir, use Rack::Directory:

run Rack::Directory.new("/my/path")

To combine several directories or serve only a some requests from the target dir:

map "/url/prefix" do
run Rack::File.new("/my/path")
end

# More calls to map if necessary...

# All other requests.
run MyApp.new

Static File serving using Rack

Cuba tries to render a template, so you can rename your file to .mote and it should render ok, or use something like this:

res.headers["Content-Type"] = "text/html; charset=utf-8"
res.write(IO.read('/path/to/your/file.html'))

Source is pretty clear on how the render function works.

How to mount static files for Rack

You need to use Rack::Builder in order to use the use SomeMiddleware syntax in a normal Ruby script (it's normally used in a config.ru file). You also need run for your application. Note that the urls key to Rack::Static takes an array, not a single string:

require 'rack'
Rack::Handler::Thin.run(Rack::Builder.new {
use(Rack::Static, urls: ["/resource/"], root: "/")
run ->env{[200, {}, [some_dyamically_generated_content]]}
}, Port: 3000)

Here Rack::Builder is taking your application, ->env{[200, {}, [some_dyamically_generated_content]]}, adding the Rack::Static middleware to it and creating a new combined application which is then passed to Thin to run.

Rack::Static is a middleware component that you can add to existing rack applications. Rack::File and Rack::Directory are both themselves rack applications, not middleware (Rack::Static uses Rack::File internally, as does Rack::Directory by default). You could achieve the same effect as above using Rack::File and the map command:

require 'rack'
Rack::Handler::Thin.run(Rack::Builder.new {
map "/resource/" do
run Rack::File.new "/"
end
map "/" do
run ->env{[200, {}, [some_dyamically_generated_content]]}
end
}, Port: 3000)

The more common way to do this would be to put the contents of the block passed to Rack::Bundler.new in a config.ru file:

use(Rack::Static, urls: ["/resource/"], root: "/") 
run ->env{[200, {}, [some_dyamically_generated_content]]}

You can then run this with thin start, which should find config.ru if run from the same directory, or you can use the -R option to specify the file. The rackup command can also be used, rackup -s thin if you want to specify Thin as the server.

Serve files using Rack TryStatic directly?

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.

Rack middleware serve static folders from submodule

It looks like the working directory might be messed with depending on how your Rails application is launched.

I got it working inside a Rails applicaiton with the following config.ru:

# This file is used by Rack-based servers to start the application.

use Rack::Static, :urls => ["/folder_a", "/folder_b"], :root => ::File.expand_path("submodule/public")

require ::File.expand_path('../config/environment', __FILE__)
run Rails.application

Then in a terminal:

$ rails server -d
=> Booting WEBrick
=> Rails 4.2.0 application starting in development on http://localhost:3000
=> Run `rails server -h` for more startup options

$ curl http://0.0.0.0:3000/folder_a/index.html
A

$ curl http://0.0.0.0:3000/folder_b/index.html
B

Pow config.ru for serving static files outside of the public directory?

You could use TryStatic from rack-contrib:

require 'rack/contrib/try_static'

use Rack::TryStatic,
:root => "html",
:urls => %w[/]

You might want to add if ENV['RACK_ENV'] == 'development' if you only want this during development (e.g. if your web server is configured to serve from html/)
.



Related Topics



Leave a reply



Submit