mongrel 0.2.1 → 0.2.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. data/README +10 -2
  2. data/Rakefile +1 -1
  3. data/doc/rdoc/classes/Mongrel.html +11 -1
  4. data/doc/rdoc/classes/Mongrel/Const.html +342 -0
  5. data/doc/rdoc/classes/Mongrel/DirHandler.html +201 -0
  6. data/doc/rdoc/classes/Mongrel/DirHandler.src/M000008.html +20 -0
  7. data/doc/rdoc/classes/Mongrel/DirHandler.src/M000009.html +31 -0
  8. data/doc/rdoc/classes/Mongrel/DirHandler.src/M000010.html +22 -0
  9. data/doc/rdoc/classes/Mongrel/DirHandler.src/M000011.html +39 -0
  10. data/doc/rdoc/classes/Mongrel/Error404Handler.html +10 -10
  11. data/doc/rdoc/classes/Mongrel/Error404Handler.src/{M000023.html → M000028.html} +4 -4
  12. data/doc/rdoc/classes/Mongrel/Error404Handler.src/{M000024.html → M000029.html} +4 -4
  13. data/doc/rdoc/classes/Mongrel/HeaderOut.html +28 -10
  14. data/doc/rdoc/classes/Mongrel/HeaderOut.src/{M000013.html → M000017.html} +4 -4
  15. data/doc/rdoc/classes/Mongrel/HeaderOut.src/M000018.html +21 -0
  16. data/doc/rdoc/classes/Mongrel/HttpHandler.html +5 -18
  17. data/doc/rdoc/classes/Mongrel/HttpHandler.src/{M000019.html → M000023.html} +3 -3
  18. data/doc/rdoc/classes/Mongrel/HttpRequest.html +8 -8
  19. data/doc/rdoc/classes/Mongrel/HttpRequest.src/M000030.html +31 -0
  20. data/doc/rdoc/classes/Mongrel/HttpResponse.html +89 -15
  21. data/doc/rdoc/classes/Mongrel/HttpResponse.src/{M000020.html → M000024.html} +7 -7
  22. data/doc/rdoc/classes/Mongrel/HttpResponse.src/{M000021.html → M000025.html} +6 -6
  23. data/doc/rdoc/classes/Mongrel/HttpResponse.src/M000026.html +19 -0
  24. data/doc/rdoc/classes/Mongrel/HttpResponse.src/{M000022.html → M000027.html} +11 -11
  25. data/doc/rdoc/classes/Mongrel/HttpServer.html +32 -76
  26. data/doc/rdoc/classes/Mongrel/HttpServer.src/M000012.html +18 -5
  27. data/doc/rdoc/classes/Mongrel/HttpServer.src/M000013.html +64 -0
  28. data/doc/rdoc/classes/Mongrel/HttpServer.src/{M000010.html → M000014.html} +9 -8
  29. data/doc/rdoc/classes/Mongrel/HttpServer.src/{M000011.html → M000015.html} +4 -4
  30. data/doc/rdoc/classes/Mongrel/HttpServer.src/M000016.html +18 -0
  31. data/doc/rdoc/classes/Mongrel/URIClassifier.html +25 -23
  32. data/doc/rdoc/classes/Mongrel/URIClassifier.src/{M000015.html → M000019.html} +0 -0
  33. data/doc/rdoc/classes/Mongrel/URIClassifier.src/{M000016.html → M000020.html} +3 -2
  34. data/doc/rdoc/classes/Mongrel/URIClassifier.src/{M000017.html → M000021.html} +0 -0
  35. data/doc/rdoc/classes/Mongrel/URIClassifier.src/{M000018.html → M000022.html} +1 -1
  36. data/doc/rdoc/created.rid +1 -1
  37. data/doc/rdoc/files/README.html +14 -2
  38. data/doc/rdoc/files/ext/http11/http11_c.html +1 -1
  39. data/doc/rdoc/files/lib/mongrel_rb.html +1 -1
  40. data/doc/rdoc/fr_class_index.html +2 -0
  41. data/doc/rdoc/fr_method_index.html +23 -18
  42. data/examples/simpletest.rb +2 -1
  43. data/ext/http11/http11.c +10 -9
  44. data/ext/http11/http11_parser.c +10 -10
  45. data/ext/http11/http11_parser.h +5 -1
  46. data/lib/#mongrel.rb# +493 -0
  47. data/lib/mongrel.rb +242 -48
  48. metadata +28 -19
  49. data/doc/rdoc/classes/Mongrel/HeaderOut.src/M000014.html +0 -21
  50. data/doc/rdoc/classes/Mongrel/HttpRequest.src/M000025.html +0 -30
  51. data/doc/rdoc/classes/Mongrel/HttpServer.src/M000008.html +0 -26
  52. data/doc/rdoc/classes/Mongrel/HttpServer.src/M000009.html +0 -58
