m2r 0.0.3 → 1.0.0

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