giraffesoft-unicorn 0.93.5

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 (141) hide show
  1. data/.CHANGELOG.old +25 -0
  2. data/.document +16 -0
  3. data/.gitignore +20 -0
  4. data/.mailmap +26 -0
  5. data/CONTRIBUTORS +31 -0
  6. data/COPYING +339 -0
  7. data/DESIGN +105 -0
  8. data/Documentation/.gitignore +5 -0
  9. data/Documentation/GNUmakefile +30 -0
  10. data/Documentation/unicorn.1.txt +167 -0
  11. data/Documentation/unicorn_rails.1.txt +169 -0
  12. data/GIT-VERSION-GEN +40 -0
  13. data/GNUmakefile +270 -0
  14. data/HACKING +113 -0
  15. data/KNOWN_ISSUES +40 -0
  16. data/LICENSE +55 -0
  17. data/PHILOSOPHY +144 -0
  18. data/README +153 -0
  19. data/Rakefile +108 -0
  20. data/SIGNALS +97 -0
  21. data/TODO +16 -0
  22. data/TUNING +70 -0
  23. data/bin/unicorn +165 -0
  24. data/bin/unicorn_rails +208 -0
  25. data/examples/echo.ru +27 -0
  26. data/examples/git.ru +13 -0
  27. data/examples/init.sh +53 -0
  28. data/ext/unicorn_http/c_util.h +107 -0
  29. data/ext/unicorn_http/common_field_optimization.h +111 -0
  30. data/ext/unicorn_http/ext_help.h +73 -0
  31. data/ext/unicorn_http/extconf.rb +14 -0
  32. data/ext/unicorn_http/global_variables.h +91 -0
  33. data/ext/unicorn_http/unicorn_http.rl +715 -0
  34. data/ext/unicorn_http/unicorn_http_common.rl +74 -0
  35. data/lib/unicorn.rb +730 -0
  36. data/lib/unicorn/app/exec_cgi.rb +150 -0
  37. data/lib/unicorn/app/inetd.rb +109 -0
  38. data/lib/unicorn/app/old_rails.rb +31 -0
  39. data/lib/unicorn/app/old_rails/static.rb +60 -0
  40. data/lib/unicorn/cgi_wrapper.rb +145 -0
  41. data/lib/unicorn/configurator.rb +403 -0
  42. data/lib/unicorn/const.rb +37 -0
  43. data/lib/unicorn/http_request.rb +74 -0
  44. data/lib/unicorn/http_response.rb +74 -0
  45. data/lib/unicorn/launcher.rb +39 -0
  46. data/lib/unicorn/socket_helper.rb +138 -0
  47. data/lib/unicorn/tee_input.rb +174 -0
  48. data/lib/unicorn/util.rb +64 -0
  49. data/local.mk.sample +53 -0
  50. data/setup.rb +1586 -0
  51. data/test/aggregate.rb +15 -0
  52. data/test/benchmark/README +50 -0
  53. data/test/benchmark/dd.ru +18 -0
  54. data/test/exec/README +5 -0
  55. data/test/exec/test_exec.rb +855 -0
  56. data/test/rails/app-1.2.3/.gitignore +2 -0
  57. data/test/rails/app-1.2.3/Rakefile +7 -0
  58. data/test/rails/app-1.2.3/app/controllers/application.rb +6 -0
  59. data/test/rails/app-1.2.3/app/controllers/foo_controller.rb +36 -0
  60. data/test/rails/app-1.2.3/app/helpers/application_helper.rb +4 -0
  61. data/test/rails/app-1.2.3/config/boot.rb +11 -0
  62. data/test/rails/app-1.2.3/config/database.yml +12 -0
  63. data/test/rails/app-1.2.3/config/environment.rb +13 -0
  64. data/test/rails/app-1.2.3/config/environments/development.rb +9 -0
  65. data/test/rails/app-1.2.3/config/environments/production.rb +5 -0
  66. data/test/rails/app-1.2.3/config/routes.rb +6 -0
  67. data/test/rails/app-1.2.3/db/.gitignore +0 -0
  68. data/test/rails/app-1.2.3/public/404.html +1 -0
  69. data/test/rails/app-1.2.3/public/500.html +1 -0
  70. data/test/rails/app-2.0.2/.gitignore +2 -0
  71. data/test/rails/app-2.0.2/Rakefile +7 -0
  72. data/test/rails/app-2.0.2/app/controllers/application.rb +4 -0
  73. data/test/rails/app-2.0.2/app/controllers/foo_controller.rb +36 -0
  74. data/test/rails/app-2.0.2/app/helpers/application_helper.rb +4 -0
  75. data/test/rails/app-2.0.2/config/boot.rb +11 -0
  76. data/test/rails/app-2.0.2/config/database.yml +12 -0
  77. data/test/rails/app-2.0.2/config/environment.rb +17 -0
  78. data/test/rails/app-2.0.2/config/environments/development.rb +8 -0
  79. data/test/rails/app-2.0.2/config/environments/production.rb +5 -0
  80. data/test/rails/app-2.0.2/config/routes.rb +6 -0
  81. data/test/rails/app-2.0.2/db/.gitignore +0 -0
  82. data/test/rails/app-2.0.2/public/404.html +1 -0
  83. data/test/rails/app-2.0.2/public/500.html +1 -0
  84. data/test/rails/app-2.1.2/.gitignore +2 -0
  85. data/test/rails/app-2.1.2/Rakefile +7 -0
  86. data/test/rails/app-2.1.2/app/controllers/application.rb +4 -0
  87. data/test/rails/app-2.1.2/app/controllers/foo_controller.rb +36 -0
  88. data/test/rails/app-2.1.2/app/helpers/application_helper.rb +4 -0
  89. data/test/rails/app-2.1.2/config/boot.rb +111 -0
  90. data/test/rails/app-2.1.2/config/database.yml +12 -0
  91. data/test/rails/app-2.1.2/config/environment.rb +17 -0
  92. data/test/rails/app-2.1.2/config/environments/development.rb +7 -0
  93. data/test/rails/app-2.1.2/config/environments/production.rb +5 -0
  94. data/test/rails/app-2.1.2/config/routes.rb +6 -0
  95. data/test/rails/app-2.1.2/db/.gitignore +0 -0
  96. data/test/rails/app-2.1.2/public/404.html +1 -0
  97. data/test/rails/app-2.1.2/public/500.html +1 -0
  98. data/test/rails/app-2.2.2/.gitignore +2 -0
  99. data/test/rails/app-2.2.2/Rakefile +7 -0
  100. data/test/rails/app-2.2.2/app/controllers/application.rb +4 -0
  101. data/test/rails/app-2.2.2/app/controllers/foo_controller.rb +36 -0
  102. data/test/rails/app-2.2.2/app/helpers/application_helper.rb +4 -0
  103. data/test/rails/app-2.2.2/config/boot.rb +111 -0
  104. data/test/rails/app-2.2.2/config/database.yml +12 -0
  105. data/test/rails/app-2.2.2/config/environment.rb +17 -0
  106. data/test/rails/app-2.2.2/config/environments/development.rb +7 -0
  107. data/test/rails/app-2.2.2/config/environments/production.rb +5 -0
  108. data/test/rails/app-2.2.2/config/routes.rb +6 -0
  109. data/test/rails/app-2.2.2/db/.gitignore +0 -0
  110. data/test/rails/app-2.2.2/public/404.html +1 -0
  111. data/test/rails/app-2.2.2/public/500.html +1 -0
  112. data/test/rails/app-2.3.3.1/.gitignore +2 -0
  113. data/test/rails/app-2.3.3.1/Rakefile +7 -0
  114. data/test/rails/app-2.3.3.1/app/controllers/application_controller.rb +5 -0
  115. data/test/rails/app-2.3.3.1/app/controllers/foo_controller.rb +36 -0
  116. data/test/rails/app-2.3.3.1/app/helpers/application_helper.rb +4 -0
  117. data/test/rails/app-2.3.3.1/config/boot.rb +109 -0
  118. data/test/rails/app-2.3.3.1/config/database.yml +12 -0
  119. data/test/rails/app-2.3.3.1/config/environment.rb +17 -0
  120. data/test/rails/app-2.3.3.1/config/environments/development.rb +7 -0
  121. data/test/rails/app-2.3.3.1/config/environments/production.rb +6 -0
  122. data/test/rails/app-2.3.3.1/config/routes.rb +6 -0
  123. data/test/rails/app-2.3.3.1/db/.gitignore +0 -0
  124. data/test/rails/app-2.3.3.1/public/404.html +1 -0
  125. data/test/rails/app-2.3.3.1/public/500.html +1 -0
  126. data/test/rails/app-2.3.3.1/public/x.txt +1 -0
  127. data/test/rails/test_rails.rb +280 -0
  128. data/test/test_helper.rb +296 -0
  129. data/test/unit/test_configurator.rb +150 -0
  130. data/test/unit/test_http_parser.rb +492 -0
  131. data/test/unit/test_http_parser_ng.rb +308 -0
  132. data/test/unit/test_request.rb +184 -0
  133. data/test/unit/test_response.rb +110 -0
  134. data/test/unit/test_server.rb +188 -0
  135. data/test/unit/test_signals.rb +202 -0
  136. data/test/unit/test_socket_helper.rb +133 -0
  137. data/test/unit/test_tee_input.rb +229 -0
  138. data/test/unit/test_upload.rb +297 -0
  139. data/test/unit/test_util.rb +96 -0
  140. data/unicorn.gemspec +42 -0
  141. metadata +228 -0