@@ -8,6 +8,9 @@ require 'stringio'
8
8
  # functionality to service web application requests fast as possible.
9
9
  module Mongrel
10
10
 
11
+ # Every standard HTTP code mapped to the appropriate message. These are
12
+ # used so frequently that they are placed directly in Mongrel for easy
13
+ # access rather than Mongrel::Const.
11
14
  HTTP_STATUS_CODES = {
12
15
  100 => 'Continue',
13
16
  101 => 'Switching Protocols',
@@ -48,19 +51,89 @@ module Mongrel
48
51
  505 => 'HTTP Version not supported'
49
52
  }
50
53
 
54
+ # Frequently used constants when constructing requests or responses. Many times
55
+ # the constant just refers to a string with the same contents. Using these constants
56
+ # gave about a 3% to 10% performance improvement over using the strings directly.
57
+ # Symbols did not really improve things much compared to constants.
58
+ #
59
+ # While Mongrel does try to emulate the CGI/1.2 protocol, it does not use the REMOTE_IDENT,
60
+ # REMOTE_USER, or REMOTE_HOST parameters since those are either a security problem or
61
+ # too taxing on performance.
62
+ module Const
63
+ # This is the part of the path after the SCRIPT_NAME. URIClassifier will determine this.
64
+ PATH_INFO="PATH_INFO"
65
+ # This is the intial part that your handler is identified as by URIClassifier.
66
+ SCRIPT_NAME="SCRIPT_NAME"
67
+ # The original URI requested by the client. Passed to URIClassifier to build PATH_INFO and SCRIPT_NAME.
68
+ REQUEST_URI='REQUEST_URI'
69
+
70
+ # Content length (also available as HTTP_CONTENT_LENGTH).
71
+ CONTENT_LENGTH='CONTENT_LENGTH'
72
+
73
+ # Content length (also available as CONTENT_LENGTH).
74
+ HTTP_CONTENT_LENGTH='HTTP_CONTENT_LENGTH'
75
+
76
+ # Content type (also available as HTTP_CONTENT_TYPE).
77
+ CONTENT_TYPE='CONTENT_TYPE'
78
+
79
+ # Content type (also available as CONTENT_TYPE).
80
+ HTTP_CONTENT_TYPE='HTTP_CONTENT_TYPE'
81
+
82
+ # Gateway interface key in the HttpRequest parameters.
83
+ GATEWAY_INTERFACE='GATEWAY_INTERFACE'
84
+ # We claim to support CGI/1.2.
85
+ GATEWAY_INTERFACE_VALUE='CGI/1.2'
86
+
87
+ # Hosts remote IP address. Mongrel does not do DNS resolves since that slows
88
+ # processing down considerably.
89
+ REMOTE_ADDR='REMOTE_ADDR'
90
+
91
+ # This is not given since Mongrel does not do DNS resolves. It is only here for
92
+ # completeness for the CGI standard.
93
+ REMOTE_HOST='REMOTE_HOST'
94
+
95
+ # The name/host of our server as given by the HttpServer.new(host,port) call.
96
+ SERVER_NAME='SERVER_NAME'
97
+
98
+ # The port of our server as given by the HttpServer.new(host,port) call.
99
+ SERVER_PORT='SERVER_PORT'
100
+
101
+ # Official server protocol key in the HttpRequest parameters.
102
+ SERVER_PROTOCOL='SERVER_PROTOCOL'
103
+ # Mongrel claims to support HTTP/1.1.
104
+ SERVER_PROTOCOL_VALUE='HTTP/1.1'
105
+
106
+ # The actual server software being used (it's Mongrel man).
107
+ SERVER_SOFTWARE='SERVER_SOFTWARE'
108
+
109
+ # Current Mongrel version (used for SERVER_SOFTWARE and other response headers).
110
+ MONGREL_VERSION='Mongrel 0.2.2'
111
+
112
+ # The standard empty 404 response for bad requests. Use Error4040Handler for custom stuff.
113
+ ERROR_404_RESPONSE="HTTP/1.1 404 Not Found\r\nConnection: close\r\nServer: #{MONGREL_VERSION}\r\n\r\nNOT FOUND"
114
+
115
+ # A common header for indicating the server is too busy. Not used yet.
116
+ ERROR_503_RESPONSE="HTTP/1.1 503 Service Unavailable\r\n\r\nBUSY"
117
+
118
+ # The basic max request size we'll try to read.
119
+ CHUNK_SIZE=(16 * 1024)
120
+
121
+ end
122
+
123
+
51
124
  # When a handler is found for a registered URI then this class is constructed
