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'
10 class RequestTest < Test::Unit::TestCase
12 class MockRequest < StringIO
13 alias_method :readpartial, :sysread
14 alias_method :kgio_read!, :sysread
15 alias_method :read_nonblock, :sysread
22 @request = HttpRequest.new
23 @app = lambda do |env|
24 [ 200, { 'Content-Length' => '0', 'Content-Type' => 'text/plain' }, [] ]
26 @lint = Rack::Lint.new(@app)
30 client = MockRequest.new("OPTIONS * HTTP/1.1\r\n" \
33 assert_nothing_raised { env = @request.read(client) }
34 assert_equal '', env['REQUEST_PATH']
35 assert_equal '', env['PATH_INFO']
36 assert_equal '*', env['REQUEST_URI']
37 assert_nothing_raised { res = @lint.call(env) }
40 def test_absolute_uri_with_query
41 client = MockRequest.new("GET http://e:3/x?y=z HTTP/1.1\r\n" \
44 assert_nothing_raised { env = @request.read(client) }
45 assert_equal '/x', env['REQUEST_PATH']
46 assert_equal '/x', env['PATH_INFO']
47 assert_equal 'y=z', env['QUERY_STRING']
48 assert_nothing_raised { res = @lint.call(env) }
51 def test_absolute_uri_with_fragment
52 client = MockRequest.new("GET http://e:3/x#frag HTTP/1.1\r\n" \
55 assert_nothing_raised { env = @request.read(client) }
56 assert_equal '/x', env['REQUEST_PATH']
57 assert_equal '/x', env['PATH_INFO']
58 assert_equal '', env['QUERY_STRING']
59 assert_equal 'frag', env['FRAGMENT']
60 assert_nothing_raised { res = @lint.call(env) }
63 def test_absolute_uri_with_query_and_fragment
64 client = MockRequest.new("GET http://e:3/x?a=b#frag HTTP/1.1\r\n" \
67 assert_nothing_raised { env = @request.read(client) }
68 assert_equal '/x', env['REQUEST_PATH']
69 assert_equal '/x', env['PATH_INFO']
70 assert_equal 'a=b', env['QUERY_STRING']
71 assert_equal 'frag', env['FRAGMENT']
72 assert_nothing_raised { res = @lint.call(env) }
75 def test_absolute_uri_unsupported_schemes
76 %w(ssh+http://e/ ftp://e/x http+ssh://e/x).each do |abs_uri|
77 client = MockRequest.new("GET #{abs_uri} HTTP/1.1\r\n" \
79 assert_raises(HttpParserError) { @request.read(client) }
83 def test_x_forwarded_proto_https
85 client = MockRequest.new("GET / HTTP/1.1\r\n" \
86 "X-Forwarded-Proto: https\r\n" \
88 assert_nothing_raised { env = @request.read(client) }
89 assert_equal "https", env['rack.url_scheme']
90 assert_nothing_raised { res = @lint.call(env) }
93 def test_x_forwarded_proto_http
95 client = MockRequest.new("GET / HTTP/1.1\r\n" \
96 "X-Forwarded-Proto: http\r\n" \
98 assert_nothing_raised { env = @request.read(client) }
99 assert_equal "http", env['rack.url_scheme']
100 assert_nothing_raised { res = @lint.call(env) }
103 def test_x_forwarded_proto_invalid
105 client = MockRequest.new("GET / HTTP/1.1\r\n" \
106 "X-Forwarded-Proto: ftp\r\n" \
108 assert_nothing_raised { env = @request.read(client) }
109 assert_equal "http", env['rack.url_scheme']
110 assert_nothing_raised { res = @lint.call(env) }
113 def test_rack_lint_get
114 client = MockRequest.new("GET / HTTP/1.1\r\nHost: foo\r\n\r\n")
116 assert_nothing_raised { env = @request.read(client) }
117 assert_equal "http", env['rack.url_scheme']
118 assert_equal '127.0.0.1', env['REMOTE_ADDR']
119 assert_nothing_raised { res = @lint.call(env) }
122 def test_no_content_stringio
123 client = MockRequest.new("GET / HTTP/1.1\r\nHost: foo\r\n\r\n")
125 assert_nothing_raised { env = @request.read(client) }
126 assert_equal StringIO, env['rack.input'].class
129 def test_zero_content_stringio
130 client = MockRequest.new("PUT / HTTP/1.1\r\n" \
131 "Content-Length: 0\r\n" \
134 assert_nothing_raised { env = @request.read(client) }
135 assert_equal StringIO, env['rack.input'].class
138 def test_real_content_not_stringio
139 client = MockRequest.new("PUT / HTTP/1.1\r\n" \
140 "Content-Length: 1\r\n" \
143 assert_nothing_raised { env = @request.read(client) }
144 assert_equal Unicorn::TeeInput, env['rack.input'].class
147 def test_rack_lint_put
148 client = MockRequest.new(
149 "PUT / HTTP/1.1\r\n" \
151 "Content-Length: 5\r\n" \
155 assert_nothing_raised { env = @request.read(client) }
156 assert ! env.include?(:http_body)
157 assert_nothing_raised { res = @lint.call(env) }
160 def test_rack_lint_big_put
163 buf = (' ' * bs).freeze
165 client = Tempfile.new('big_put')
166 def client.kgio_addr; '127.0.0.1'; end
167 def client.kgio_read(*args)
171 def client.kgio_read!(*args)
175 "PUT / HTTP/1.1\r\n" \
177 "Content-Length: #{length}\r\n" \
179 count.times { assert_equal bs, client.syswrite(buf) }
180 assert_equal 0, client.sysseek(0)
182 assert_nothing_raised { env = @request.read(client) }
183 assert ! env.include?(:http_body)
184 assert_equal length, env['rack.input'].size
186 tmp = env['rack.input'].read(bs)
187 tmp << env['rack.input'].read(bs - tmp.size) if tmp.size != bs
188 assert_equal buf, tmp
190 assert_nil env['rack.input'].read(bs)
191 assert_nothing_raised { env['rack.input'].rewind }
192 assert_nothing_raised { res = @lint.call(env) }