Professional Programmer Notes

or just call this my soapbox

Fix for serving static files with Mongrel using Camping

with one comment

Last night, at our Ruby hack night, I had some assistance debugging a known issue with Why’s magic framework, Camping. Ok, let me be honest; Nathaniel fixed the issue while I sat and observed.

The issue occurs when you try to serve static content like images and style sheets using Mongrel. You can use Why’s example to spin up a controller to handle the static content using X-SendFile like this:


module Camping::Controllers
  class Static < R '/static/(.+)'
    MIME_TYPES = {'.css' => 'text/css', '.js' => 'text/javascript', '.jpg' => 'image/jpeg'}
    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
end

This code should allow Mongrel to serve any file under the “static” directory. This works as expected on non-Win32 platforms.

To correct this issue on Windows, a change has to be made to the Camping handler in Mongrel. Here is a diff that depicts the fix:


--- camping.rb.orig 2007-10-04 20:36:01.000000000 -0400
+++ camping.rb 2007-10-04 21:31:42.000000000 -0400
@@ -38,7 +38,7 @@
@@file_only_methods = ["GET","HEAD"]


def initialize(klass)
- @files = Mongrel::DirHandler.new("/",false)
+ @files = Mongrel::DirHandler.new(File.dirname(klass.instance_eval{@script}),false)
@guard = Mutex.new
@klass = klass
end

This change will impact the “path” parameter that is passed into the controller. Subsequently, the controller should be modified to take advantage of this change:


module Camping::Controllers
  class Static < R '/static/(.+)'
    MIME_TYPES = {'.css' => 'text/css', '.js' => 'text/javascript', '.jpg' => 'image/jpeg'}
    def get(path)
      @headers['Content-Type'] = MIME_TYPES[path[/\.\w+$/, 0]] || "text/plain"
      unless path.include? ".." # prevent directory traversal attacks
        @headers['X-Sendfile'] = path
      else
        @status = "403"
        "403 - Invalid path"
      end
    end
  end
end

As you may have guessed, this will break the contract with non-Win32 platforms, which is why I have not suggested this change to the Mongrel group. But, I hope you find it useful.

Advertisements

Written by curtismitchell

October 5, 2007 at 10:22 am

Posted in Ruby

Tagged with , , , , , ,

One Response

Subscribe to comments with RSS.

  1. Hi decent little post right right right here, was just wondering if i could quote some of it in the post im executing (I will credit and hyperlink back again below!). Drop me a message if thats not ok. you’ll be able to quote any of my stuff as prolonged as you hyperlink back again to it 🙂 Also fantastic template you use below would you thoughts telling me where by by you got it :D. Sorry for my english 🙂

    Joseph Briggeman

    June 13, 2010 at 11:59 am


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: