1
0
Fork 0
mirror of https://github.com/puma/puma.git synced 2022-11-09 13:48:40 -05:00

Fixed a bug in the Error404Handler. Created the first Rails runner script.

git-svn-id: svn+ssh://rubyforge.org/var/svn/mongrel/trunk@21 19e92222-5c0b-0410-8929-a290d50e31e9
This commit is contained in:
zedshaw 2006-02-08 12:48:41 +00:00
parent 788e4f4902
commit 98a33bb304
6 changed files with 205 additions and 84 deletions

12
README
View file

@ -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

View file

@ -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)

73
examples/mongrel_rails.rb Normal file
View file

@ -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

View file

@ -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

View file

@ -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;

View file

@ -239,18 +239,30 @@ 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,21 +441,40 @@ 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|
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
else
@ -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