mirror of
https://github.com/puma/puma.git
synced 2022-11-09 13:48:40 -05:00
Fixed the URIClassifier to solve a problem with 1 character lookups. Completed more work on Rails runner. Add index.html default lookup for DirHandler. Added some new tests for URIClassifier.
git-svn-id: svn+ssh://rubyforge.org/var/svn/mongrel/trunk@24 19e92222-5c0b-0410-8929-a290d50e31e9
This commit is contained in:
parent
3c343cca6b
commit
bce8665853
5 changed files with 92 additions and 27 deletions
|
@ -1,4 +1,4 @@
|
|||
require 'config/environment'
|
||||
require 'rubygems'
|
||||
require 'mongrel'
|
||||
require 'cgi'
|
||||
begin
|
||||
|
@ -78,12 +78,13 @@ end
|
|||
|
||||
cwd = Dir.pwd
|
||||
|
||||
#Daemonize.daemonize(log_file=File.join(cwd,"log","mongrel.log"))
|
||||
#Dir.chdir(cwd)
|
||||
|
||||
open(File.join(cwd,"log/mongrel-#{ARGV[1]}.pid"),"w") {|f| f.write(Process.pid) }
|
||||
h = Mongrel::HttpServer.new(ARGV[0], ARGV[1])
|
||||
h.register("/", RailsHandler.new(File.join(cwd,"public")))
|
||||
h.run
|
||||
|
||||
h.acceptor.join
|
||||
Daemonize.daemonize(log_file=File.join(cwd,"log","mongrel.log"))
|
||||
Dir.chdir(cwd) do
|
||||
require 'config/environment'
|
||||
open(File.join(cwd,"log/mongrel-#{ARGV[1]}.pid"),"w") {|f| f.write(Process.pid) }
|
||||
h = Mongrel::HttpServer.new(ARGV[0], ARGV[1])
|
||||
h.register("/", RailsHandler.new(File.join(cwd,"public")))
|
||||
h.run
|
||||
|
||||
h.acceptor.join
|
||||
end
|
||||
|
|
|
@ -341,7 +341,9 @@ VALUE URIClassifier_unregister(VALUE self, VALUE uri)
|
|||
* uc.resolve("/someuri") -> "/someuri", "", handler
|
||||
* uc.resolve("/someuri/pathinfo") -> "/someuri", "/pathinfo", handler
|
||||
* uc.resolve("/notfound/orhere") -> nil, nil, nil
|
||||
*
|
||||
* uc.resolve("/") -> "/", "/", handler # if uc.register("/", handler)
|
||||
* uc.resolve("/path/from/root") -> "/", "/path/from/root", handler # if uc.register("/", handler)
|
||||
*
|
||||
* Attempts to resolve either the whole URI or at the longest prefix, returning
|
||||
* the prefix (as script_info), path (as path_info), and registered handler
|
||||
* (usually an HttpHandler). If it doesn't find a handler registered at the longest
|
||||
|
@ -358,7 +360,13 @@ VALUE URIClassifier_unregister(VALUE self, VALUE uri)
|
|||
* It also means that it's very efficient to do this only taking as long as the URI has
|
||||
* characters.
|
||||
*
|
||||
* It expects strings with no embedded '\0' characters. Don't try other string-line stuff yet.
|
||||
* A slight modification to the CGI 1.2 standard is given for handlers registered to "/".
|
||||
* CGI expects all CGI scripts to be at some script path, so it doesn't really say anything
|
||||
* about a script that handles the root. To make this work, the resolver will detect that
|
||||
* the requested handler is at "/", and return that for script_name, and then simply return
|
||||
* the full URI back as path_info.
|
||||
*
|
||||
* It expects strings with no embedded '\0' characters. Don't try other string-like stuff yet.
|
||||
*/
|
||||
VALUE URIClassifier_resolve(VALUE self, VALUE uri)
|
||||
{
|
||||
|
@ -379,7 +387,15 @@ VALUE URIClassifier_resolve(VALUE self, VALUE uri)
|
|||
|
||||
if(handler) {
|
||||
rb_ary_push(result, rb_str_substr (uri, 0, pref_len));
|
||||
rb_ary_push(result, rb_str_substr(uri, pref_len, RSTRING(uri)->len));
|
||||
// compensate for a script_name="/" where we need to add the "/" to path_info to keep it consistent
|
||||
if(pref_len == 1 && uri_str[0] == '/') {
|
||||
// matches the root URI so we have to use the whole URI as the path_info
|
||||
rb_ary_push(result, uri);
|
||||
} else {
|
||||
// matches a script so process like normal
|
||||
rb_ary_push(result, rb_str_substr(uri, pref_len, RSTRING(uri)->len));
|
||||
}
|
||||
|
||||
rb_ary_push(result, (VALUE)handler);
|
||||
} else {
|
||||
// not found so push back nothing
|
||||
|
|
|
@ -32,7 +32,6 @@ void *tst_search(unsigned char *key, struct tst *tst, int *prefix_len)
|
|||
if(prefix_len) *prefix_len = key_index;
|
||||
return current_node->middle;
|
||||
} else {
|
||||
|
||||
current_node = current_node->middle;
|
||||
if(current_node && current_node->value == 0) {
|
||||
if(prefix_len) *prefix_len = key_index+1;
|
||||
|
@ -47,7 +46,7 @@ void *tst_search(unsigned char *key, struct tst *tst, int *prefix_len)
|
|||
((current_node->value != 0) && (key[key_index] <
|
||||
current_node->value)) )
|
||||
{
|
||||
if(current_node->left && current_node->value == 0) {
|
||||
if(current_node->value == 0) {
|
||||
if(prefix_len) *prefix_len = key_index;
|
||||
longest_match = current_node->middle;
|
||||
}
|
||||
|
@ -56,7 +55,7 @@ void *tst_search(unsigned char *key, struct tst *tst, int *prefix_len)
|
|||
}
|
||||
else
|
||||
{
|
||||
if(current_node->right && current_node->value == 0) {
|
||||
if(current_node->value == 0) {
|
||||
if(prefix_len) *prefix_len = key_index;
|
||||
longest_match = current_node->middle;
|
||||
}
|
||||
|
|
|
@ -51,6 +51,8 @@ module Mongrel
|
|||
505 => 'HTTP Version not supported'
|
||||
}
|
||||
|
||||
|
||||
|
||||
# Frequently used constants when constructing requests or responses. Many times
|
||||
# the constant just refers to a string with the same contents. Using these constants
|
||||
# gave about a 3% to 10% performance improvement over using the strings directly.
|
||||
|
@ -350,7 +352,7 @@ module Mongrel
|
|||
params[Const::PATH_INFO] = path_info
|
||||
params[Const::SCRIPT_NAME] = script_name
|
||||
params[Const::GATEWAY_INTERFACE]=Const::GATEWAY_INTERFACE_VALUE
|
||||
params[Const::REMOTE_ADDR]=client.peeraddr
|
||||
params[Const::REMOTE_ADDR]=client.peeraddr[3]
|
||||
params[Const::SERVER_NAME]=@host
|
||||
params[Const::SERVER_PORT]=@port
|
||||
params[Const::SERVER_PROTOCOL]=Const::SERVER_PROTOCOL_VALUE
|
||||
|
@ -444,22 +446,45 @@ module Mongrel
|
|||
attr_reader :path
|
||||
|
||||
# You give it the path to the directory root and an (optional)
|
||||
def initialize(path, listing_allowed=true)
|
||||
def initialize(path, listing_allowed=true, index_html="index.html")
|
||||
@path = File.expand_path(path)
|
||||
@listing_allowed=listing_allowed
|
||||
@index_html = index_html
|
||||
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 or (File.directory?(req) and not @listing_allowed)
|
||||
return nil
|
||||
else
|
||||
return req
|
||||
req = File.expand_path(File.join(@path,path_info), @path)
|
||||
|
||||
if req.index(@path) == 0 and File.exist? req
|
||||
# it exists and it's in the right location
|
||||
if File.directory? req
|
||||
# the request is for a directory
|
||||
index = File.join(req, @index_html)
|
||||
if File.exist? index
|
||||
# serve the index
|
||||
return index
|
||||
elsif @listing_allows
|
||||
# serve the directory
|
||||
req
|
||||
else
|
||||
# do not serve anything
|
||||
return nil
|
||||
end
|
||||
else
|
||||
# it's a file and it's there
|
||||
return req
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
# Returns a simplistic directory listing if they're enabled, otherwise a 403.
|
||||
# Base is the base URI from the REQUEST_URI, dir is the directory to serve
|
||||
# on the file system (comes from can_serve()), and response is the HttpResponse
|
||||
# object to send the results on.
|
||||
def send_dir_listing(base, dir, response)
|
||||
# take off any trailing / so the links come out right
|
||||
base.chop! if base[-1] == "/"[-1]
|
||||
|
||||
if @listing_allowed
|
||||
|
@ -484,7 +509,9 @@ module Mongrel
|
|||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
# Sends the contents of a file back to the user. Not terribly efficient since it's
|
||||
# opening and closing the file for each read.
|
||||
def send_file(req, response)
|
||||
response.start(200) do |head,out|
|
||||
open(req, "r") do |f|
|
||||
|
@ -494,9 +521,10 @@ module Mongrel
|
|||
end
|
||||
|
||||
|
||||
# Process the request to either serve a file or a directory listing
|
||||
# if allowed (based on the listing_allowed paramter to the constructor).
|
||||
def process(request, response)
|
||||
path_info = request.params['PATH_INFO']
|
||||
req = can_serve path_info
|
||||
req = can_serve request.params['PATH_INFO']
|
||||
if not req
|
||||
# not found, return a 404
|
||||
response.start(404) do |head,out|
|
||||
|
|
|
@ -115,7 +115,6 @@ class URIClassifierTest < Test::Unit::TestCase
|
|||
assert_equal 1, h, "wrong result for branching uri"
|
||||
end
|
||||
|
||||
|
||||
def test_all_prefixing
|
||||
tests = ["/test","/test/that","/test/this"]
|
||||
uri = "/test/this/that"
|
||||
|
@ -151,5 +150,27 @@ class URIClassifierTest < Test::Unit::TestCase
|
|||
assert_nil sn, "shoulnd't find anything"
|
||||
assert_nil pi, "shoulnd't find anything"
|
||||
end
|
||||
|
||||
|
||||
# Verifies that a root mounted ("/") handler resolves
|
||||
# such that path info matches the original URI.
|
||||
# This is needed to accomodate real usage of handlers.
|
||||
def test_root_mounted
|
||||
u = URIClassifier.new
|
||||
root = "/"
|
||||
path = "/this/is/a/test"
|
||||
|
||||
u.register(root, 1)
|
||||
|
||||
sn, pi, h = u.resolve(root)
|
||||
assert_equal 1,h, "didn't find handler"
|
||||
assert_equal root,pi, "didn't get right path info"
|
||||
assert_equal root,sn, "didn't get right script name"
|
||||
|
||||
sn, pi, h = u.resolve(path)
|
||||
assert_equal path,pi, "didn't get right path info"
|
||||
assert_equal root,sn, "didn't get right script name"
|
||||
assert_equal 1,h, "didn't find handler"
|
||||
end
|
||||
end
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue