tee_input: update documentation for Rack 1.2
[unicorn.git] / test / unit / test_request.rb
blob1896300455314d4dcc099a94f6ec5da40a4919b0
1 # -*- encoding: binary -*-
3 # Copyright (c) 2009 Eric Wong
4 # You can redistribute it and/or modify it under the same terms as Ruby.
6 require 'test/test_helper'
8 include Unicorn
10 class RequestTest < Test::Unit::TestCase
12   class MockRequest < StringIO
13     alias_method :readpartial, :sysread
14     alias_method :read_nonblock, :sysread
15   end
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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