about summary refs log tree commit homepage
diff options
context:
space:
mode:
authorzedshaw <zedshaw@19e92222-5c0b-0410-8929-a290d50e31e9>2006-02-08 12:48:41 +0000
committerzedshaw <zedshaw@19e92222-5c0b-0410-8929-a290d50e31e9>2006-02-08 12:48:41 +0000
commit98a33bb30438c2bcbb10d48523afd9d491750a1e (patch)
treec9d06e668e43720cab061ce4a45fa302d357efe8
parent788e4f4902992a9de25f995729b7de713003bcc2 (diff)
downloadunicorn-98a33bb30438c2bcbb10d48523afd9d491750a1e.tar.gz
git-svn-id: svn+ssh://rubyforge.org/var/svn/mongrel/trunk@21 19e92222-5c0b-0410-8929-a290d50e31e9
-rw-r--r--README12
-rw-r--r--Rakefile2
-rw-r--r--examples/mongrel_rails.rb73
-rw-r--r--examples/simpletest.rb22
-rw-r--r--ext/http11/http11_parser.c122
-rw-r--r--lib/mongrel.rb58
6 files changed, 205 insertions, 84 deletions
diff --git a/README b/README
index 050c3cf..be4da9c 100644
--- a/README
+++ b/README
@@ -11,7 +11,7 @@ scream without too many portability issues.
 
 == Status
 
-The 0.2.1 release of Mongrel features an HTTP core server that is the fastest possible
+The 0.2.2 release of Mongrel features an HTTP core server that is the fastest possible
 thing I could get without using something other than Ruby.  It features a few bug fixes,
 but mostly just a change to the Mongrel::HttpResponse class to make it more feature
 complete.  The remaining development will be spent getting Mongrel to work with
@@ -28,6 +28,9 @@ page found at http://rubyforge.org/projects/mongrel/ thanks to Tom Copland.
 I'll be looking to automate management of this, but feel free to use
 rubyforge to post feature requests, bugs, and join the mailing list.
 
+Finally, it now supports all CGI parameters that don't cause a performance hit,
+and it has a Mongrel::DirHandler which can serve files out of a directory and
+do (optional) directory listings.
 
 == Install
 
@@ -40,7 +43,6 @@ who can build it for you.
 
 Finally, the source includes a setup.rb for those who hate RubyGems.
 
-
 == Usage
 
 The examples/simpletest.rb file has the following code as the simplest
@@ -59,6 +61,7 @@ example:
 
  h = Mongrel::HttpServer.new("0.0.0.0", "3000")
  h.register("/test", SimpleHandler.new)
+ h.register("/files", DirHandler.new("."))
  h.run.join
 
 If you run this and access port 3000 with a browser it will say
@@ -66,6 +69,11 @@ If you run this and access port 3000 with a browser it will say
 give a simple 404.  Check out the Mongrel::Error404Handler for a
 basic way to give a more complex 404 message.
 
+This also shows the DirHandler with directory listings.  This is still
+rough but it should work for basic hosting.  *File extension to mime
+type mapping is missing though.*
+
+
 == Speed
 
 The 0.2.1 release probably consists of the most effort I've ever put into
diff --git a/Rakefile b/Rakefile
index f084c88..3dddf71 100644
--- a/Rakefile
+++ b/Rakefile
@@ -27,4 +27,4 @@ setup_extension("http11", "http11")
 
 summary = "An experimental fast simple web server for Ruby."
 test_file = "test/test_ws.rb"