52
125
  # and passed to your HttpHandler::process method. You should assume that
53
126
  # *one* handler processes all requests. Included in the HttpReqeust is a
54
127
  # HttpRequest.params Hash that matches common CGI params, and a HttpRequest.body
55
128
  # which is a string containing the request body (raw for now).
56
129
  #
57
- # Mongrel really only support small-ish request bodies right now since really
130
+ # Mongrel really only supports small-ish request bodies right now since really
58
131
  # huge ones have to be completely read off the wire and put into a string.
59
132
  # Later there will be several options for efficiently handling large file
60
133
  # uploads.
61
134
  class HttpRequest
62
135
  attr_reader :body, :params
63
-
136
+
64
137
  # You don't really call this. It's made for you.
65
138
  # Main thing it does is hook up the params, and store any remaining
66
139
  # body data into the HttpRequest.body attribute.
@@ -68,13 +141,14 @@ module Mongrel
68
141
  @body = initial_body || ""
69
142
  @params = params
70
143
  @socket = socket
71
-
144
+
72
145
  # fix up the CGI requirements
73
- params['CONTENT_LENGTH'] = params['HTTP_CONTENT_LENGTH'] || 0
146
+ params[Const::CONTENT_LENGTH] = params[Const::HTTP_CONTENT_LENGTH] || 0
147
+ params[Const::CONTENT_TYPE] ||= params[Const::HTTP_CONTENT_TYPE]
74
148
 
75
149
  # now, if the initial_body isn't long enough for the content length we have to fill it
76
150
  # TODO: adapt for big ass stuff by writing to a temp file
77
- clen = params['HTTP_CONTENT_LENGTH'].to_i
151
+ clen = params[Const::HTTP_CONTENT_LENGTH].to_i
78
152
  if @body.length < clen
79
153
  @body << @socket.read(clen - @body.length)
80
154
  end
@@ -82,6 +156,13 @@ module Mongrel
82
156
  end
83
157
 
84
158
 
159
+ # This class implements a simple way of constructing the HTTP headers dynamically
160
+ # via a Hash syntax. Think of it as a write-only Hash. Refer to HttpResponse for
161
+ # information on how this is used.
162
+ #
163
+ # One consequence of this write-only nature is that you can write multiple headers
164
+ # by just doing them twice (which is sometimes needed in HTTP), but that the normal
165
+ # semantics for Hash (where doing an insert replaces) is not there.
85
166
  class HeaderOut
86
167
  attr_reader :out
87
168
 
@@ -89,6 +170,7 @@ module Mongrel
89
170
  @out = out
90
171
  end
91
172
 
173
+ # Simply writes "#{key}: #{value}" to an output buffer.
92
174
  def[]=(key,value)
93
175
  @out.write(key)
94
176
  @out.write(": ")
@@ -97,7 +179,35 @@ module Mongrel
97
179
  end
98
180
  end
99
181
 
