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 :read_nonblock, :sysread
18 @request = HttpRequest.new
19 @app = lambda do |env|
20 [ 200, { 'Content-Length' => '0', 'Content-Type' => 'text/plain' }, [] ]
22 @lint = Rack::Lint.new(@app)
26 client = MockRequest.new("OPTIONS * HTTP/1.1\r\n" \
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) }
36 def test_absolute_uri_with_query
37 client = MockRequest.new("GET http://e:3/x?y=z HTTP/1.1\r\n" \
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) }
47 def test_absolute_uri_with_fragment
48 client = MockRequest.new("GET http://e:3/x#frag HTTP/1.1\r\n" \
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) }
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" \
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) }
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" \
75 assert_raises(HttpParserError) { @request.read(client) }
79 def test_x_forwarded_proto_https
81 client = MockRequest.new("GET / HTTP/1.1\r\n" \
82 "X-Forwarded-Proto: https\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) }
89 def test_x_forwarded_proto_http
91 client = MockRequest.new("GET / HTTP/1.1\r\n" \
92 "X-Forwarded-Proto: http\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) }
99 def test_x_forwarded_proto_invalid
101 client = MockRequest.new("GET / HTTP/1.1\r\n" \
102 "X-Forwarded-Proto: ftp\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) }
109 def test_rack_lint_get
110 client = MockRequest.new("GET / HTTP/1.1\r\nHost: foo\r\n\r\n")
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) }
118 def test_no_content_stringio
119 client = MockRequest.new("GET / HTTP/1.1\r\nHost: foo\r\n\r\n")
121 assert_nothing_raised { env = @request.read(client) }
122 assert_equal StringIO, env['rack.input'].class
125 def test_zero_content_stringio
126 client = MockRequest.new("PUT / HTTP/1.1\r\n" \
127 "Content-Length: 0\r\n" \
130 assert_nothing_raised { env = @request.read(client) }
131 assert_equal StringIO, env['rack.input'].class
134 def test_real_content_not_stringio
135 client = MockRequest.new("PUT / HTTP/1.1\r\n" \
136 "Content-Length: 1\r\n" \
139 assert_nothing_raised { env = @request.read(client) }
140 assert_equal Unicorn::TeeInput, env['rack.input'].class
143 def test_rack_lint_put
144 client = MockRequest.new(
145 "PUT / HTTP/1.1\r\n" \
147 "Content-Length: 5\r\n" \
151 assert_nothing_raised { env = @request.read(client) }
152 assert ! env.include?(:http_body)
153 assert_nothing_raised { res = @lint.call(env) }
156 def test_rack_lint_big_put
159 buf = (' ' * bs).freeze
161 client = Tempfile.new('big_put')
163 "PUT / HTTP/1.1\r\n" \
165 "Content-Length: #{length}\r\n" \
167 count.times { assert_equal bs, client.syswrite(buf) }
168 assert_equal 0, client.sysseek(0)
170 assert_nothing_raised { env = @request.read(client) }
171 assert ! env.include?(:http_body)
172 assert_equal length, env['rack.input'].size
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
178 assert_nil env['rack.input'].read(bs)
179 assert_nothing_raised { env['rack.input'].rewind }
180 assert_nothing_raised { res = @lint.call(env) }