diff --git a/Rakefile b/Rakefile index 4dd78abb..799fabe0 100644 --- a/Rakefile +++ b/Rakefile @@ -87,6 +87,7 @@ task :install do sub_project("mongrel_status", :install) sub_project("mongrel_upload_progress", :install) sub_project("mongrel_console", :install) + sub_project("mongrel_cluster", :install) if RUBY_PLATFORM =~ /mswin/ sub_project("mongrel_service", :install) end diff --git a/ext/http11/http11_parser.c b/ext/http11/http11_parser.c index 02a47558..9b399f83 100644 --- a/ext/http11/http11_parser.c +++ b/ext/http11/http11_parser.c @@ -180,11 +180,25 @@ tr31: parser->request_uri(parser->data, PTR_TO(mark), LEN(mark, p)); } goto st5; +tr40: +#line 43 "ext/http11/http11_parser.rl" + {MARK(query_start, p); } +#line 44 "ext/http11/http11_parser.rl" + { + if(parser->query_string != NULL) + parser->query_string(parser->data, PTR_TO(query_start), LEN(query_start, p)); + } +#line 38 "ext/http11/http11_parser.rl" + { + if(parser->request_uri != NULL) + parser->request_uri(parser->data, PTR_TO(mark), LEN(mark, p)); + } + goto st5; st5: if ( ++p == pe ) goto _out5; case 5: -#line 188 "ext/http11/http11_parser.c" +#line 202 "ext/http11/http11_parser.c" if ( (*p) == 72 ) goto tr3; goto st1; @@ -196,7 +210,7 @@ st6: if ( ++p == pe ) goto _out6; case 6: -#line 200 "ext/http11/http11_parser.c" +#line 214 "ext/http11/http11_parser.c" if ( (*p) == 84 ) goto st7; goto st1; @@ -272,7 +286,7 @@ st14: if ( ++p == pe ) goto _out14; case 14: -#line 276 "ext/http11/http11_parser.c" +#line 290 "ext/http11/http11_parser.c" if ( (*p) == 10 ) goto st15; goto st1; @@ -324,7 +338,7 @@ st53: if ( ++p == pe ) goto _out53; case 53: -#line 328 "ext/http11/http11_parser.c" +#line 342 "ext/http11/http11_parser.c" goto st1; tr21: #line 23 "ext/http11/http11_parser.rl" @@ -334,7 +348,7 @@ st17: if ( ++p == pe ) goto _out17; case 17: -#line 338 "ext/http11/http11_parser.c" +#line 352 "ext/http11/http11_parser.c" switch( (*p) ) { case 33: goto st17; case 58: goto tr16; @@ -373,7 +387,7 @@ st18: if ( ++p == pe ) goto _out18; case 18: -#line 377 "ext/http11/http11_parser.c" +#line 391 "ext/http11/http11_parser.c" switch( (*p) ) { case 13: goto tr36; case 32: goto tr38; @@ -387,7 +401,7 @@ st19: if ( ++p == pe ) goto _out19; case 19: -#line 391 "ext/http11/http11_parser.c" +#line 405 "ext/http11/http11_parser.c" if ( (*p) == 13 ) goto tr36; goto st19; @@ -399,7 +413,7 @@ st20: if ( ++p == pe ) goto _out20; case 20: -#line 403 "ext/http11/http11_parser.c" +#line 417 "ext/http11/http11_parser.c" switch( (*p) ) { case 43: goto st20; case 58: goto st21; @@ -424,7 +438,7 @@ st21: if ( ++p == pe ) goto _out21; case 21: -#line 428 "ext/http11/http11_parser.c" +#line 442 "ext/http11/http11_parser.c" switch( (*p) ) { case 32: goto tr19; case 37: goto st22; @@ -472,7 +486,7 @@ st24: if ( ++p == pe ) goto _out24; case 24: -#line 476 "ext/http11/http11_parser.c" +#line 490 "ext/http11/http11_parser.c" switch( (*p) ) { case 32: goto tr31; case 37: goto st25; @@ -525,7 +539,7 @@ st27: if ( ++p == pe ) goto _out27; case 27: -#line 529 "ext/http11/http11_parser.c" +#line 543 "ext/http11/http11_parser.c" switch( (*p) ) { case 32: goto tr19; case 37: goto st28; @@ -577,10 +591,10 @@ st30: if ( ++p == pe ) goto _out30; case 30: -#line 581 "ext/http11/http11_parser.c" +#line 595 "ext/http11/http11_parser.c" switch( (*p) ) { - case 32: goto tr28; - case 37: goto tr40; + case 32: goto tr40; + case 37: goto tr41; case 60: goto st1; case 62: goto st1; case 127: goto st1; @@ -599,7 +613,7 @@ st31: if ( ++p == pe ) goto _out31; case 31: -#line 603 "ext/http11/http11_parser.c" +#line 617 "ext/http11/http11_parser.c" switch( (*p) ) { case 32: goto tr28; case 37: goto st32; @@ -613,7 +627,7 @@ case 31: } else if ( (*p) >= 0 ) goto st1; goto st31; -tr40: +tr41: #line 43 "ext/http11/http11_parser.rl" {MARK(query_start, p); } goto st32; @@ -621,7 +635,7 @@ st32: if ( ++p == pe ) goto _out32; case 32: -#line 625 "ext/http11/http11_parser.c" +#line 639 "ext/http11/http11_parser.c" if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto st33; @@ -1047,7 +1061,7 @@ case 52: if(parser->body_start) { /* final \r\n combo encountered so stop right here */ -#line 1051 "ext/http11/http11_parser.c" +#line 1065 "ext/http11/http11_parser.c" #line 163 "ext/http11/http11_parser.rl" parser->nread++; } @@ -1060,7 +1074,7 @@ int http_parser_finish(http_parser *parser) int cs = parser->cs; -#line 1064 "ext/http11/http11_parser.c" +#line 1078 "ext/http11/http11_parser.c" #line 174 "ext/http11/http11_parser.rl" parser->cs = cs; diff --git a/ext/http11/http11_parser.rl b/ext/http11/http11_parser.rl index ce9d9057..90bb63f9 100644 --- a/ext/http11/http11_parser.rl +++ b/ext/http11/http11_parser.rl @@ -89,10 +89,10 @@ absolute_uri = (scheme ":" (uchar | reserved )*); path = (pchar+ ( "/" pchar* )*) ; - query = ( uchar | reserved )* >start_query %query_string ; + query = ( uchar | reserved )* %query_string ; param = ( pchar | "/" )* ; params = (param ( ";" param )*) ; - rel_path = (path? %request_path (";" params)?) ("?" query)?; + rel_path = (path? %request_path (";" params)?) ("?" %start_query query)?; absolute_path = ("/"+ rel_path); Request_URI = ("*" | absolute_uri | absolute_path) >mark %request_uri; diff --git a/lib/mongrel.rb b/lib/mongrel.rb index 595df66d..6fb72221 100644 --- a/lib/mongrel.rb +++ b/lib/mongrel.rb @@ -4,6 +4,8 @@ # Additional work donated by contributors. See http://mongrel.rubyforge.org/attributions.html # for more information. +$mongrel_debug_client = false + require 'socket' require 'http11' require 'tempfile' @@ -585,11 +587,14 @@ module Mongrel # ignored rescue HttpParserError STDERR.puts "#{Time.now}: BAD CLIENT (#{params[Const::HTTP_X_FORWARDED_FOR] || client.peeraddr.last}): #$!" + if $mongrel_debug_client + STDERR.puts "#{Time.now}: REQUEST DATA: #{data.inspect}\n---\nPARAMS: #{params.inspect}\n---\n" + end rescue Errno::EMFILE reap_dead_workers('too many files') rescue Object STDERR.puts "#{Time.now}: ERROR: #$!" - STDERR.puts $!.backtrace.join("\n") + STDERR.puts $!.backtrace.join("\n") if $mongrel_debug_client ensure client.close rescue Object request.body.delete if request and request.body.class == Tempfile diff --git a/lib/mongrel/configurator.rb b/lib/mongrel/configurator.rb index 78895b9b..adb2e1f4 100644 --- a/lib/mongrel/configurator.rb +++ b/lib/mongrel/configurator.rb @@ -356,7 +356,7 @@ module Mongrel if RUBY_PLATFORM !~ /mswin/ # graceful shutdown trap("TERM") { log "TERM signal received."; stop } - + trap("USR1") { log "USR1 received, toggling $mongrel_debug_client to #{!$mongrel_debug_client}"; $mongrel_debug_client = !$mongrel_debug_client } # restart trap("USR2") { log "USR2 signal received."; stop(true) } diff --git a/test/test_http11.rb b/test/test_http11.rb index a633ce8f..00fecf27 100644 --- a/test/test_http11.rb +++ b/test/test_http11.rb @@ -60,9 +60,9 @@ class HttpParserTest < Test::Unit::TestCase res = count.to_s + "/" if readable - res << Digest::SHA1.hexdigest(rand(count * 1000).to_s) * (count / 40) + res << Digest::SHA1.hexdigest(rand(count * 100).to_s) * (count / 40) else - res << Digest::SHA1.digest(rand(count * 1000).to_s) * (count / 20) + res << Digest::SHA1.digest(rand(count * 100).to_s) * (count / 20) end return res @@ -72,17 +72,8 @@ class HttpParserTest < Test::Unit::TestCase def test_horrible_queries parser = HttpParser.new - # first verify that large random get requests fail - 100.times do |c| - get = "GET /#{rand_data(1024, 1024+(c*1024))} HTTP/1.1\r\n" - assert_raises Mongrel::HttpParserError do - parser.execute({}, get, 0) - parser.reset - end - end - # then that large header names are caught - 100.times do |c| + 10.times do |c| get = "GET /#{rand_data(10,120)} HTTP/1.1\r\nX-#{rand_data(1024, 1024+(c*1024))}: Test\r\n\r\n" assert_raises Mongrel::HttpParserError do parser.execute({}, get, 0) @@ -91,7 +82,7 @@ class HttpParserTest < Test::Unit::TestCase end # then that large mangled field values are caught - 100.times do |c| + 10.times do |c| get = "GET /#{rand_data(10,120)} HTTP/1.1\r\nX-Test: #{rand_data(1024, 1024+(c*1024), false)}\r\n\r\n" assert_raises Mongrel::HttpParserError do parser.execute({}, get, 0)