m2r 0.0.3 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. data/Gemfile +6 -0
  2. data/README.md +141 -35
  3. data/Rakefile +13 -45
  4. data/example/Procfile +4 -0
  5. data/example/config.sqlite +0 -0
  6. data/example/http_0mq.rb +37 -19
  7. data/example/lobster.ru +14 -6
  8. data/example/mongrel2.conf +47 -0
  9. data/example/tmp/access.log +505 -0
  10. data/example/uploading.ru +37 -0
  11. data/lib/m2r.rb +49 -3
  12. data/lib/m2r/connection.rb +66 -0
  13. data/lib/m2r/connection_factory.rb +41 -0
  14. data/lib/m2r/handler.rb +130 -0
  15. data/lib/m2r/headers.rb +72 -0
  16. data/lib/m2r/rack_handler.rb +47 -0
  17. data/lib/m2r/request.rb +129 -0
  18. data/lib/m2r/request/base.rb +33 -0
  19. data/lib/m2r/request/upload.rb +60 -0
  20. data/lib/m2r/response.rb +102 -0
  21. data/lib/m2r/response/content_length.rb +18 -0
  22. data/lib/m2r/version.rb +5 -0
  23. data/lib/rack/handler/mongrel2.rb +33 -0
  24. data/m2r.gemspec +30 -63
  25. data/test/acceptance/examples_test.rb +32 -0
  26. data/test/support/capybara.rb +4 -0
  27. data/test/support/mongrel_helper.rb +40 -0
  28. data/test/support/test_handler.rb +51 -0
  29. data/test/support/test_user.rb +37 -0
  30. data/test/test_helper.rb +5 -0
  31. data/test/unit/connection_factory_test.rb +29 -0
  32. data/test/unit/connection_test.rb +49 -0
  33. data/test/unit/handler_test.rb +41 -0
  34. data/test/unit/headers_test.rb +50 -0
  35. data/test/unit/m2r_test.rb +40 -0
  36. data/test/unit/rack_handler_test.rb +52 -0
  37. data/test/unit/request_test.rb +38 -0
  38. data/test/unit/response_test.rb +30 -0
  39. metadata +310 -105
  40. data/.document +0 -5
  41. data/.gitignore +0 -21
  42. data/ISSUES +0 -62
  43. data/VERSION +0 -1
  44. data/benchmarks/jruby +0 -60
  45. data/example/rack_handler.rb +0 -69
  46. data/lib/connection.rb +0 -158
  47. data/lib/fiber_handler.rb +0 -43
  48. data/lib/handler.rb +0 -66
  49. data/lib/request.rb +0 -44
  50. data/test/helper.rb +0 -10
  51. data/test/test_m2r.rb +0 -7
data/.document DELETED
@@ -1,5 +0,0 @@
1
- README.rdoc
2
- lib/**/*.rb
3
- bin/*
4
- features/**/*.feature
5
- LICENSE
data/.gitignore DELETED
@@ -1,21 +0,0 @@
1
- ## MAC OS
2
- .DS_Store
3
-
4
- ## TEXTMATE
5
- *.tmproj
6
- tmtags
7
-
8
- ## EMACS
9
- *~
10
- \#*
11
- .\#*
12
-
13
- ## VIM
14
- *.swp
15
-
16
- ## PROJECT::GENERAL
17
- coverage
18
- rdoc
19
- pkg
20
-
21
- ## PROJECT::SPECIFIC
data/ISSUES DELETED
@@ -1,62 +0,0 @@
1
- On Ruby 1.9.2, ffi-rzmq crashes on even moderately high loads with the following stack. At this point, the only fix is to switch over to JRuby. I suspect that this crash has a lot to do with MRI's global interpreter lock (GIL). There's also a note about weird behavior on the ffi-rzmq github page, which counsels people to use JRuby, which doesn't have a GIL.
2
-
3
- .rvm/gems/ruby-1.9.2-p0/gems/ffi-rzmq-0.5.0/lib/ffi-rzmq/message.rb:80: [BUG] cfp consistency error - call0
4
- ruby 1.9.2p0 (2010-08-18 revision 29036) [x86_64-darwin10.4.0]
5
-
6
- -- control frame ----------
7
- c:0014 p:---- s:0048 b:0048 l:000047 d:000047 CFUNC :(null)
8
- c:0013 p:---- s:0046 b:0046 l:000045 d:000045 CFUNC :new
9
- c:0012 p:0044 s:0040 b:0040 l:000039 d:000039 METHOD .rvm/gems/ruby-1.9.2-p0/gems/ffi-rzmq-0.5.0/lib/ffi-rzmq/message.rb:80
10
- c:0011 p:---- s:0035 b:0035 l:000034 d:000034 FINISH
11
- c:0010 p:---- s:0033 b:0033 l:000032 d:000032 CFUNC :new
12
- c:0009 p:0017 s:0030 b:0030 l:000029 d:000029 METHOD .rvm/gems/ruby-1.9.2-p0/gems/ffi-rzmq-0.5.0/lib/ffi-rzmq/socket.rb:293
13
- c:0008 p:0022 s:0024 b:0023 l:000022 d:000022 METHOD /m2r/lib/connection.rb:42
14
- c:0007 p:0021 s:0020 b:0020 l:000010 d:000019 BLOCK /m2r/lib/handler.rb:43
15
- c:0006 p:---- s:0016 b:0016 l:000015 d:000015 FINISH
16
- c:0005 p:---- s:0014 b:0014 l:000013 d:000013 CFUNC :loop
17
- c:0004 p:0011 s:0011 b:0011 l:000010 d:000010 METHOD /m2r/lib/handler.rb:39
18
- c:0003 p:0112 s:0008 b:0008 l:001598 d:000a68 EVAL example/http_0mq.rb:33
19
- c:0002 p:---- s:0004 b:0004 l:000003 d:000003 FINISH
20
- c:0001 p:0000 s:0002 b:0002 l:001598 d:001598 TOP
21
- ---------------------------
22
- -- Ruby level backtrace information ----------------------------------------
23
- example/http_0mq.rb:33:in `<main>'
24
- /m2r/lib/handler.rb:39:in `listen'
25
- /m2r/lib/handler.rb:39:in `loop'
26
- /m2r/lib/handler.rb:43:in `block in listen'
27
- /m2r/lib/connection.rb:42:in `recv'
28
- .rvm/gems/ruby-1.9.2-p0/gems/ffi-rzmq-0.5.0/lib/ffi-rzmq/socket.rb:293:in `recv_string'
29
- .rvm/gems/ruby-1.9.2-p0/gems/ffi-rzmq-0.5.0/lib/ffi-rzmq/socket.rb:293:in `new'
30
- .rvm/gems/ruby-1.9.2-p0/gems/ffi-rzmq-0.5.0/lib/ffi-rzmq/message.rb:80:in `initialize'
31
- .rvm/gems/ruby-1.9.2-p0/gems/ffi-rzmq-0.5.0/lib/ffi-rzmq/message.rb:80:in `new'
32
- .rvm/gems/ruby-1.9.2-p0/gems/ffi-rzmq-0.5.0/lib/ffi-rzmq/message.rb:80: [BUG] Segmentation fault
33
- ruby 1.9.2p0 (2010-08-18 revision 29036) [x86_64-darwin10.4.0]
34
-
35
- -- control frame ----------
36
- c:0014 p:---- s:0048 b:0048 l:000047 d:000047 CFUNC :(null)
37
- c:0013 p:---- s:0046 b:0046 l:000045 d:000045 CFUNC :new
38
- c:0012 p:0044 s:0040 b:0040 l:000039 d:000039 METHOD .rvm/gems/ruby-1.9.2-p0/gems/ffi-rzmq-0.5.0/lib/ffi-rzmq/message.rb:80
39
- c:0011 p:---- s:0035 b:0035 l:000034 d:000034 FINISH
40
- c:0010 p:---- s:0033 b:0033 l:000032 d:000032 CFUNC :new
41
- c:0009 p:0017 s:0030 b:0030 l:000029 d:000029 METHOD .rvm/gems/ruby-1.9.2-p0/gems/ffi-rzmq-0.5.0/lib/ffi-rzmq/socket.rb:293
42
- c:0008 p:0022 s:0024 b:0023 l:000022 d:000022 METHOD /m2r/lib/connection.rb:42
43
- c:0007 p:0021 s:0020 b:0020 l:000010 d:000019 BLOCK /m2r/lib/handler.rb:43
44
- c:0006 p:---- s:0016 b:0016 l:000015 d:000015 FINISH
45
- c:0005 p:---- s:0014 b:0014 l:000013 d:000013 CFUNC :loop
46
- c:0004 p:0011 s:0011 b:0011 l:000010 d:000010 METHOD /m2r/lib/handler.rb:39
47
- c:0003 p:0112 s:0008 b:0008 l:001598 d:000a68 EVAL example/http_0mq.rb:33
48
- c:0002 p:---- s:0004 b:0004 l:000003 d:000003 FINISH
49
- c:0001 p:0000 s:0002 b:0002 l:001598 d:001598 TOP
50
- ---------------------------
51
- -- Ruby level backtrace information ----------------------------------------
52
- example/http_0mq.rb:33:in `<main>'
53
- /m2r/lib/handler.rb:39:in `listen'
54
- /m2r/lib/handler.rb:39:in `loop'
55
- /m2r/lib/handler.rb:43:in `block in listen'
56
- /m2r/lib/connection.rb:42:in `recv'
57
- .rvm/gems/ruby-1.9.2-p0/gems/ffi-rzmq-0.5.0/lib/ffi-rzmq/socket.rb:293:in `recv_string'
58
- .rvm/gems/ruby-1.9.2-p0/gems/ffi-rzmq-0.5.0/lib/ffi-rzmq/socket.rb:293:in `new'
59
- .rvm/gems/ruby-1.9.2-p0/gems/ffi-rzmq-0.5.0/lib/ffi-rzmq/message.rb:80:in `initialize'
60
- .rvm/gems/ruby-1.9.2-p0/gems/ffi-rzmq-0.5.0/lib/ffi-rzmq/message.rb:80:in `new'
61
-
62
-
data/VERSION DELETED
@@ -1 +0,0 @@
1
- 0.0.3
@@ -1,60 +0,0 @@
1
- Machine: 2.66GHZ Core 2 Duo
2
- RAM: 4GB
3
-
4
- w/ 1 worker running on JRuby 1.5.1 64-bit hotspot
5
- --------------------------------------------------------------------------------------------------
6
- httperf --server=localhost --num-conns 10 --num-calls 10000 --port 6767 --uri "/handlertest"
7
- httperf --client=0/1 --server=localhost --port=6767 --uri=/handlertest --send-buffer=4096 --recv-buffer=16384 --num-conns=10 --num-calls=10000
8
- httperf: warning: open file limit > FD_SETSIZE; limiting max. # of open files to FD_SETSIZE
9
- Maximum connect burst length: 1
10
-
11
- Total: connections 10 requests 100000 replies 100000 test-duration 278.142 s
12
-
13
- Connection rate: 0.0 conn/s (27814.2 ms/conn, <=1 concurrent connections)
14
- Connection time [ms]: min 23196.2 avg 27814.2 max 36479.8 median 25946.5 stddev 3871.1
15
- Connection time [ms]: connect 1.1
16
- Connection length [replies/conn]: 10000.000
17
-
18
- Request rate: 359.5 req/s (2.8 ms/req)
19
- Request size [B]: 73.0
20
-
21
- Reply rate [replies/s]: min 165.0 avg 359.1 max 473.6 stddev 61.9 (55 samples)
22
- Reply time [ms]: response 2.8 transfer 0.0
23
- Reply size [B]: header 40.0 content 290.0 footer 0.0 (total 330.0)
24
- Reply status: 1xx=0 2xx=100000 3xx=0 4xx=0 5xx=0
25
-
26
- CPU time [s]: user 25.18 system 109.49 (user 9.1% system 39.4% total 48.4%)
27
- Net I/O: 141.5 KB/s (1.2*10^6 bps)
28
-
29
- Errors: total 0 client-timo 0 socket-timo 0 connrefused 0 connreset 0
30
- Errors: fd-unavail 0 addrunavail 0 ftab-full 0 other 0
31
-
32
-
33
- w/ 3 workers running on Jruby 1.5.1 64-bit hotspot
34
- ----------------------------------------------------------------------------------------------------
35
- httperf --server=localhost --num-conns 10 --num-calls 10000 --port 6767 --uri "/handlertest"
36
- httperf --client=0/1 --server=localhost --port=6767 --uri=/handlertest --send-buffer=4096 --recv-buffer=16384 --num-conns=10 --num-calls=10000
37
- httperf: warning: open file limit > FD_SETSIZE; limiting max. # of open files to FD_SETSIZE
38
- Maximum connect burst length: 1
39
-
40
- Total: connections 10 requests 100000 replies 100000 test-duration 311.645 s
41
-
42
- Connection rate: 0.0 conn/s (31164.5 ms/conn, <=1 concurrent connections)
43
- Connection time [ms]: min 26030.3 avg 31164.5 max 40239.7 median 28590.5 stddev 4521.9
44
- Connection time [ms]: connect 0.5
45
- Connection length [replies/conn]: 10000.000
46
-
47
- Request rate: 320.9 req/s (3.1 ms/req)
48
- Request size [B]: 73.0
49
-
50
- Reply rate [replies/s]: min 152.2 avg 320.6 max 409.4 stddev 56.1 (62 samples)
51
- Reply time [ms]: response 3.1 transfer 0.0
52
- Reply size [B]: header 40.0 content 290.0 footer 0.0 (total 330.0)
53
- Reply status: 1xx=0 2xx=100000 3xx=0 4xx=0 5xx=0
54
-
55
- CPU time [s]: user 30.40 system 134.12 (user 9.8% system 43.0% total 52.8%)
56
- Net I/O: 126.3 KB/s (1.0*10^6 bps)
57
-
58
- Errors: total 0 client-timo 0 socket-timo 0 connrefused 0 connreset 0
59
- Errors: fd-unavail 0 addrunavail 0 ftab-full 0 other 0
60
-
@@ -1,69 +0,0 @@
1
- require 'rubygems'
2
- require 'rack'
3
- require 'stringio'
4
- # require 'ruby-debug'
5
- # Debugger.start
6
- # gem install ruby-debug19 -- --with-ruby-include=$HOME/.rvm/src/ruby-1.9.2-head
7
-
8
- $: << ::File.expand_path(::File.dirname(__FILE__) + '/../lib')
9
- require 'connection'
10
-
11
- $sender_id = "70D107AB-19F5-44AE-A2D0-2326A167D8D7"
12
-
13
- module Rack
14
- module Handler
15
- class Mongrel2
16
- def self.run(app, receive = "tcp://127.0.0.1:9997", send = "tcp://127.0.0.1:9996")
17
- conn = ::Mongrel2::Connection.new($sender_id, receive, send)
18
- @running = true
19
- trap("SIGINT") do
20
- @running = false
21
- end
22
-
23
- while @running
24
- puts "WAITING FOR REQUEST"
25
-
26
- req = conn.recv # Caution: Abort traps on SIGINT :/
27
- if req.disconnect?
28
- puts "DICONNECT"
29
- next
30
- end
31
-
32
- script_name = ENV["RACK_RELATIVE_URL_ROOT"] ||
33
- # PATTERN is like: /test/(.*.json) or /handlertest
34
- req.headers["PATTERN"].split('(', 2).first.gsub(/\/$/, '')
35
-
36
- env = {
37
- "rack.version" => Rack::VERSION,
38
- "rack.url_scheme" => "http",
39
- "rack.input" => StringIO.new(req.body),
40
- "rack.errors" => $stderr,
41
- "rack.multithread" => true,
42
- "rack.multiprocess" => true,
43
- "rack.run_once" => false,
44
-
45
- "mongrel2.pattern" => req.headers["PATTERN"],
46
-
47
- "REQUEST_METHOD" => req.headers["METHOD"],
48
- "SCRIPT_NAME" => script_name,
49
- "PATH_INFO" => req.headers["PATH"].gsub(script_name, ''),
50
- "QUERY_STRING" => req.headers["QUERY"]
51
- }
52
-
53
- env["SERVER_NAME"], env["SERVER_PORT"] = req.headers["host"].split(':', 2)
54
- req.headers.each do |key, val|
55
- unless key =~ /content_(type|length)/i
56
- key = "HTTP_#{key.upcase}"
57
- end
58
- env[key] = val
59
- end
60
-
61
- status, headers, rack_response = app.call(env)
62
- body = ""
63
- rack_response.each{|b| body << b}
64
- conn.reply_http(req, body, status, headers)
65
- end
66
- end
67
- end
68
- end
69
- end
@@ -1,158 +0,0 @@
1
- # On OSX:
2
- # sudo port install zmq
3
- # sudo gem install zmq
4
- # RUBY_ENGINE = 'ruby'
5
- require 'rubygems'
6
- gem 'ffi-rzmq'
7
- gem 'json'
8
- require 'ffi-rzmq'
9
- require 'json'
10
-
11
- $: << File.dirname(__FILE__)
12
- require 'request'
13
-
14
- CTX = ZMQ::Context.new(1)
15
-
16
- module Mongrel2
17
- # A Connection object manages the connection between your handler
18
- # and a Mongrel2 server (or servers). It can receive raw requests
19
- # or JSON encoded requests whether from HTTP or MSG request types,
20
- # and it can send individual responses or batch responses either
21
- # raw or as JSON. It also has a way to encode HTTP responses
22
- # for simplicity since that'll be fairly common.
23
- class Connection
24
-
25
- def initialize(sender_id, sub_addr, pub_addr)
26
- @sender_id = sender_id
27
-
28
- @reqs = CTX.socket(ZMQ::UPSTREAM)
29
- @reqs.connect(sub_addr)
30
-
31
- @resp = CTX.socket(ZMQ::PUB)
32
- @resp.connect(pub_addr)
33
- @resp.setsockopt(ZMQ::IDENTITY, sender_id)
34
-
35
- @sub_addr = sub_addr
36
- @pub_addr = pub_addr
37
- end
38
-
39
- # Receives a raw Request object that you
40
- # can then work with.
41
- def recv
42
- Request.parse(@reqs.recv_string(0))
43
- end
44
-
45
- # Same as regular recv, but assumes the body is JSON and
46
- # creates a new attribute named req.data with the decoded
47
- # payload. This will throw an error if it is not JSON.
48
- #
49
- # Normally Request just does this if the METHOD is 'JSON'
50
- # but you can use this to force it for say HTTP requests.
51
- def recv_json
52
- self.recv.tap do |req|
53
- req.data ||= JSON.parse(req.body)
54
- end
55
- end
56
-
57
- # Raw send to the given connection ID, mostly used
58
- # internally.
59
- def send_resp(uuid, conn_id, msg)
60
- header = "%s %d:%s," % [uuid, conn_id.size, conn_id]
61
- string = header + ' ' + msg
62
- #puts "DEBUG: #{string.inspect}"
63
- @resp.send_string(string, 0)
64
- end
65
-
66
- # Does a reply based on the given Request object and message.
67
- # This is easier since the req object contains all the info
68
- # needed to do the proper reply addressing.
69
- def reply(req, msg)
70
- self.send_resp(req.sender, req.conn_id, msg)
71
- end
72
-
73
- # Same as reply, but tries to convert data to JSON first.
74
- def reply_json(req, data)
75
- self.send_resp(req.sender, req.conn_id, JSON.generate(data))
76
- end
77
-
78
- # Basic HTTP response mechanism which will take your body,
79
- # any headers you've made, and encode them so that the
80
- # browser gets them.
81
- def reply_http(req, body, code=200, headers={})
82
- self.reply(req, http_response(body, code, headers))
83
- end
84
-
85
- # This lets you send a single message to many currently
86
- # connected clients. There's a MAX_IDENTS that you should
87
- # not exceed, so chunk your targets as needed. Each target
88
- # will receive the message once by Mongrel2, but you don't have
89
- # to loop which cuts down on reply volume.
90
- def deliver(uuid, idents, data)
91
- self.send_resp(uuid, idents.join(' '), data)
92
- end
93
-
94
- # Same as deliver, but converts to JSON first.
95
- def deliver_json(uuid, idents, data)
96
- self.deliver(uuid, idents, JSON.generate(data))
97
- end
98
-
99
- # Same as deliver, but builds an HTTP response, which means, yes,
100
- # you can reply to multiple connected clients waiting for an HTTP
101
- # response from one handler. Kinda cool.
102
- def deliver_http(uuid, idents, body, code=200, headers={})
103
- self.deliver(uuid, idents, http_response(body, code, headers))
104
- end
105
-
106
- private
107
- def http_response(body, code, headers)
108
- headers['Content-Length'] = body.size
109
- headers_s = headers.map{|k, v| "%s: %s" % [k,v]}.join("\r\n")
110
-
111
- "HTTP/1.1 #{code} #{StatusMessage[code.to_i]}\r\n#{headers_s}\r\n\r\n#{body}"
112
- end
113
-
114
- # From WEBrick: thanks dawg.
115
- StatusMessage = {
116
- 100 => 'Continue',
117
- 101 => 'Switching Protocols',
118
- 200 => 'OK',
119
- 201 => 'Created',
120
- 202 => 'Accepted',
121
- 203 => 'Non-Authoritative Information',
122
- 204 => 'No Content',
123
- 205 => 'Reset Content',
124
- 206 => 'Partial Content',
125
- 300 => 'Multiple Choices',
126
- 301 => 'Moved Permanently',
127
- 302 => 'Found',
128
- 303 => 'See Other',
129
- 304 => 'Not Modified',
130
- 305 => 'Use Proxy',
131
- 307 => 'Temporary Redirect',
132
- 400 => 'Bad Request',
133
- 401 => 'Unauthorized',
134
- 402 => 'Payment Required',
135
- 403 => 'Forbidden',
136
- 404 => 'Not Found',
137
- 405 => 'Method Not Allowed',
138
- 406 => 'Not Acceptable',
139
- 407 => 'Proxy Authentication Required',
140
- 408 => 'Request Timeout',
141
- 409 => 'Conflict',
142
- 410 => 'Gone',
143
- 411 => 'Length Required',
144
- 412 => 'Precondition Failed',
145
- 413 => 'Request Entity Too Large',
146
- 414 => 'Request-URI Too Large',
147
- 415 => 'Unsupported Media Type',
148
- 416 => 'Request Range Not Satisfiable',
149
- 417 => 'Expectation Failed',
150
- 500 => 'Internal Server Error',
151
- 501 => 'Not Implemented',
152
- 502 => 'Bad Gateway',
153
- 503 => 'Service Unavailable',
154
- 504 => 'Gateway Timeout',
155
- 505 => 'HTTP Version Not Supported'
156
- }
157
- end # class Connection
158
- end # mod Mongrel2
@@ -1,43 +0,0 @@
1
- module Mongrel2
2
- class FiberHandler < Handler
3
- def initialize(*args)
4
- raise "This handler is just around for testing. don't use it, it'll suck."
5
- end
6
-
7
- def fiber_handle
8
- @fiber ||= Fiber.new do |request|
9
- loop do
10
- on_request(request)
11
-
12
- # run on_disconnect if the server disconnects
13
- if request.disconnect?
14
- on_disconnect
15
- request = Fiber.yield
16
- next
17
- end
18
-
19
- # get the response from on_request
20
- response = process(request)
21
-
22
- # run the response through a filter
23
- response = after_process(response, request)
24
-
25
- # send it back to the server on the PUB socket
26
- @connection.reply_http(request, response)
27
-
28
- after_reply(request, response)
29
- request = Fiber.yield
30
- end
31
- end
32
- end
33
-
34
- def listen
35
- loop do
36
- on_wait
37
- request = @connection.recv
38
- fiber_handle.resume(request)
39
- end
40
- end
41
-
42
- end
43
- end
@@ -1,66 +0,0 @@
1
- module Mongrel2
2
- class Handler
3
- attr_accessor :connection
4
- def initialize(sender_uuid, subscribe_address, publish_address)
5
- @connection = Mongrel2::Connection.new(sender_uuid,
6
- subscribe_address, publish_address)
7
- end
8
-
9
- # Callback for when the handler is waiting for a request
10
- def on_wait(*args)
11
- end
12
-
13
- # Callback when a request is received (for debug)
14
- def on_request(request, *args)
15
- end
16
-
17
- # Override this to return a custom response
18
- def process(request, *args)
19
- puts "PROCESS REQUEST: #{request}"
20
- #raise NoHandlerDefined, "define process_request in your subclass"
21
- return request.inspect
22
- end
23
-
24
- # Callback for when the server disconnects
25
- def on_disconnect(request, *args)
26
- end
27
-
28
- # Callback after process_request is done
29
- def after_process(response, request, *args)
30
- return response
31
- end
32
-
33
- # Callback after the server gets the response
34
- def after_reply(request, response, *args)
35
- end
36
-
37
- # the body of the main recv loop
38
- def listen
39
- loop do
40
- on_wait
41
-
42
- # get the request from Mongrel2 on the UPSTREAM socket
43
- request = @connection.recv
44
- # run the on_request hook
45
- on_request(request)
46
-
47
- # run on_disconnect if the server disconnects
48
- if request.disconnect?
49
- on_disconnect
50
- next
51
- end
52
-
53
- # get the response from on_request
54
- response = process(request)
55
-
56
- # run the response through a filter
57
- response = after_process(response, request)
58
-
59
- # send it back to the server on the PUB socket
60
- @connection.reply_http(request, response)
61
-
62
- after_reply(request, response)
63
- end
64
- end
65
- end
66
- end