@@ -0,0 +1,308 @@
1
+ # -*- encoding: binary -*-
2
+
3
+ # coding: binary
4
+ require 'test/test_helper'
5
+ require 'digest/md5'
6
+
7
+ include Unicorn
8
+
9
+ class HttpParserNgTest < Test::Unit::TestCase
10
+
11
+ def setup
12
+ @parser = HttpParser.new
13
+ end
14
+
15
+ def test_identity_step_headers
16
+ req = {}
17
+ str = "PUT / HTTP/1.1\r\n"
18
+ assert ! @parser.headers(req, str)
19
+ str << "Content-Length: 123\r\n"
20
+ assert ! @parser.headers(req, str)
21
+ str << "\r\n"
22
+ assert_equal req.object_id, @parser.headers(req, str).object_id
23
+ assert_equal '123', req['CONTENT_LENGTH']
24
+ assert_equal 0, str.size
25
+ assert ! @parser.keepalive?
26
+ assert @parser.headers?
27
+ end
28
+
29
+ def test_identity_oneshot_header
30
+ req = {}
31
+ str = "PUT / HTTP/1.1\r\nContent-Length: 123\r\n\r\n"
32
+ assert_equal req.object_id, @parser.headers(req, str).object_id
33
+ assert_equal '123', req['CONTENT_LENGTH']
34
+ assert_equal 0, str.size
35
+ assert ! @parser.keepalive?
36
+ end
37
+
38
+ def test_identity_oneshot_header_with_body
39
+ body = ('a' * 123).freeze
40
+ req = {}
41
+ str = "PUT / HTTP/1.1\r\n" \
42
+ "Content-Length: #{body.length}\r\n" \
43
+ "\r\n#{body}"
44
+ assert_equal req.object_id, @parser.headers(req, str).object_id
45
+ assert_equal '123', req['CONTENT_LENGTH']
46
+ assert_equal 123, str.size
47
+ assert_equal body, str
48
+ tmp = ''
49
+ assert_nil @parser.filter_body(tmp, str)
50
+ assert_equal 0, str.size
51
+ assert_equal tmp, body
52
+ assert_equal "", @parser.filter_body(tmp, str)
53
+ assert ! @parser.keepalive?
54
+ end
55
+
56
+ def test_identity_oneshot_header_with_body_partial
57
+ str = "PUT / HTTP/1.1\r\nContent-Length: 123\r\n\r\na"
58
+ assert_equal Hash, @parser.headers({}, str).class
59
+ assert_equal 1, str.size
60
+ assert_equal 'a', str
61
+ tmp = ''
62
+ assert_nil @parser.filter_body(tmp, str)
63
+ assert_equal "", str
64
+ assert_equal "a", tmp
65
+ str << ' ' * 122
66
+ rv = @parser.filter_body(tmp, str)
67
+ assert_equal 122, tmp.size
68
+ assert_nil rv
69
+ assert_equal "", str
70
+ assert_equal str.object_id, @parser.filter_body(tmp, str).object_id
71
+ assert ! @parser.keepalive?
72
+ end
73
+
74
+ def test_identity_oneshot_header_with_body_slop
75
+ str = "PUT / HTTP/1.1\r\nContent-Length: 1\r\n\r\naG"
76
+ assert_equal Hash, @parser.headers({}, str).class
77
+ assert_equal 2, str.size
78
+ assert_equal 'aG', str
79
+ tmp = ''
80
+ assert_nil @parser.filter_body(tmp, str)
81
+ assert_equal "G", str
82
+ assert_equal "G", @parser.filter_body(tmp, str)
83
+ assert_equal 1, tmp.size
84
+ assert_equal "a", tmp
85
+ assert ! @parser.keepalive?
86
+ end
87
+
88
+ def test_chunked
89
+ str = "PUT / HTTP/1.1\r\ntransfer-Encoding: chunked\r\n\r\n"
90
+ req = {}
91
+ assert_equal req, @parser.headers(req, str)
92
+ assert_equal 0, str.size
93
+ tmp = ""
94
+ assert_nil @parser.filter_body(tmp, "6")
95
+ assert_equal 0, tmp.size
96
+ assert_nil @parser.filter_body(tmp, rv = "\r\n")
97
+ assert_equal 0, rv.size
98
+ assert_equal 0, tmp.size
99
+ tmp = ""
100
+ assert_nil @parser.filter_body(tmp, "..")
101
+ assert_equal "..", tmp
102
+ assert_nil @parser.filter_body(tmp, "abcd\r\n0\r\n")
103
+ assert_equal "abcd", tmp
104
+ rv = "PUT"
105
+ assert_equal rv.object_id, @parser.filter_body(tmp, rv).object_id
106
+ assert_equal "PUT", rv
107
+ assert ! @parser.keepalive?
108
+ end
109
+
110
+ def test_two_chunks
111
+ str = "PUT / HTTP/1.1\r\ntransfer-Encoding: chunked\r\n\r\n"
112
+ req = {}
113
+ assert_equal req, @parser.headers(req, str)
114
+ assert_equal 0, str.size
115
+ tmp = ""
116
+ assert_nil @parser.filter_body(tmp, "6")
117
+ assert_equal 0, tmp.size
118
+ assert_nil @parser.filter_body(tmp, rv = "\r\n")
119
+ assert_equal "", rv
120
+ assert_equal 0, tmp.size
121
+ tmp = ""
122
+ assert_nil @parser.filter_body(tmp, "..")
123
+ assert_equal 2, tmp.size
124
+ assert_equal "..", tmp
125
+ assert_nil @parser.filter_body(tmp, "abcd\r\n1")
126
+ assert_equal "abcd", tmp
127
+ assert_nil @parser.filter_body(tmp, "\r")
128
+ assert_equal "", tmp
129
+ assert_nil @parser.filter_body(tmp, "\n")
130
+ assert_equal "", tmp
131
+ assert_nil @parser.filter_body(tmp, "z")
132
+ assert_equal "z", tmp
133
+ assert_nil @parser.filter_body(tmp, "\r\n")
134
+ assert_nil @parser.filter_body(tmp, "0")
135
+ assert_nil @parser.filter_body(tmp, "\r")
136
+ rv = @parser.filter_body(tmp, buf = "\nGET")
137
+ assert_equal "GET", rv
138
+ assert_equal buf.object_id, rv.object_id
139
+ assert ! @parser.keepalive?
140
+ end
141
+
142
+ def test_big_chunk
143
+ str = "PUT / HTTP/1.1\r\ntransfer-Encoding: chunked\r\n\r\n" \
144
+ "4000\r\nabcd"
145
+ req = {}
146
+ assert_equal req, @parser.headers(req, str)
147
+ tmp = ''
148
+ assert_nil @parser.filter_body(tmp, str)
149
+ assert_equal '', str
150
+ str = ' ' * 16300
151
+ assert_nil @parser.filter_body(tmp, str)
152
+ assert_equal '', str
153
+ str = ' ' * 80
154
+ assert_nil @parser.filter_body(tmp, str)
155
+ assert_equal '', str
156
+ assert ! @parser.body_eof?
157
+ assert_equal "", @parser.filter_body(tmp, "\r\n0\r\n")
158
+ assert @parser.body_eof?
159
+ assert ! @parser.keepalive?
160
+ end
161
+
162
+ def test_two_chunks_oneshot
163
+ str = "PUT / HTTP/1.1\r\ntransfer-Encoding: chunked\r\n\r\n" \
164
+ "1\r\na\r\n2\r\n..\r\n0\r\n"
165
+ req = {}
166
+ assert_equal req, @parser.headers(req, str)
167
+ tmp = ''
168
+ assert_nil @parser.filter_body(tmp, str)
169
+ assert_equal 'a..', tmp
170
+ rv = @parser.filter_body(tmp, str)
171
+ assert_equal rv.object_id, str.object_id
172
+ assert ! @parser.keepalive?
173
+ end
174
+
175
+ def test_trailers
176
+ str = "PUT / HTTP/1.1\r\n" \
177
+ "Trailer: Content-MD5\r\n" \
178
+ "transfer-Encoding: chunked\r\n\r\n" \
179
+ "1\r\na\r\n2\r\n..\r\n0\r\n"
180
+ req = {}
181
+ assert_equal req, @parser.headers(req, str)
182
+ assert_equal 'Content-MD5', req['HTTP_TRAILER']
183
+ assert_nil req['HTTP_CONTENT_MD5']
184
+ tmp = ''
185
+ assert_nil @parser.filter_body(tmp, str)
186
+ assert_equal 'a..', tmp
187
+ md5_b64 = [ Digest::MD5.digest(tmp) ].pack('m').strip.freeze
188
+ rv = @parser.filter_body(tmp, str)
189
+ assert_equal rv.object_id, str.object_id
190
+ assert_equal '', str
191
+ md5_hdr = "Content-MD5: #{md5_b64}\r\n".freeze
192
+ str << md5_hdr
193
+ assert_nil @parser.trailers(req, str)
194
+ assert_equal md5_b64, req['HTTP_CONTENT_MD5']
195
+ assert_equal "CONTENT_MD5: #{md5_b64}\r\n", str
196
+ assert_nil @parser.trailers(req, str << "\r")
197
+ assert_equal req, @parser.trailers(req, str << "\nGET / ")
198
+ assert_equal "GET / ", str
199
+ assert ! @parser.keepalive?
200
+ end
201
+
202
+ def test_max_chunk
203
+ str = "PUT / HTTP/1.1\r\n" \
204
+ "transfer-Encoding: chunked\r\n\r\n" \
205
+ "#{HttpParser::CHUNK_MAX.to_s(16)}\r\na\r\n2\r\n..\r\n0\r\n"
206
+ req = {}
207
+ assert_equal req, @parser.headers(req, str)
208
+ assert_nil @parser.content_length
209
+ assert_nothing_raised { @parser.filter_body('', str) }
210
+ assert ! @parser.keepalive?
211
+ end
212
+
213
+ def test_max_body
214
+ n = HttpParser::LENGTH_MAX
215
+ str = "PUT / HTTP/1.1\r\nContent-Length: #{n}\r\n\r\n"
216
+ req = {}
217
+ assert_nothing_raised { @parser.headers(req, str) }
218
+ assert_equal n, req['CONTENT_LENGTH'].to_i
219
+ assert ! @parser.keepalive?
220
+ end
221
+
222
+ def test_overflow_chunk
223
+ n = HttpParser::CHUNK_MAX + 1
224
+ str = "PUT / HTTP/1.1\r\n" \
225
+ "transfer-Encoding: chunked\r\n\r\n" \
226
+ "#{n.to_s(16)}\r\na\r\n2\r\n..\r\n0\r\n"
227
+ req = {}
228
+ assert_equal req, @parser.headers(req, str)
229
+ assert_nil @parser.content_length
230
+ assert_raise(HttpParserError) { @parser.filter_body('', str) }
231
+ assert ! @parser.keepalive?
232
+ end
233
+
234
+ def test_overflow_content_length
235
+ n = HttpParser::LENGTH_MAX + 1
236
+ str = "PUT / HTTP/1.1\r\nContent-Length: #{n}\r\n\r\n"
237
+ assert_raise(HttpParserError) { @parser.headers({}, str) }
238
+ assert ! @parser.keepalive?
239
+ end
240
+
241
+ def test_bad_chunk
242
+ str = "PUT / HTTP/1.1\r\n" \
243
+ "transfer-Encoding: chunked\r\n\r\n" \
244
+ "#zzz\r\na\r\n2\r\n..\r\n0\r\n"
245
+ req = {}
246
+ assert_equal req, @parser.headers(req, str)
247
+ assert_nil @parser.content_length
248
+ assert_raise(HttpParserError) { @parser.filter_body('', str) }
249
+ assert ! @parser.keepalive?
250
+ end
251
+
252
+ def test_bad_content_length
253
+ str = "PUT / HTTP/1.1\r\nContent-Length: 7ff\r\n\r\n"
254
+ assert_raise(HttpParserError) { @parser.headers({}, str) }
255
+ assert ! @parser.keepalive?
256
+ end
257
+
258
+ def test_bad_trailers
259
+ str = "PUT / HTTP/1.1\r\n" \
260
+ "Trailer: Transfer-Encoding\r\n" \
261
+ "transfer-Encoding: chunked\r\n\r\n" \
262
+ "1\r\na\r\n2\r\n..\r\n0\r\n"
263
+ req = {}
264
+ assert_equal req, @parser.headers(req, str)
265
+ assert_equal 'Transfer-Encoding', req['HTTP_TRAILER']
266
+ tmp = ''
267
+ assert_nil @parser.filter_body(tmp, str)
268
+ assert_equal 'a..', tmp
269
+ assert_equal '', str
270
+ str << "Transfer-Encoding: identity\r\n\r\n"
271
+ assert_raise(HttpParserError) { @parser.trailers(req, str) }
272
+ assert ! @parser.keepalive?
273
+ end
274
+
275
+ def test_repeat_headers
276
+ str = "PUT / HTTP/1.1\r\n" \
277
+ "Trailer: Content-MD5\r\n" \
278
+ "Trailer: Content-SHA1\r\n" \
279
+ "transfer-Encoding: chunked\r\n\r\n" \
280
+ "1\r\na\r\n2\r\n..\r\n0\r\n"
281
+ req = {}
282
+ assert_equal req, @parser.headers(req, str)
283
+ assert_equal 'Content-MD5,Content-SHA1', req['HTTP_TRAILER']
284
+ assert ! @parser.keepalive?
285
+ end
286
+
287
+ def test_parse_simple_request
288
+ parser = HttpParser.new
289
+ req = {}
290
+ http = "GET /read-rfc1945-if-you-dont-believe-me\r\n"
291
+ assert_equal req, parser.headers(req, http)
292
+ assert_equal '', http
293
+ expect = {
294
+ "SERVER_NAME"=>"localhost",
295
+ "rack.url_scheme"=>"http",
296
+ "REQUEST_PATH"=>"/read-rfc1945-if-you-dont-believe-me",
297
+ "PATH_INFO"=>"/read-rfc1945-if-you-dont-believe-me",
298
+ "REQUEST_URI"=>"/read-rfc1945-if-you-dont-believe-me",
299
+ "SERVER_PORT"=>"80",
300
+ "SERVER_PROTOCOL"=>"HTTP/0.9",
301
+ "REQUEST_METHOD"=>"GET",
302
+ "QUERY_STRING"=>""
303
+ }
304
+ assert_equal expect, req
305
+ assert ! parser.headers?
306
+ end
307
+
308
+ end
@@ -0,0 +1,184 @@
1
+ # -*- encoding: binary -*-
2
+
3
+ # Copyright (c) 2009 Eric Wong
4
+ # You can redistribute it and/or modify it under the same terms as Ruby.
5
+
6
+ require 'test/test_helper'
7
+
8
+ include Unicorn
9
+
10
+ class RequestTest < Test::Unit::TestCase
11
+
12
+ class MockRequest < StringIO
13
+ alias_method :readpartial, :sysread
14
+ alias_method :read_nonblock, :sysread
15
+ end
16
+
17
+ def setup
18
+ @request = HttpRequest.new
19
+ @app = lambda do |env|
20
+ [ 200, { 'Content-Length' => '0', 'Content-Type' => 'text/plain' }, [] ]
21
+ end
22
+ @lint = Rack::Lint.new(@app)
23
+ end
24
+
25
+ def test_options
26
+ client = MockRequest.new("OPTIONS * HTTP/1.1\r\n" \
27
+ "Host: foo\r\n\r\n")
28
+ res = env = nil
29
+ assert_nothing_raised { env = @request.read(client) }
30
+ assert_equal '', env['REQUEST_PATH']
31
+ assert_equal '', env['PATH_INFO']
32
+ assert_equal '*', env['REQUEST_URI']
33
+ assert_nothing_raised { res = @lint.call(env) }
34
+ end
35
+
36
+ def test_absolute_uri_with_query
37
+ client = MockRequest.new("GET http://e:3/x?y=z HTTP/1.1\r\n" \
38
+ "Host: foo\r\n\r\n")
39
+ res = env = nil
40
+ assert_nothing_raised { env = @request.read(client) }
41
+ assert_equal '/x', env['REQUEST_PATH']
42
+ assert_equal '/x', env['PATH_INFO']
43
+ assert_equal 'y=z', env['QUERY_STRING']
44
+ assert_nothing_raised { res = @lint.call(env) }
45
+ end
46
+
47
+ def test_absolute_uri_with_fragment
48
+ client = MockRequest.new("GET http://e:3/x#frag HTTP/1.1\r\n" \
49
+ "Host: foo\r\n\r\n")
50
+ res = env = nil
51
+ assert_nothing_raised { env = @request.read(client) }
52
+ assert_equal '/x', env['REQUEST_PATH']
53
+ assert_equal '/x', env['PATH_INFO']
54
+ assert_equal '', env['QUERY_STRING']
55
+ assert_equal 'frag', env['FRAGMENT']
56
+ assert_nothing_raised { res = @lint.call(env) }
57
+ end
58
+
59
+ def test_absolute_uri_with_query_and_fragment
60
+ client = MockRequest.new("GET http://e:3/x?a=b#frag HTTP/1.1\r\n" \
61
+ "Host: foo\r\n\r\n")
62
+ res = env = nil
63
+ assert_nothing_raised { env = @request.read(client) }
64
+ assert_equal '/x', env['REQUEST_PATH']
65
+ assert_equal '/x', env['PATH_INFO']
66
+ assert_equal 'a=b', env['QUERY_STRING']
67
+ assert_equal 'frag', env['FRAGMENT']
68
+ assert_nothing_raised { res = @lint.call(env) }
69
+ end
70
+
71
+ def test_absolute_uri_unsupported_schemes
72
+ %w(ssh+http://e/ ftp://e/x http+ssh://e/x).each do |abs_uri|
73
+ client = MockRequest.new("GET #{abs_uri} HTTP/1.1\r\n" \
74
+ "Host: foo\r\n\r\n")
75
+ assert_raises(HttpParserError) { @request.read(client) }
76
+ end
77
+ end
78
+
79
+ def test_x_forwarded_proto_https
80
+ res = env = nil
81
+ client = MockRequest.new("GET / HTTP/1.1\r\n" \
82
+ "X-Forwarded-Proto: https\r\n" \
83
+ "Host: foo\r\n\r\n")
84
+ assert_nothing_raised { env = @request.read(client) }
85
+ assert_equal "https", env['rack.url_scheme']
86
+ assert_nothing_raised { res = @lint.call(env) }
87
+ end
88
+
89
+ def test_x_forwarded_proto_http
90
+ res = env = nil
91
+ client = MockRequest.new("GET / HTTP/1.1\r\n" \
92
+ "X-Forwarded-Proto: http\r\n" \
93
+ "Host: foo\r\n\r\n")
94
+ assert_nothing_raised { env = @request.read(client) }
95
+ assert_equal "http", env['rack.url_scheme']
96
+ assert_nothing_raised { res = @lint.call(env) }
97
+ end
98
+
99
+ def test_x_forwarded_proto_invalid
100
+ res = env = nil
101
+ client = MockRequest.new("GET / HTTP/1.1\r\n" \
102
+ "X-Forwarded-Proto: ftp\r\n" \
103
+ "Host: foo\r\n\r\n")
104
+ assert_nothing_raised { env = @request.read(client) }
105
+ assert_equal "http", env['rack.url_scheme']
106
+ assert_nothing_raised { res = @lint.call(env) }
107
+ end
108
+
109
+ def test_rack_lint_get
110
+ client = MockRequest.new("GET / HTTP/1.1\r\nHost: foo\r\n\r\n")
111
+ res = env = nil
112
+ assert_nothing_raised { env = @request.read(client) }
113
+ assert_equal "http", env['rack.url_scheme']
114
+ assert_equal '127.0.0.1', env['REMOTE_ADDR']
115
+ assert_nothing_raised { res = @lint.call(env) }
116
+ end
117
+
118
+ def test_no_content_stringio
119
+ client = MockRequest.new("GET / HTTP/1.1\r\nHost: foo\r\n\r\n")
120
+ res = env = nil
121
+ assert_nothing_raised { env = @request.read(client) }
122
+ assert_equal StringIO, env['rack.input'].class
123
+ end
124
+
125
+ def test_zero_content_stringio
126
+ client = MockRequest.new("PUT / HTTP/1.1\r\n" \
127
+ "Content-Length: 0\r\n" \
128
+ "Host: foo\r\n\r\n")
129
+ res = env = nil
130
+ assert_nothing_raised { env = @request.read(client) }
131
+ assert_equal StringIO, env['rack.input'].class
132
+ end
133
+
134
+ def test_real_content_not_stringio
135
+ client = MockRequest.new("PUT / HTTP/1.1\r\n" \
136
+ "Content-Length: 1\r\n" \
137
+ "Host: foo\r\n\r\n")
138
+ res = env = nil
139
+ assert_nothing_raised { env = @request.read(client) }
140
+ assert_equal Unicorn::TeeInput, env['rack.input'].class
141
+ end
142
+
143
+ def test_rack_lint_put
144
+ client = MockRequest.new(
145
+ "PUT / HTTP/1.1\r\n" \
146
+ "Host: foo\r\n" \
147
+ "Content-Length: 5\r\n" \
148
+ "\r\n" \
149
+ "abcde")
150
+ res = env = nil
151
+ assert_nothing_raised { env = @request.read(client) }
152
+ assert ! env.include?(:http_body)
153
+ assert_nothing_raised { res = @lint.call(env) }
154
+ end
155
+
156
+ def test_rack_lint_big_put
157
+ count = 100
158
+ bs = 0x10000
159
+ buf = (' ' * bs).freeze
160
+ length = bs * count
161
+ client = Tempfile.new('big_put')
162
+ client.syswrite(
163
+ "PUT / HTTP/1.1\r\n" \
164
+ "Host: foo\r\n" \
165
+ "Content-Length: #{length}\r\n" \
166
+ "\r\n")
167
+ count.times { assert_equal bs, client.syswrite(buf) }
168
+ assert_equal 0, client.sysseek(0)
169
+ res = env = nil
170
+ assert_nothing_raised { env = @request.read(client) }
171
+ assert ! env.include?(:http_body)
172
+ assert_equal length, env['rack.input'].size
173
+ count.times {
174
+ tmp = env['rack.input'].read(bs)
175
+ tmp << env['rack.input'].read(bs - tmp.size) if tmp.size != bs
176
+ assert_equal buf, tmp
177
+ }
178
+ assert_nil env['rack.input'].read(bs)
179
+ assert_nothing_raised { env['rack.input'].rewind }
180
+ assert_nothing_raised { res = @lint.call(env) }
181
+ end
182
+
183
+ end
184
+