Reputation: 137792
In Camping, how's it best to serve static files, such as css?
Right now I have
class Style < R '/cards.css'
def get
@headers["Content-Type"] = "text/css"
File.read('cards.css')
end
end
Is there a smarter way involving Rack?
Upvotes: 5
Views: 730
Reputation: 1221
Camping's current (remember to install the latest version from RubyGems!) stance on static files is that the server should be responsible for serving static files.
If you use the camping
-command then the public/
-directory should automatically be served for you. Simply move cards.css
into public/cards.css
and localhost:3301/cards.css should return the file.
In production you should configure Apache/Nginx/whatever to serve files directly from the public/
-directory.
If you can't configure Apache/Nginx (e.g. in Heroku) you can write a custom config.ru like this:
# Your Camping app:
app = MyApp
# Static files:
files = Rack::File.new('public')
# First try the static files, then "fallback" to the app
run Rack::Cascade.new([files, app], [405, 404, 403])
(This is what Camping::Server does internally: https://github.com/camping/camping/blob/5201b49b753fe29dc3d2e96405d724bcaa7ad7d4/lib/camping/server.rb#L151)
For small files, you can store them in the DATA-block of your app.rb: https://github.com/camping/camping/blob/5201b49b753fe29dc3d2e96405d724bcaa7ad7d4/test/app_file.rb#L37
This is also useful if you want to keep everything inside one file.
Camping.goes :Foo
__END__
@@ /cards.css
...
Camping will use the file extension to set the correct Content-Type.
Also, the latest version of Camping has a serve
-method which handles the Content-Type for you. You could simplify your controller to this:
class Style < R '/style.css'
def get
serve "cards.css", File.read("cards.css")
end
end
I'll have to apologize for the bad documentation. For now you
Upvotes: 9
Reputation: 4132
Here's a suggestion originally by whytheluckystiff:
class Static < R '/static/(.+)'
MIME_TYPES = {
'.html' => 'text/html',
'.css' => 'text/css',
'.js' => 'text/javascript',
'.jpg' => 'image/jpeg',
'.gif' => 'image/gif'
}
PATH = File.expand_path(File.dirname(@__FILE__@))
def get(path)
@headers['Content-Type'] = MIME_TYPES[path[/\.\w+$/, 0]] || "text/plain"
unless path.include? ".." # prevent directory traversal attacks
@headers['X-Sendfile'] = "#{PATH}/static/#{path}"
else
@status = "403"
"403 - Invalid path"
end
end
end
PS- Actually, you can find some other great ideas here, like file uploads, sessions, etc.
Upvotes: 2