-setup_gem("mongrel", "0.2.1",  "Zed A. Shaw", summary, [], test_file)
+setup_gem("mongrel", "0.2.2",  "Zed A. Shaw", summary, [], test_file)
diff --git a/examples/mongrel_rails.rb b/examples/mongrel_rails.rb
new file mode 100644
index 0000000..ab5b740
--- /dev/null
+++ b/examples/mongrel_rails.rb
@@ -0,0 +1,73 @@
+require 'mongrel'
+require 'cgi'
+require 'config/environment'
+
+class CGIFixed < ::CGI
+  public :env_table
+  
+  def initialize(params, data, out, *args)
+    @env_table = params
+    @args = *args
+    @input = StringIO.new(data)
+    @out = out
+    super(*args)
+  end
+  
+  def args
+    @args
+  end
+  
+  def env_table
+    @env_table
+  end
+  
+  def stdinput
+    @input
+  end
+  
+  def stdoutput
+    @out
+  end
+end
+
+
+class RailsHandler < Mongrel::HttpHandler
+  def initialize
+    @guard = Mutex.new
+  end
+  
+  def process(request, response)
+    # not static, need to talk to rails
+    return if response.socket.closed?
+    
+    cgi = CGIFixed.new(request.params, request.body, response.socket)
+    begin
+
+      @guard.synchronize do
+        # Rails is not thread safe so must be run entirely within synchronize
+        Dispatcher.dispatch(cgi, ActionController::CgiRequest::DEFAULT_SESSION_OPTIONS, response.body)
+      end
+
+      response.send_status
+      response.send_body
+    rescue IOError
+      @log.error("received IOError #$! when handling client.  Your web server doesn't like me.")
+    rescue Object => rails_error
+      @log.error("calling Dispatcher.dispatch", rails_error)
+    end
+  end
+end
+
+if ARGV.length != 3
+  STDERR.puts "usage:  mongrel_rails.rb <host> <port> <docroot>"
+  exit(1)
+end
+
+h = Mongrel::HttpServer.new(ARGV[0], ARGV[1])
+h.register("/", Mongrel::DirHandler.new(ARGV[2]))
+h.register("/app", RailsHandler.new)
+h.run
+
+puts "Mongrel running on #{ARGV[0]}:#{ARGV[1]} with docroot #{ARGV[2]}"
+
+h.acceptor.join
diff --git a/examples/simpletest.rb b/examples/simpletest.rb
index 532e289..893df96 100644
--- a/examples/simpletest.rb
+++ b/examples/simpletest.rb
@@ -4,14 +4,24 @@ require 'yaml'
 class SimpleHandler < Mongrel::HttpHandler
     def process(request, response)
       response.start do |head,out|
-        head["Content-Type"] = "text/plain"
-        out.write("hello!\n")
+        head["Content-Type"] = "text/html"
+        out << "<html><body>Your request:<br />"
+        out << "<pre>#{request.params.to_yaml}</pre>"
+        out << "<a href=\"/files\">View the files.</a></body></html>"
       end
     end
 end
 
-h = Mongrel::HttpServer.new("0.0.0.0", "3000")
-h.register("/test", SimpleHandler.new)
-h.register("/files", Mongrel::DirHandler.new("."))
-h.run.join
+if ARGV.length != 3
+  STDERR.puts "usage:  simpletest.rb <host> <port> <docroot>"
+  exit(1)
+end
+
+h = Mongrel::HttpServer.new(ARGV[0], ARGV[1])
+h.register("/", SimpleHandler.new)
+h.register("/files", Mongrel::DirHandler.new(ARGV[2]))
+h.run
+
+puts "Mongrel running on #{ARGV[0]}:#{ARGV[1]} with docroot #{ARGV[2]}"
 
+h.acceptor.join
diff --git a/ext/http11/http11_parser.c b/ext/http11/http11_parser.c
index 83d0431..9c1c01b 100644
--- a/ext/http11/http11_parser.c
+++ b/ext/http11/http11_parser.c
@@ -1,4 +1,4 @@
-#line 1 "http11_parser.rl"
+#line 1 "ext/http11/http11_parser.rl"
 #include "http11_parser.h"
 #include <stdio.h>
 #include <assert.h>
@@ -9,28 +9,28 @@
 #define MARK(S,F) assert((F) - (S)->mark >= 0); (S)->mark = (F);
 
 /** machine **/
-#line 98 "http11_parser.rl"
+#line 98 "ext/http11/http11_parser.rl"
 
 
 /** Data **/
 
-#line 18 "http11_parser.c"
+#line 18 "ext/http11/http11_parser.c"
 static int http_parser_start = 0;
 
 static int http_parser_first_final = 56;
 
 static int http_parser_error = 1;
 