100
-
182
+ # Writes and controls your response to the client using the HTTP/1.1 specification.
183
+ # You use it by simply doing:
184
+ #
185
+ # response.start(200) do |head,out|
186
+ # head['Content-Type'] = 'text/plain'
187
+ # out.write("hello\n")
188
+ # end
189
+ #
190
+ # The parameter to start is the response code--which Mongrel will translate for you
191
+ # based on HTTP_STATUS_CODES. The head parameter is how you write custom headers.
192
+ # The out parameter is where you write your body. The default status code for
193
+ # HttpResponse.start is 200 so the above example is redundant.
194
+ #
195
+ # As you can see, it's just like using a Hash and as you do this it writes the proper
196
+ # header to the output on the fly. You can even intermix specifying headers and
197
+ # writing content. The HttpResponse class with write the things in the proper order
198
+ # once the HttpResponse.block is ended.
199
+ #
200
+ # You may also work the HttpResponse object directly using the various attributes available
201
+ # for the raw socket, body, header, and status codes. If you do this you're on your own.
202
+ # A design decision was made to force the client to not pipeline requests. HTTP/1.1
203
+ # pipelining really kills the performance due to how it has to be handled and how
204
+ # unclear the standard is. To fix this the HttpResponse gives a "Connection: close"
205
+ # header which forces the client to close right away. The bonus for this is that it
206
+ # gives a pretty nice speed boost to most clients since they can close their connection
207
+ # immediately.
208
+ #
209
+ # One additional caveat is that you don't have to specify the Content-length header
210
+ # as the HttpResponse will write this for you based on the out length.
101
211
  class HttpResponse
102
212
  attr_reader :socket
103
213
  attr_reader :body
@@ -112,12 +222,25 @@ module Mongrel
112
222
  @header = HeaderOut.new(StringIO.new)
113
223
  end
114
224
 
225
+ # Receives a block passing it the header and body for you to work with.
226
+ # When the block is finished it writes everything you've done to
227
+ # the socket in the proper order. This lets you intermix header and
228
+ # body content as needed.
115
229
  def start(status=200)
116
230
  @status = status
117
231
  yield @header, @body
118
232
  finished
119
233
  end
120
-
234
+
235
+ # Primarily used in exception handling to reset the response output in order to write
236
+ # an alternative response.
237
+ def reset
238
+ @header.out.rewind
239
+ @body.rewind
240
+ end
241
+
242
+ # This takes whatever has been done to header and body and then writes it in the
243
+ # proper format to make an HTTP/1.1 response.
121
244
  def finished
122
245
  @header.out.rewind
123
246
  @body.rewind
@@ -136,29 +259,8 @@ module Mongrel
136
259
  # a response. Look at the HttpRequest and HttpResponse objects for how
137
260
  # to use them.
138
261
  class HttpHandler
139
- attr_accessor :script_name
140
-
141
- def process(request, response)
142
- end
143
- end
144
-
145
-
146
- # The server normally returns a 404 response if a URI is requested, but it
147
- # also returns a lame empty message. This lets you do a 404 response
148
- # with a custom message for special URIs.
149
- class Error404Handler < HttpHandler
150
-
151
- # Sets the message to return. This is constructed once for the handler
152
- # so it's pretty efficient.
153
- def initialize(msg)
154
- @response = HttpServer::ERROR_404_RESPONSE + msg
155
- end
156
-
157
- # Just kicks back the standard 404 response with your special message.
158
262
  def process(request, response)
159
- response.socket.write(@response)
160
263
  end
161
-
162
264
  end
163
265
 
164
266
 
@@ -183,16 +285,6 @@ module Mongrel
183
285
  class HttpServer
184
286
  attr_reader :acceptor
185
287
 
186
- # The standard empty 404 response for bad requests. Use Error4040Handler for custom stuff.
187
- ERROR_404_RESPONSE="HTTP/1.1 404 Not Found\r\nConnection: close\r\nServer: Mongrel/0.2\r\n\r\nNOT FOUND"
188
- ERROR_503_RESPONSE="HTTP/1.1 503 Service Unavailable\r\n\r\nBUSY"
189
-
190
- # The basic max request size we'll try to read.
191
- CHUNK_SIZE=(16 * 1024)
192
-
193
- PATH_INFO="PATH_INFO"
194
- SCRIPT_NAME="SCRIPT_NAME"
195
-
196
288
  # Creates a working server on host:port (strange things happen if port isn't a Number).
197
289
  # Use HttpServer::run to start the server.
198
290
  #
@@ -210,8 +302,13 @@ module Mongrel
210
302
  # Future versions of Mongrel will make this more dynamic (hopefully).
211
303
  def initialize(host, port, num_processors=20)
212
304
  @socket = TCPServer.new(host, port)
305
+
213
306
  @classifier = URIClassifier.new
