Professional Programmer Notes

or just call this my soapbox

Posts Tagged ‘camping

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.

Advertisement

Written by curtismitchell

October 5, 2007 at 10:22 am

Posted in Ruby

Tagged with , , , , , ,