mongrel 0.2.1 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README +10 -2
- data/Rakefile +1 -1
- data/doc/rdoc/classes/Mongrel.html +11 -1
- data/doc/rdoc/classes/Mongrel/Const.html +342 -0
- data/doc/rdoc/classes/Mongrel/DirHandler.html +201 -0
- data/doc/rdoc/classes/Mongrel/DirHandler.src/M000008.html +20 -0
- data/doc/rdoc/classes/Mongrel/DirHandler.src/M000009.html +31 -0
- data/doc/rdoc/classes/Mongrel/DirHandler.src/M000010.html +22 -0
- data/doc/rdoc/classes/Mongrel/DirHandler.src/M000011.html +39 -0
- data/doc/rdoc/classes/Mongrel/Error404Handler.html +10 -10
- data/doc/rdoc/classes/Mongrel/Error404Handler.src/{M000023.html → M000028.html} +4 -4
- data/doc/rdoc/classes/Mongrel/Error404Handler.src/{M000024.html → M000029.html} +4 -4
- data/doc/rdoc/classes/Mongrel/HeaderOut.html +28 -10
- data/doc/rdoc/classes/Mongrel/HeaderOut.src/{M000013.html → M000017.html} +4 -4
- data/doc/rdoc/classes/Mongrel/HeaderOut.src/M000018.html +21 -0
- data/doc/rdoc/classes/Mongrel/HttpHandler.html +5 -18
- data/doc/rdoc/classes/Mongrel/HttpHandler.src/{M000019.html → M000023.html} +3 -3
- data/doc/rdoc/classes/Mongrel/HttpRequest.html +8 -8
- data/doc/rdoc/classes/Mongrel/HttpRequest.src/M000030.html +31 -0
- data/doc/rdoc/classes/Mongrel/HttpResponse.html +89 -15
- data/doc/rdoc/classes/Mongrel/HttpResponse.src/{M000020.html → M000024.html} +7 -7
- data/doc/rdoc/classes/Mongrel/HttpResponse.src/{M000021.html → M000025.html} +6 -6
- data/doc/rdoc/classes/Mongrel/HttpResponse.src/M000026.html +19 -0
- data/doc/rdoc/classes/Mongrel/HttpResponse.src/{M000022.html → M000027.html} +11 -11
- data/doc/rdoc/classes/Mongrel/HttpServer.html +32 -76
- data/doc/rdoc/classes/Mongrel/HttpServer.src/M000012.html +18 -5
- data/doc/rdoc/classes/Mongrel/HttpServer.src/M000013.html +64 -0
- data/doc/rdoc/classes/Mongrel/HttpServer.src/{M000010.html → M000014.html} +9 -8
- data/doc/rdoc/classes/Mongrel/HttpServer.src/{M000011.html → M000015.html} +4 -4
- data/doc/rdoc/classes/Mongrel/HttpServer.src/M000016.html +18 -0
- data/doc/rdoc/classes/Mongrel/URIClassifier.html +25 -23
- data/doc/rdoc/classes/Mongrel/URIClassifier.src/{M000015.html → M000019.html} +0 -0
- data/doc/rdoc/classes/Mongrel/URIClassifier.src/{M000016.html → M000020.html} +3 -2
- data/doc/rdoc/classes/Mongrel/URIClassifier.src/{M000017.html → M000021.html} +0 -0
- data/doc/rdoc/classes/Mongrel/URIClassifier.src/{M000018.html → M000022.html} +1 -1
- data/doc/rdoc/created.rid +1 -1
- data/doc/rdoc/files/README.html +14 -2
- data/doc/rdoc/files/ext/http11/http11_c.html +1 -1
- data/doc/rdoc/files/lib/mongrel_rb.html +1 -1
- data/doc/rdoc/fr_class_index.html +2 -0
- data/doc/rdoc/fr_method_index.html +23 -18
- data/examples/simpletest.rb +2 -1
- data/ext/http11/http11.c +10 -9
- data/ext/http11/http11_parser.c +10 -10
- data/ext/http11/http11_parser.h +5 -1
- data/lib/#mongrel.rb# +493 -0
- data/lib/mongrel.rb +242 -48
- metadata +28 -19
- data/doc/rdoc/classes/Mongrel/HeaderOut.src/M000014.html +0 -21
- data/doc/rdoc/classes/Mongrel/HttpRequest.src/M000025.html +0 -30
- data/doc/rdoc/classes/Mongrel/HttpServer.src/M000008.html +0 -26
- data/doc/rdoc/classes/Mongrel/HttpServer.src/M000009.html +0 -58
data/lib/mongrel.rb
CHANGED
@@ -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
|
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[
|
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[
|
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.
|
227
|
-
#
|
228
|
-
#
|
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[
|
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.
|
7
|
-
date: 2006-02-
|
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/
|
65
|
-
- doc/rdoc/classes/Mongrel/
|
66
|
-
- doc/rdoc/classes/Mongrel/
|
67
|
-
- doc/rdoc/classes/Mongrel/
|
68
|
-
- doc/rdoc/classes/Mongrel/
|
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/
|
77
|
-
- doc/rdoc/classes/Mongrel/HttpResponse.src/
|
78
|
-
- doc/rdoc/classes/Mongrel/HttpResponse.src/
|
79
|
-
- doc/rdoc/classes/Mongrel/HttpResponse.src/
|
80
|
-
- doc/rdoc/classes/Mongrel/
|
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/
|
86
|
-
- doc/rdoc/classes/Mongrel/
|
87
|
-
- doc/rdoc/classes/Mongrel/
|
88
|
-
- doc/rdoc/classes/Mongrel/
|
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
|