214
307
  @req_queue = Queue.new
308
+ @host = host
309
+ @port = port
310
+ @num_procesors = num_processors
311
+
215
312
  num_processors.times {|i| Thread.new do
216
313
  while client = @req_queue.deq
217
314
  process_client(client)
@@ -223,30 +320,35 @@ module Mongrel
223
320
 
224
321
  # Does the majority of the IO processing. It has been written in Ruby using
225
322
  # about 7 different IO processing strategies and no matter how it's done
226
- # the performance just does not improve. Ruby's use of select to implement
227
- # threads means that it will most likely never improve, so the only remaining
228
- # approach is to write all or some of this function in C. That will be the
229
- # focus of future releases.
323
+ # the performance just does not improve. It is currently carefully constructed
324
+ # to make sure that it gets the best possible performance, but anyone who
325
+ # thinks they can make it faster is more than welcome to take a crack at it.
230
326
  def process_client(client)
231
327
  begin
232
328
  parser = HttpParser.new
233
329
  params = {}
234
- data = client.readpartial(CHUNK_SIZE)
330
+ data = client.readpartial(Const::CHUNK_SIZE)
235
331
 
236
332
  while true
237
333
  nread = parser.execute(params, data)
238
334
  if parser.finished?
239
- script_name, path_info, handler = @classifier.resolve(params[PATH_INFO])
335
+ script_name, path_info, handler = @classifier.resolve(params[Const::REQUEST_URI])
240
336
 
241
337
  if handler
242
- params[PATH_INFO] = path_info
243
- params[SCRIPT_NAME] = script_name
338
+ params[Const::PATH_INFO] = path_info
339
+ params[Const::SCRIPT_NAME] = script_name
340
+ params[Const::GATEWAY_INTERFACE]=Const::GATEWAY_INTERFACE_VALUE
341
+ params[Const::REMOTE_ADDR]=client.peeraddr
342
+ params[Const::SERVER_NAME]=@host
343
+ params[Const::SERVER_PORT]=@port
344
+ params[Const::SERVER_PROTOCOL]=Const::SERVER_PROTOCOL_VALUE
345
+ params[Const::SERVER_SOFTWARE]=Const::MONGREL_VERSION
244
346
 
245
347
  request = HttpRequest.new(params, data[nread ... data.length], client)
246
348
  response = HttpResponse.new(client)
247
349
  handler.process(request, response)
248
350
  else
249
- client.write(ERROR_404_RESPONSE)
351
+ client.write(Const::ERROR_404_RESPONSE)
250
352
  end
251
353
 
252
354
  break
@@ -254,7 +356,7 @@ module Mongrel
254
356
  # gotta stream and read again until we can get the parser to be character safe
255
357
  # TODO: make this more efficient since this means we're parsing a lot repeatedly
256
358
  parser.reset
257
- data << client.readpartial(CHUNK_SIZE)
359
+ data << client.readpartial(Const::CHUNK_SIZE)
258
360
  end
259
361
  end
260
362
  rescue EOFError
@@ -274,6 +376,7 @@ module Mongrel
274
376
  # Runs the thing. It returns the thread used so you can "join" it. You can also
275
377
  # access the HttpServer::acceptor attribute to get the thread later.
276
378
  def run
379
+ BasicSocket.do_not_reverse_lookup=true
277
380
  @acceptor = Thread.new do
278
381
  while true
279
382
  @req_queue << @socket.accept
@@ -295,4 +398,95 @@ module Mongrel
295
398
  @classifier.unregister(uri)
296
399
  end
297
400
  end
401
+
402
+
403
+ # The server normally returns a 404 response if a URI is requested, but it
404
+ # also returns a lame empty message. This lets you do a 404 response
405
+ # with a custom message for special URIs.
406
+ class Error404Handler < HttpHandler
407
+
408
+ # Sets the message to return. This is constructed once for the handler
409
+ # so it's pretty efficient.
410
+ def initialize(msg)
411
+ @response = HttpServer::ERROR_404_RESPONSE + msg
412
+ end
413
+
414
+ # Just kicks back the standard 404 response with your special message.
415
+ def process(request, response)
416
+ response.socket.write(@response)
417
+ end
418
+
419
+ end
420
+
421
+
422
+ # Serves the contents of a directory. You give it the path to the root
423
+ # where the files are located, and it tries to find the files based on
424
+ # the PATH_INFO inside the directory. If the requested path is a
425
+ # directory then it returns a simple directory listing.
426
+ #
427
+ # It does a simple protection against going outside it's root path by
428
+ # converting all paths to an absolute expanded path, and then making sure
429
+ # that the final expanded path includes the root path. If it doesn't
430
+ # than it simply gives a 404.
431
+ class DirHandler < HttpHandler
432
+
433
+ def initialize(path, listing_allowed=true)
434
+ @path = File.expand_path(path)
435
+ @listing_allowed=listing_allowed
436
+ puts "DIR: #@path"
437
+ end
438
+
439
+ def send_dir_listing(base, dir, response)
440
+ if @listing_allowed
441
+ response.start(200) do |head,out|
442
+ head['Content-Type'] = "text/html"
443
+ out << "<html><head><title>Directory Listing</title></head><body>"
444
+ Dir.entries(dir).each do |child|
445
+ out << "<a href=\"#{base}/#{child}\">#{child}</a><br/>"
446
+ end
447
+ out << "</body></html>"
448
+ end
449
+ else
450
+ response.start(403) do |head,out|
451
+ out.write("Directory listings not allowed")
452
+ end
453
+ end
454
+ end
455
+
456
+
457
+ def send_file(req, response)
458
+ response.start(200) do |head,out|
459
+ open(req, "r") do |f|
460
+ out.write(f.read)
461
+ end
462
+ end
463
+ end
464
+
465
+
466
+ def process(request, response)
467
+ req = File.expand_path("." + request.params['PATH_INFO'], @path)
468
+ puts "FIND: #{req}"
469
+ if req.index(@path) != 0 or !File.exist? req
470
+ # not found, return a 404
471
+ response.start(404) do |head,out|
472
+ out << "File not found"
473
+ end
474
+ else
475
+ begin
476
+ if File.directory? req
477
+ send_dir_listing(request.params["REQUEST_URI"],req, response)
478
+ else
479
+ send_file(req, response)
480
+ end
481
+ rescue => details
482
+ response.reset
483
+ response.start(403) do |head,out|
484
+ out << "Error accessing file"
485
+ end
486
+ STDERR.puts "ERROR: #{details}"
487
+ end
488
+ end
489
+ end
490
+ end
491
+
298
492
  end
metadata CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.8.11
3
3
  specification_version: 1
4
4
  name: mongrel
5
5
  version: !ruby/object:Gem::Version
6
- version: 0.2.1
7
- date: 2006-02-02 00:00:00 -05:00
6
+ version: 0.2.2
7
+ date: 2006-02-03 00:00:00 -05:00
8
8
  summary: An experimental fast simple web server for Ruby.
9
9
  require_paths:
10
10
  - lib
@@ -45,6 +45,9 @@ files:
45
45
  - doc/rdoc/rdoc-style.css
46
46
  - doc/rdoc/classes/Mongrel
47
47
  - doc/rdoc/classes/Mongrel.html
48
+ - doc/rdoc/classes/Mongrel/Const.html
49
+ - doc/rdoc/classes/Mongrel/DirHandler.html
50
+ - doc/rdoc/classes/Mongrel/DirHandler.src
48
51
  - doc/rdoc/classes/Mongrel/Error404Handler.html
49
52
  - doc/rdoc/classes/Mongrel/Error404Handler.src
50
53
  - doc/rdoc/classes/Mongrel/HeaderOut.html
@@ -61,11 +64,15 @@ files:
61
64
  - doc/rdoc/classes/Mongrel/HttpServer.src
62
65
  - doc/rdoc/classes/Mongrel/URIClassifier.html
63
66
  - doc/rdoc/classes/Mongrel/URIClassifier.src
64
- - doc/rdoc/classes/Mongrel/Error404Handler.src/M000023.html
65
- - doc/rdoc/classes/Mongrel/Error404Handler.src/M000024.html
66
- - doc/rdoc/classes/Mongrel/HeaderOut.src/M000013.html
67
- - doc/rdoc/classes/Mongrel/HeaderOut.src/M000014.html
68
- - doc/rdoc/classes/Mongrel/HttpHandler.src/M000019.html
67
+ - doc/rdoc/classes/Mongrel/DirHandler.src/M000008.html
68
+ - doc/rdoc/classes/Mongrel/DirHandler.src/M000009.html
69
+ - doc/rdoc/classes/Mongrel/DirHandler.src/M000010.html
70
+ - doc/rdoc/classes/Mongrel/DirHandler.src/M000011.html
71
+ - doc/rdoc/classes/Mongrel/Error404Handler.src/M000028.html
72
+ - doc/rdoc/classes/Mongrel/Error404Handler.src/M000029.html
73
+ - doc/rdoc/classes/Mongrel/HeaderOut.src/M000017.html
74
+ - doc/rdoc/classes/Mongrel/HeaderOut.src/M000018.html
75
+ - doc/rdoc/classes/Mongrel/HttpHandler.src/M000023.html
69
76
  - doc/rdoc/classes/Mongrel/HttpParser.src/M000001.html
70
77
  - doc/rdoc/classes/Mongrel/HttpParser.src/M000002.html
71
78
  - doc/rdoc/classes/Mongrel/HttpParser.src/M000003.html
@@ -73,19 +80,20 @@ files:
73
80
  - doc/rdoc/classes/Mongrel/HttpParser.src/M000005.html
74
81
  - doc/rdoc/classes/Mongrel/HttpParser.src/M000006.html
75
82
  - doc/rdoc/classes/Mongrel/HttpParser.src/M000007.html
76
- - doc/rdoc/classes/Mongrel/HttpRequest.src/M000025.html
77
- - doc/rdoc/classes/Mongrel/HttpResponse.src/M000020.html
78
- - doc/rdoc/classes/Mongrel/HttpResponse.src/M000021.html
79
- - doc/rdoc/classes/Mongrel/HttpResponse.src/M000022.html
80
- - doc/rdoc/classes/Mongrel/HttpServer.src/M000008.html
81
- - doc/rdoc/classes/Mongrel/HttpServer.src/M000009.html
82
- - doc/rdoc/classes/Mongrel/HttpServer.src/M000010.html
83
- - doc/rdoc/classes/Mongrel/HttpServer.src/M000011.html
83
+ - doc/rdoc/classes/Mongrel/HttpRequest.src/M000030.html
84
+ - doc/rdoc/classes/Mongrel/HttpResponse.src/M000024.html
85
+ - doc/rdoc/classes/Mongrel/HttpResponse.src/M000025.html
86
+ - doc/rdoc/classes/Mongrel/HttpResponse.src/M000026.html
87
+ - doc/rdoc/classes/Mongrel/HttpResponse.src/M000027.html
84
88
  - doc/rdoc/classes/Mongrel/HttpServer.src/M000012.html
85
- - doc/rdoc/classes/Mongrel/URIClassifier.src/M000015.html
86
- - doc/rdoc/classes/Mongrel/URIClassifier.src/M000016.html
87
- - doc/rdoc/classes/Mongrel/URIClassifier.src/M000017.html
88
- - doc/rdoc/classes/Mongrel/URIClassifier.src/M000018.html
89
+ - doc/rdoc/classes/Mongrel/HttpServer.src/M000013.html
90
+ - doc/rdoc/classes/Mongrel/HttpServer.src/M000014.html
91
+ - doc/rdoc/classes/Mongrel/HttpServer.src/M000015.html
92
+ - doc/rdoc/classes/Mongrel/HttpServer.src/M000016.html
93
+ - doc/rdoc/classes/Mongrel/URIClassifier.src/M000019.html
94
+ - doc/rdoc/classes/Mongrel/URIClassifier.src/M000020.html
95
+ - doc/rdoc/classes/Mongrel/URIClassifier.src/M000021.html
96
+ - doc/rdoc/classes/Mongrel/URIClassifier.src/M000022.html
89
97
  - doc/rdoc/files/COPYING.html
90
98
  - doc/rdoc/files/ext
91
99
  - doc/rdoc/files/lib
@@ -98,6 +106,7 @@ files:
98
106
  - test/test_response.rb
99
107
  - test/test_uriclassifier.rb
100
108
  - test/test_ws.rb
109
+ - lib/#mongrel.rb#
101
110
  - lib/mongrel.rb
102
111
  - ext/http11/ext_help.h
103
112
  - ext/http11/http11_parser.h