-#line 102 "http11_parser.rl"
+#line 102 "ext/http11/http11_parser.rl"
 
 int http_parser_init(http_parser *parser)  {
     int cs = 0;
     
-#line 30 "http11_parser.c"
+#line 30 "ext/http11/http11_parser.c"
         {
         cs = http_parser_start;
         }
-#line 106 "http11_parser.rl"
+#line 106 "ext/http11/http11_parser.rl"
     parser->cs = cs;
     parser->body_start = NULL;
     parser->content_len = 0;
@@ -50,7 +50,7 @@ size_t http_parser_execute(http_parser *parser, const char *buffer, size_t len)
     pe = buffer+len;
 
     
-#line 54 "http11_parser.c"
+#line 54 "ext/http11/http11_parser.c"
         {
         p -= 1;
         if ( ++p == pe )
@@ -70,14 +70,14 @@ case 0:
 st1:
         goto _out1;
 tr13:
-#line 14 "http11_parser.rl"
+#line 14 "ext/http11/http11_parser.rl"
         { MARK(parser, p); }
         goto st2;
 st2:
         if ( ++p == pe )
                 goto _out2;
 case 2:
-#line 81 "http11_parser.c"
+#line 81 "ext/http11/http11_parser.c"
         if ( (*p) == 69 )
                 goto st3;
         goto st1;
@@ -117,7 +117,7 @@ case 7:
                 goto tr33;
         goto st1;
 tr33:
-#line 29 "http11_parser.rl"
+#line 29 "ext/http11/http11_parser.rl"
         {
                if(parser->request_method != NULL)
                               parser->request_method(parser->data, parser->mark, p - parser->mark);
@@ -127,7 +127,7 @@ st8:
         if ( ++p == pe )
                 goto _out8;
 case 8:
-#line 131 "http11_parser.c"
+#line 131 "ext/http11/http11_parser.c"
         switch( (*p) ) {
                 case 42: goto tr27;
                 case 43: goto tr28;
@@ -144,26 +144,26 @@ case 8:
                 goto tr28;
         goto st1;
 tr27:
-#line 14 "http11_parser.rl"
+#line 14 "ext/http11/http11_parser.rl"
         { MARK(parser, p); }
         goto st9;
 st9:
         if ( ++p == pe )
                 goto _out9;
 case 9:
-#line 155 "http11_parser.c"
+#line 155 "ext/http11/http11_parser.c"
         if ( (*p) == 32 )
                 goto tr34;
         goto st1;
 tr34:
-#line 33 "http11_parser.rl"
+#line 33 "ext/http11/http11_parser.rl"
         {
                if(parser->request_uri != NULL)
                               parser->request_uri(parser->data, parser->mark, p - parser->mark);
         }
         goto st10;
 tr48:
-#line 37 "http11_parser.rl"
+#line 37 "ext/http11/http11_parser.rl"
         {
                if(parser->query_string != NULL)
                               parser->query_string(parser->data, parser->mark, p - parser->mark);
@@ -173,19 +173,19 @@ st10:
         if ( ++p == pe )
                 goto _out10;
 case 10:
-#line 177 "http11_parser.c"
+#line 177 "ext/http11/http11_parser.c"
         if ( (*p) == 72 )
                 goto tr11;
         goto st1;
 tr11:
-#line 14 "http11_parser.rl"
+#line 14 "ext/http11/http11_parser.rl"
         { MARK(parser, p); }
         goto st11;
 st11:
         if ( ++p == pe )
                 goto _out11;
 case 11:
-#line 189 "http11_parser.c"
+#line 189 "ext/http11/http11_parser.c"
         if ( (*p) == 84 )
                 goto st12;
         goto st1;
@@ -243,7 +243,7 @@ case 18:
                 goto st18;
         goto st1;
 tr37:
-#line 42 "http11_parser.rl"
+#line 42 "ext/http11/http11_parser.rl"
         {        
                if(parser->http_version != NULL)
                               parser->http_version(parser->data, parser->mark, p - parser->mark);
@@ -253,7 +253,7 @@ st19:
         if ( ++p == pe )
                 goto _out19;
 case 19:
-#line 257 "http11_parser.c"
+#line 257 "ext/http11/http11_parser.c"
         if ( (*p) == 10 )
                 goto st20;
         goto st1;
@@ -293,7 +293,7 @@ case 21:
                 goto tr40;
         goto st1;
 tr40:
-#line 46 "http11_parser.rl"
+#line 46 "ext/http11/http11_parser.rl"
         {
                parser->body_start = p+1; goto _out56;
         }
@@ -302,17 +302,17 @@ st56:
         if ( ++p == pe )
                 goto _out56;
 case 56:
-#line 306 "http11_parser.c"
+#line 306 "ext/http11/http11_parser.c"
         goto st1;
 tr36:
-#line 16 "http11_parser.rl"
+#line 16 "ext/http11/http11_parser.rl"
         { parser->field_start = p; }
         goto st22;
 st22:
         if ( ++p == pe )
                 goto _out22;
 case 22:
-#line 316 "http11_parser.c"
+#line 316 "ext/http11/http11_parser.c"
         switch( (*p) ) {
                 case 33: goto st22;
                 case 58: goto tr32;
@@ -338,7 +338,7 @@ case 22:
                 goto st22;
         goto st1;
 tr32:
-#line 17 "http11_parser.rl"
+#line 17 "ext/http11/http11_parser.rl"
         {
                parser->field_len = (p - parser->field_start);
         }
@@ -347,24 +347,24 @@ st23:
         if ( ++p == pe )
                 goto _out23;
 case 23:
-#line 351 "http11_parser.c"
+#line 351 "ext/http11/http11_parser.c"
         if ( (*p) == 13 )
                 goto tr56;
         goto tr55;
 tr55:
-#line 21 "http11_parser.rl"
+#line 21 "ext/http11/http11_parser.rl"
         { MARK(parser, p); }
         goto st24;
 st24:
         if ( ++p == pe )
                 goto _out24;
 case 24:
-#line 363 "http11_parser.c"
+#line 363 "ext/http11/http11_parser.c"
         if ( (*p) == 13 )
                 goto tr51;
         goto st24;
 tr51:
-#line 22 "http11_parser.rl"
+#line 22 "ext/http11/http11_parser.rl"
         {
                if(parser->http_field != NULL) {
                               parser->http_field(parser->data,
@@ -374,9 +374,9 @@ tr51:
         }
         goto st25;
 tr56:
-#line 21 "http11_parser.rl"
+#line 21 "ext/http11/http11_parser.rl"
         { MARK(parser, p); }
-#line 22 "http11_parser.rl"
+#line 22 "ext/http11/http11_parser.rl"
         {
                if(parser->http_field != NULL) {
                               parser->http_field(parser->data,
@@ -389,7 +389,7 @@ st25:
         if ( ++p == pe )
                 goto _out25;
 case 25:
-#line 393 "http11_parser.c"
+#line 393 "ext/http11/http11_parser.c"
         switch( (*p) ) {
                 case 10: goto st26;
                 case 13: goto tr51;
@@ -424,14 +424,14 @@ case 26:
                 goto tr42;
         goto st24;
 tr42:
-#line 16 "http11_parser.rl"
+#line 16 "ext/http11/http11_parser.rl"
         { parser->field_start = p; }
         goto st27;
 st27:
         if ( ++p == pe )
                 goto _out27;
 case 27:
-#line 435 "http11_parser.c"
+#line 435 "ext/http11/http11_parser.c"
         switch( (*p) ) {
                 case 13: goto tr51;
                 case 33: goto st27;
@@ -458,14 +458,14 @@ case 27:
                 goto st27;
         goto st24;
 tr28:
-#line 14 "http11_parser.rl"
+#line 14 "ext/http11/http11_parser.rl"
         { MARK(parser, p); }
         goto st28;
 st28:
         if ( ++p == pe )
                 goto _out28;
 case 28:
-#line 469 "http11_parser.c"
+#line 469 "ext/http11/http11_parser.c"
         switch( (*p) ) {
                 case 43: goto st28;
                 case 58: goto st29;
@@ -483,14 +483,14 @@ case 28:
                 goto st28;
         goto st1;
 tr30:
-#line 14 "http11_parser.rl"
+#line 14 "ext/http11/http11_parser.rl"
         { MARK(parser, p); }
         goto st29;
 st29:
         if ( ++p == pe )
                 goto _out29;
 case 29:
-#line 494 "http11_parser.c"
+#line 494 "ext/http11/http11_parser.c"
         switch( (*p) ) {
                 case 32: goto tr34;
                 case 37: goto st30;
@@ -531,14 +531,14 @@ case 31:
                 goto st29;
         goto st1;
 tr29:
-#line 14 "http11_parser.rl"
+#line 14 "ext/http11/http11_parser.rl"
         { MARK(parser, p); }
         goto st32;
 st32:
         if ( ++p == pe )
                 goto _out32;
 case 32:
-#line 542 "http11_parser.c"
+#line 542 "ext/http11/http11_parser.c"
         switch( (*p) ) {
                 case 32: goto tr34;
                 case 37: goto st34;
@@ -599,7 +599,7 @@ case 35:
                 goto st33;
         goto st1;
 tr46:
-#line 33 "http11_parser.rl"
+#line 33 "ext/http11/http11_parser.rl"
         {
                if(parser->request_uri != NULL)
                               parser->request_uri(parser->data, parser->mark, p - parser->mark);
@@ -609,7 +609,7 @@ st36:
         if ( ++p == pe )
                 goto _out36;
 case 36:
-#line 613 "http11_parser.c"
+#line 613 "ext/http11/http11_parser.c"
         switch( (*p) ) {
                 case 32: goto tr48;
                 case 37: goto tr54;
@@ -624,14 +624,14 @@ case 36:
                 goto st1;
         goto tr53;
 tr53:
-#line 14 "http11_parser.rl"
+#line 14 "ext/http11/http11_parser.rl"
         { MARK(parser, p); }
         goto st37;
 st37:
         if ( ++p == pe )
                 goto _out37;
 case 37:
-#line 635 "http11_parser.c"
+#line 635 "ext/http11/http11_parser.c"
         switch( (*p) ) {
                 case 32: goto tr48;
                 case 37: goto st38;
@@ -646,14 +646,14 @@ case 37:
                 goto st1;
         goto st37;
 tr54:
-#line 14 "http11_parser.rl"
+#line 14 "ext/http11/http11_parser.rl"
         { MARK(parser, p); }
         goto st38;
 st38:
         if ( ++p == pe )
                 goto _out38;
 case 38:
-#line 657 "http11_parser.c"
+#line 657 "ext/http11/http11_parser.c"
         if ( (*p) < 65 ) {
                 if ( 48 <= (*p) && (*p) <= 57 )
                         goto st39;
@@ -677,14 +677,14 @@ case 39:
                 goto st37;
         goto st1;
 tr14:
-#line 14 "http11_parser.rl"
+#line 14 "ext/http11/http11_parser.rl"
         { MARK(parser, p); }
         goto st40;
 st40:
         if ( ++p == pe )
                 goto _out40;
 case 40:
-#line 688 "http11_parser.c"
+#line 688 "ext/http11/http11_parser.c"
         if ( (*p) == 69 )
                 goto st41;
         goto st1;
@@ -696,14 +696,14 @@ case 41:
                 goto st7;
         goto st1;
 tr15:
-#line 14 "http11_parser.rl"
+#line 14 "ext/http11/http11_parser.rl"
         { MARK(parser, p); }
         goto st42;
 st42:
         if ( ++p == pe )
                 goto _out42;
 case 42:
-#line 707 "http11_parser.c"
+#line 707 "ext/http11/http11_parser.c"
         if ( (*p) == 69 )
                 goto st43;
         goto st1;
@@ -722,14 +722,14 @@ case 44:
                 goto st7;
         goto st1;
 tr16:
-#line 14 "http11_parser.rl"
+#line 14 "ext/http11/http11_parser.rl"
         { MARK(parser, p); }
         goto st45;
 st45:
         if ( ++p == pe )
                 goto _out45;
 case 45:
-#line 733 "http11_parser.c"
+#line 733 "ext/http11/http11_parser.c"
         if ( (*p) == 80 )
                 goto st46;
         goto st1;
@@ -769,14 +769,14 @@ case 50:
                 goto st7;
         goto st1;
 tr17:
-#line 14 "http11_parser.rl"
+#line 14 "ext/http11/http11_parser.rl"
         { MARK(parser, p); }
         goto st51;
 st51:
         if ( ++p == pe )
                 goto _out51;
 case 51:
-#line 780 "http11_parser.c"
+#line 780 "ext/http11/http11_parser.c"
         switch( (*p) ) {
                 case 79: goto st52;
                 case 85: goto st41;
@@ -790,14 +790,14 @@ case 52:
                 goto st41;
         goto st1;
 tr18:
-#line 14 "http11_parser.rl"
+#line 14 "ext/http11/http11_parser.rl"
         { MARK(parser, p); }
         goto st53;
 st53:
         if ( ++p == pe )
                 goto _out53;
 case 53:
-#line 801 "http11_parser.c"
+#line 801 "ext/http11/http11_parser.c"
         if ( (*p) == 82 )
                 goto st54;
         goto st1;
@@ -875,15 +875,15 @@ case 55:
 
         _out: {}
         }
-#line 125 "http11_parser.rl"
+#line 125 "ext/http11/http11_parser.rl"
 
     parser->cs = cs;
     parser->nread = p - buffer;
     if(parser->body_start) {
         /* final \r\n combo encountered so stop right here */
         
-#line 886 "http11_parser.c"
-#line 131 "http11_parser.rl"
+#line 886 "ext/http11/http11_parser.c"
+#line 131 "ext/http11/http11_parser.rl"
         parser->nread++;
     }
 
@@ -895,8 +895,8 @@ int http_parser_finish(http_parser *parser)
         int cs = parser->cs;
 
         
-#line 899 "http11_parser.c"
-#line 142 "http11_parser.rl"
+#line 899 "ext/http11/http11_parser.c"
+#line 142 "ext/http11/http11_parser.rl"
 
         parser->cs = cs;
 
diff --git a/lib/mongrel.rb b/lib/mongrel.rb
index 4b59549..1bc1c23 100644
--- a/lib/mongrel.rb
+++ b/lib/mongrel.rb
@@ -239,17 +239,29 @@ module Mongrel
       @body.rewind
     end
 
-    # This takes whatever has been done to header and body and then writes it in the
-    # proper format to make an HTTP/1.1 response.
-    def finished
+    def send_status
+      @socket.write("HTTP/1.1 #{@status} #{HTTP_STATUS_CODES[@status]}\r\nContent-Length: #{@body.length}\r\nConnection: close\r\n")
+    end
+
+    def send_header
       @header.out.rewind
+      @socket.write(@header.out.read)
+      @socket.write("\r\n")
+    end
+
+    def send_body
       @body.rewind
       
       # connection: close is also added to ensure that the client does not pipeline.
-      @socket.write("HTTP/1.1 #{@status} #{HTTP_STATUS_CODES[@status]}\r\nContent-Length: #{@body.length}\r\nConnection: close\r\n")
-      @socket.write(@header.out.read)
-      @socket.write("\r\n")
       @socket.write(@body.read)
+    end      
+
+    # This takes whatever has been done to header and body and then writes it in the
+    # proper format to make an HTTP/1.1 response.
+    def finished
+      send_status
+      send_header
+      send_body
     end
   end
   
@@ -408,7 +420,7 @@ module Mongrel
     # Sets the message to return.  This is constructed once for the handler
     # so it's pretty efficient.
     def initialize(msg)
-      @response = HttpServer::ERROR_404_RESPONSE + msg
+      @response = Const::ERROR_404_RESPONSE + msg
     end
     
     # Just kicks back the standard 404 response with your special message.
@@ -429,20 +441,39 @@ module Mongrel
   # that the final expanded path includes the root path.  If it doesn't
   # than it simply gives a 404.
   class DirHandler < HttpHandler
+    attr_reader :path
 
+    # You give it the path to the directory root and an (optional)
     def initialize(path, listing_allowed=true)
       @path = File.expand_path(path)
       @listing_allowed=listing_allowed
-      puts "DIR: #@path"
+    end
+
+    # Checks if the given path can be served and returns the full path (or nil if not).
+    def can_serve(path_info)
+      req = File.expand_path(path_info, @path)
+      if req.index(@path) != 0 or !File.exist? req
+        return nil
+      else
+        return req
+      end
     end
 
     def send_dir_listing(base, dir, response)
+      base.chop! if base[-1] == "/"[-1]
+
       if @listing_allowed
         response.start(200) do |head,out|
           head['Content-Type'] = "text/html"
           out << "<html><head><title>Directory Listing</title></head><body>"
           Dir.entries(dir).each do |child|
-            out << "<a href=\"#{base}/#{child}\">#{child}</a><br/>"
+            next if child == "."
+
+            if child == ".."
+              out << "<a href=\"#{base}/#{child}\">Up to parent..</a><br/>"
+            else
+              out << "<a href=\"#{base}/#{child}\">#{child}</a><br/>"
+            end
           end
           out << "</body></html>"
         end
@@ -464,9 +495,9 @@ module Mongrel
 
 
     def process(request, response)
-      req = File.expand_path("." + request.params['PATH_INFO'], @path)
-      puts "FIND: #{req}"
-      if req.index(@path) != 0 or !File.exist? req
+      path_info = request.params['PATH_INFO']
+      req = can_serve path_info
+      if not req
         # not found, return a 404
         response.start(404) do |head,out|
           out << "File not found"
@@ -481,9 +512,8 @@ module Mongrel
         rescue => details
           response.reset
           response.start(403) do |head,out|
-            out << "Error accessing file"
+            out << "Error accessing file: #{details}"
           end
-          STDERR.puts "ERROR: #{details}"
         end
       end
     end