1 # Copyright (c) 2009 Eric Wong
2 # You can redistribute it and/or modify it under the same terms as Ruby.
4 require 'test/test_helper'
9 warn "Unable to load rack, skipping test"
15 class RequestTest < Test::Unit::TestCase
17 class MockRequest < StringIO
18 alias_method :readpartial, :sysread
22 @request = HttpRequest.new(Logger.new($stderr))
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_rack_lint_put
123 client = MockRequest.new(
124 "PUT / HTTP/1.1\r\n" \
126 "Content-Length: 5\r\n" \
130 assert_nothing_raised { env = @request.read(client) }
131 assert ! env.include?(:http_body)
132 assert_nothing_raised { res = @lint.call(env) }
135 def test_rack_lint_big_put
138 buf = (' ' * bs).freeze
140 client = Tempfile.new('big_put')
142 "PUT / HTTP/1.1\r\n" \
144 "Content-Length: #{length}\r\n" \
146 count.times { assert_equal bs, client.syswrite(buf) }
147 assert_equal 0, client.sysseek(0)
149 assert_nothing_raised { env = @request.read(client) }
150 assert ! env.include?(:http_body)
151 assert_equal length, env['rack.input'].size
152 count.times { assert_equal buf, env['rack.input'].read(bs) }
153 assert_nil env['rack.input'].read(bs)
154 assert_nothing_raised { env['rack.input'].rewind }
155 assert_nothing_raised { res = @lint.call(env) }