Colonel Panic
Colonel Panic

Reputation: 137792

How to serve static files? (css)

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

Answers (2)

Magnus Holm
Magnus Holm

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

Josh Voigts
Josh Voigts

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

Related Questions