~ubuntu-branches/ubuntu/trusty/python-webob/trusty-proposed

« back to all changes in this revision

Viewing changes to tests/test_request.py

  • Committer: Package Import Robot
  • Author(s): Chuck Short
  • Date: 2013-01-07 07:52:32 UTC
  • mfrom: (1.3.5)
  • Revision ID: package-import@ubuntu.com-20130107075232-w6x8r94du3t48wj4
Tags: 1.2.3-0ubuntu1
* New upstream release:
  - Dropped debian/patches/01_lp_920197.patch: no longer needed.
  - debian/watch: Update to point to pypi.
  - debian/rules: Disable docs build.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
import unittest, warnings
2
 
from webob import Request, BaseRequest, UTC
3
 
 
4
 
_marker = object()
5
 
 
6
 
warnings.showwarning = lambda *args, **kw: None
7
 
 
8
 
class BaseRequestTests(unittest.TestCase):
9
 
    def _makeStringIO(self, text):
10
 
        try:
11
 
            from io import BytesIO
12
 
        except ImportError: # Python < 2.6
13
 
            from StringIO import StringIO as BytesIO
14
 
        return BytesIO(text)
 
1
# -*- coding: utf-8 -*-
 
2
 
 
3
import collections
 
4
import sys
 
5
import unittest
 
6
import warnings
 
7
 
 
8
from io import (
 
9
    BytesIO,
 
10
    StringIO,
 
11
    )
 
12
 
 
13
from webob.compat import (
 
14
    bytes_,
 
15
    native_,
 
16
    text_type,
 
17
    text_,
 
18
    PY3,
 
19
    )
 
20
 
 
21
class TestRequestCommon(unittest.TestCase):
 
22
    # unit tests of non-bytes-vs-text-specific methods of request object
 
23
    def _getTargetClass(self):
 
24
        from webob.request import Request
 
25
        return Request
 
26
 
 
27
    def _makeOne(self, *arg, **kw):
 
28
        cls = self._getTargetClass()
 
29
        return cls(*arg, **kw)
 
30
 
 
31
    def _blankOne(self, *arg, **kw):
 
32
        cls = self._getTargetClass()
 
33
        return cls.blank(*arg, **kw)
15
34
 
16
35
    def test_ctor_environ_getter_raises_WTF(self):
17
 
        self.assertRaises(TypeError, Request, {}, environ_getter=object())
 
36
        self.assertRaises(TypeError, self._makeOne, {}, environ_getter=object())
18
37
 
19
38
    def test_ctor_wo_environ_raises_WTF(self):
20
 
        self.assertRaises(TypeError, Request, None)
 
39
        self.assertRaises(TypeError, self._makeOne, None)
21
40
 
22
41
    def test_ctor_w_environ(self):
23
42
        environ = {}
24
 
        req = BaseRequest(environ)
 
43
        req = self._makeOne(environ)
25
44
        self.assertEqual(req.environ, environ)
26
45
 
 
46
    def test_ctor_w_non_utf8_charset(self):
 
47
        environ = {}
 
48
        self.assertRaises(DeprecationWarning, self._makeOne, environ,
 
49
                          charset='latin-1')
 
50
 
 
51
    def test_scheme(self):
 
52
        environ = {'wsgi.url_scheme': 'something:',
 
53
                  }
 
54
        req = self._makeOne(environ)
 
55
        self.assertEqual(req.scheme, 'something:')
 
56
 
27
57
    def test_body_file_getter(self):
28
 
        body = 'input'
29
 
        INPUT = self._makeStringIO(body)
 
58
        body = b'input'
 
59
        INPUT = BytesIO(body)
30
60
        environ = {'wsgi.input': INPUT,
31
61
            'CONTENT_LENGTH': len(body),
32
62
            'REQUEST_METHOD': 'POST',
33
63
        }
34
 
        req = BaseRequest(environ)
35
 
        self.assert_(req.body_file is not INPUT)
 
64
        req = self._makeOne(environ)
 
65
        self.assertTrue(req.body_file is not INPUT)
36
66
 
37
67
    def test_body_file_getter_seekable(self):
38
 
        body = 'input'
39
 
        INPUT = self._makeStringIO(body)
 
68
        body = b'input'
 
69
        INPUT = BytesIO(body)
40
70
        environ = {'wsgi.input': INPUT,
41
71
            'CONTENT_LENGTH': len(body),
42
72
            'REQUEST_METHOD': 'POST',
43
73
            'webob.is_body_seekable': True,
44
74
        }
45
 
        req = BaseRequest(environ)
46
 
        self.assert_(req.body_file is INPUT)
 
75
        req = self._makeOne(environ)
 
76
        self.assertTrue(req.body_file is INPUT)
47
77
 
48
78
    def test_body_file_getter_cache(self):
49
 
        body = 'input'
50
 
        INPUT = self._makeStringIO(body)
 
79
        body = b'input'
 
80
        INPUT = BytesIO(body)
51
81
        environ = {'wsgi.input': INPUT,
52
82
            'CONTENT_LENGTH': len(body),
53
83
            'REQUEST_METHOD': 'POST',
54
84
        }
55
 
        req = BaseRequest(environ)
56
 
        self.assert_(req.body_file is req.body_file)
 
85
        req = self._makeOne(environ)
 
86
        self.assertTrue(req.body_file is req.body_file)
57
87
 
58
88
    def test_body_file_getter_unreadable(self):
59
 
        body = 'input'
60
 
        INPUT = self._makeStringIO(body)
 
89
        body = b'input'
 
90
        INPUT = BytesIO(body)
61
91
        environ = {'wsgi.input': INPUT, 'REQUEST_METHOD': 'FOO'}
62
 
        req = BaseRequest(environ)
 
92
        req = self._makeOne(environ)
63
93
        assert req.body_file_raw is INPUT
64
94
        assert req.body_file is not INPUT
65
 
        assert req.body_file.read() == ''
66
 
 
67
 
    def test_body_file_setter_w_string(self):
68
 
        BEFORE = self._makeStringIO('before')
69
 
        AFTER = str('AFTER')
70
 
        environ = {'wsgi.input': BEFORE,
71
 
                   'CONTENT_LENGTH': len('before'),
72
 
                   'REQUEST_METHOD': 'POST',
73
 
                  }
74
 
        req = BaseRequest(environ)
75
 
        warnings.simplefilter('ignore', PendingDeprecationWarning)
76
 
        req.body_file = AFTER
77
 
        warnings.resetwarnings()
78
 
        self.assertEqual(req.content_length, len(AFTER))
79
 
        self.assertEqual(req.body_file.read(), AFTER)
80
 
        del req.body_file
81
 
        self.assertEqual(req.content_length, 0)
82
 
        assert req.is_body_seekable
83
 
        req.body_file.seek(0)
84
 
        self.assertEqual(req.body_file.read(), '')
85
 
 
86
 
    def test_body_file_setter_non_string(self):
87
 
        BEFORE = self._makeStringIO('before')
88
 
        AFTER =  self._makeStringIO('after')
 
95
        assert req.body_file.read() == b''
 
96
 
 
97
    def test_body_file_setter_w_bytes(self):
 
98
        req = self._blankOne('/')
 
99
        self.assertRaises(DeprecationWarning, setattr, req, 'body_file', b'foo')
 
100
 
 
101
    def test_body_file_setter_non_bytes(self):
 
102
        BEFORE = BytesIO(b'before')
 
103
        AFTER =  BytesIO(b'after')
89
104
        environ = {'wsgi.input': BEFORE,
90
105
                   'CONTENT_LENGTH': len('before'),
91
106
                   'REQUEST_METHOD': 'POST'
92
107
                  }
93
 
        req = BaseRequest(environ)
 
108
        req = self._makeOne(environ)
94
109
        req.body_file = AFTER
95
 
        self.assert_(req.body_file is AFTER)
 
110
        self.assertTrue(req.body_file is AFTER)
96
111
        self.assertEqual(req.content_length, None)
97
112
 
98
113
    def test_body_file_deleter(self):
99
 
        INPUT = self._makeStringIO('before')
 
114
        body = b'input'
 
115
        INPUT = BytesIO(body)
100
116
        environ = {'wsgi.input': INPUT,
101
 
                   'CONTENT_LENGTH': len('before'),
 
117
                   'CONTENT_LENGTH': len(body),
102
118
                   'REQUEST_METHOD': 'POST',
103
119
                  }
104
 
        req = BaseRequest(environ)
 
120
        req = self._makeOne(environ)
105
121
        del req.body_file
106
 
        self.assertEqual(req.body_file.getvalue(), '')
 
122
        self.assertEqual(req.body_file.getvalue(), b'')
107
123
        self.assertEqual(req.content_length, 0)
108
124
 
109
125
    def test_body_file_raw(self):
110
 
        INPUT = self._makeStringIO('input')
 
126
        INPUT = BytesIO(b'input')
111
127
        environ = {'wsgi.input': INPUT,
112
128
                   'CONTENT_LENGTH': len('input'),
113
129
                   'REQUEST_METHOD': 'POST',
114
130
                  }
115
 
        req = BaseRequest(environ)
116
 
        self.assert_(req.body_file_raw is INPUT)
 
131
        req = self._makeOne(environ)
 
132
        self.assertTrue(req.body_file_raw is INPUT)
117
133
 
118
134
    def test_body_file_seekable_input_not_seekable(self):
119
 
        INPUT = self._makeStringIO('input')
 
135
        data = b'input'
 
136
        INPUT = BytesIO(data)
120
137
        INPUT.seek(1, 0) # consume
121
138
        environ = {'wsgi.input': INPUT,
122
139
                   'webob.is_body_seekable': False,
123
 
                   'CONTENT_LENGTH': len('input')-1,
 
140
                   'CONTENT_LENGTH': len(data)-1,
124
141
                   'REQUEST_METHOD': 'POST',
125
142
                  }
126
 
        req = BaseRequest(environ)
 
143
        req = self._makeOne(environ)
127
144
        seekable = req.body_file_seekable
128
 
        self.assert_(seekable is not INPUT)
129
 
        self.assertEqual(seekable.getvalue(), 'nput')
 
145
        self.assertTrue(seekable is not INPUT)
 
146
        self.assertEqual(seekable.getvalue(), b'nput')
130
147
 
131
148
    def test_body_file_seekable_input_is_seekable(self):
132
 
        INPUT = self._makeStringIO('input')
 
149
        INPUT = BytesIO(b'input')
133
150
        INPUT.seek(1, 0) # consume
134
151
        environ = {'wsgi.input': INPUT,
135
152
                   'webob.is_body_seekable': True,
136
153
                   'CONTENT_LENGTH': len('input')-1,
137
154
                   'REQUEST_METHOD': 'POST',
138
155
                  }
139
 
        req = BaseRequest(environ)
 
156
        req = self._makeOne(environ)
140
157
        seekable = req.body_file_seekable
141
 
        self.assert_(seekable is INPUT)
142
 
 
143
 
    def test_scheme(self):
144
 
        environ = {'wsgi.url_scheme': 'something:',
145
 
                  }
146
 
        req = BaseRequest(environ)
147
 
        self.assertEqual(req.scheme, 'something:')
148
 
 
149
 
    def test_method(self):
150
 
        environ = {'REQUEST_METHOD': 'OPTIONS',
151
 
                  }
152
 
        req = BaseRequest(environ)
153
 
        self.assertEqual(req.method, 'OPTIONS')
154
 
 
155
 
    def test_http_version(self):
156
 
        environ = {'SERVER_PROTOCOL': '1.1',
157
 
                  }
158
 
        req = BaseRequest(environ)
159
 
        self.assertEqual(req.http_version, '1.1')
160
 
 
161
 
    def test_script_name(self):
162
 
        environ = {'SCRIPT_NAME': '/script',
163
 
                  }
164
 
        req = BaseRequest(environ)
165
 
        self.assertEqual(req.script_name, '/script')
166
 
 
167
 
    def test_path_info(self):
168
 
        environ = {'PATH_INFO': '/path/info',
169
 
                  }
170
 
        req = BaseRequest(environ)
171
 
        self.assertEqual(req.path_info, '/path/info')
172
 
 
173
 
    def test_content_length_getter(self):
174
 
        environ = {'CONTENT_LENGTH': '1234',
175
 
                  }
176
 
        req = BaseRequest(environ)
177
 
        self.assertEqual(req.content_length, 1234)
178
 
 
179
 
    def test_content_length_setter_w_str(self):
180
 
        environ = {'CONTENT_LENGTH': '1234',
181
 
                  }
182
 
        req = BaseRequest(environ)
183
 
        req.content_length = '3456'
184
 
        self.assertEqual(req.content_length, 3456)
185
 
 
186
 
    def test_remote_user(self):
187
 
        environ = {'REMOTE_USER': 'phred',
188
 
                  }
189
 
        req = BaseRequest(environ)
190
 
        self.assertEqual(req.remote_user, 'phred')
191
 
 
192
 
    def test_remote_addr(self):
193
 
        environ = {'REMOTE_ADDR': '1.2.3.4',
194
 
                  }
195
 
        req = BaseRequest(environ)
196
 
        self.assertEqual(req.remote_addr, '1.2.3.4')
197
 
 
198
 
    def test_query_string(self):
199
 
        environ = {'QUERY_STRING': 'foo=bar&baz=bam',
200
 
                  }
201
 
        req = BaseRequest(environ)
202
 
        self.assertEqual(req.query_string, 'foo=bar&baz=bam')
203
 
 
204
 
    def test_server_name(self):
205
 
        environ = {'SERVER_NAME': 'somehost.tld',
206
 
                  }
207
 
        req = BaseRequest(environ)
208
 
        self.assertEqual(req.server_name, 'somehost.tld')
209
 
 
210
 
    def test_server_port_getter(self):
211
 
        environ = {'SERVER_PORT': '6666',
212
 
                  }
213
 
        req = BaseRequest(environ)
214
 
        self.assertEqual(req.server_port, 6666)
215
 
 
216
 
    def test_server_port_setter_with_string(self):
217
 
        environ = {'SERVER_PORT': '6666',
218
 
                  }
219
 
        req = BaseRequest(environ)
220
 
        req.server_port = '6667'
221
 
        self.assertEqual(req.server_port, 6667)
222
 
 
223
 
    def test_uscript_name(self):
224
 
        environ = {'SCRIPT_NAME': '/script',
225
 
                  }
226
 
        req = BaseRequest(environ)
227
 
        self.assert_(isinstance(req.uscript_name, unicode))
228
 
        self.assertEqual(req.uscript_name, '/script')
229
 
 
230
 
    def test_upath_info(self):
231
 
        environ = {'PATH_INFO': '/path/info',
232
 
                  }
233
 
        req = BaseRequest(environ)
234
 
        self.assert_(isinstance(req.upath_info, unicode))
235
 
        self.assertEqual(req.upath_info, '/path/info')
236
 
 
237
 
    def test_content_type_getter_no_parameters(self):
238
 
        environ = {'CONTENT_TYPE': 'application/xml+foobar',
239
 
                  }
240
 
        req = BaseRequest(environ)
241
 
        self.assertEqual(req.content_type, 'application/xml+foobar')
242
 
 
243
 
    def test_content_type_getter_w_parameters(self):
244
 
        environ = {'CONTENT_TYPE': 'application/xml+foobar;charset="utf8"',
245
 
                  }
246
 
        req = BaseRequest(environ)
247
 
        self.assertEqual(req.content_type, 'application/xml+foobar')
248
 
 
249
 
    def test_content_type_setter_w_None(self):
250
 
        environ = {'CONTENT_TYPE': 'application/xml+foobar;charset="utf8"',
251
 
                  }
252
 
        req = BaseRequest(environ)
253
 
        req.content_type = None
254
 
        self.assertEqual(req.content_type, '')
255
 
        self.assert_('CONTENT_TYPE' not in environ)
256
 
 
257
 
    def test_content_type_setter_existing_paramter_no_new_paramter(self):
258
 
        environ = {'CONTENT_TYPE': 'application/xml+foobar;charset="utf8"',
259
 
                  }
260
 
        req = BaseRequest(environ)
261
 
        req.content_type = 'text/xml'
262
 
        self.assertEqual(req.content_type, 'text/xml')
263
 
        self.assertEqual(environ['CONTENT_TYPE'], 'text/xml;charset="utf8"')
264
 
 
265
 
    def test_content_type_deleter_clears_environ_value(self):
266
 
        environ = {'CONTENT_TYPE': 'application/xml+foobar;charset="utf8"',
267
 
                  }
268
 
        req = BaseRequest(environ)
269
 
        del req.content_type
270
 
        self.assertEqual(req.content_type, '')
271
 
        self.assert_('CONTENT_TYPE' not in environ)
272
 
 
273
 
    def test_content_type_deleter_no_environ_value(self):
274
 
        environ = {}
275
 
        req = BaseRequest(environ)
276
 
        del req.content_type
277
 
        self.assertEqual(req.content_type, '')
278
 
        self.assert_('CONTENT_TYPE' not in environ)
279
 
 
280
 
    def test_charset_getter_cache_hit(self):
281
 
        CT = 'application/xml+foobar'
282
 
        environ = {'CONTENT_TYPE': CT,
283
 
                  }
284
 
        req = BaseRequest(environ)
285
 
        req._charset_cache = (CT, 'cp1252')
286
 
        self.assertEqual(req.charset, 'cp1252')
287
 
 
288
 
    def test_charset_getter_cache_miss_w_parameter(self):
289
 
        CT = 'application/xml+foobar;charset="utf8"'
290
 
        environ = {'CONTENT_TYPE': CT,
291
 
                  }
292
 
        req = BaseRequest(environ)
293
 
        self.assertEqual(req.charset, 'utf8')
294
 
        self.assertEqual(req._charset_cache, (CT, 'utf8'))
295
 
 
296
 
    def test_charset_getter_cache_miss_wo_parameter(self):
297
 
        CT = 'application/xml+foobar'
298
 
        environ = {'CONTENT_TYPE': CT,
299
 
                  }
300
 
        req = BaseRequest(environ)
301
 
        self.assertEqual(req.charset, 'UTF-8')
302
 
        self.assertEqual(req._charset_cache, (CT, 'UTF-8'))
303
 
 
304
 
    def test_charset_setter_None_w_parameter(self):
305
 
        CT = 'application/xml+foobar;charset="utf8"'
306
 
        environ = {'CONTENT_TYPE': CT,
307
 
                  }
308
 
        req = BaseRequest(environ)
309
 
        req.charset = None
310
 
        self.assertEqual(environ['CONTENT_TYPE'], 'application/xml+foobar')
311
 
        self.assertEqual(req.charset, 'UTF-8')
312
 
 
313
 
    def test_charset_setter_empty_w_parameter(self):
314
 
        CT = 'application/xml+foobar;charset="utf8"'
315
 
        environ = {'CONTENT_TYPE': CT,
316
 
                  }
317
 
        req = BaseRequest(environ)
318
 
        req.charset = ''
319
 
        self.assertEqual(environ['CONTENT_TYPE'], 'application/xml+foobar')
320
 
        self.assertEqual(req.charset, 'UTF-8')
321
 
 
322
 
    def test_charset_setter_nonempty_w_parameter(self):
323
 
        CT = 'application/xml+foobar;charset="utf8"'
324
 
        environ = {'CONTENT_TYPE': CT,
325
 
                  }
326
 
        req = BaseRequest(environ)
327
 
        req.charset = 'cp1252'
328
 
        self.assertEqual(environ['CONTENT_TYPE'],
329
 
                         #'application/xml+foobar; charset="cp1252"') WTF?
330
 
                         'application/xml+foobar;charset=cp1252',
331
 
                         )
332
 
        self.assertEqual(req.charset, 'cp1252')
333
 
 
334
 
    def test_charset_setter_nonempty_wo_parameter(self):
335
 
        CT = 'application/xml+foobar'
336
 
        environ = {'CONTENT_TYPE': CT,
337
 
                  }
338
 
        req = BaseRequest(environ)
339
 
        req.charset = 'cp1252'
340
 
        self.assertEqual(environ['CONTENT_TYPE'],
341
 
                         'application/xml+foobar; charset="cp1252"',
342
 
                         #'application/xml+foobar;charset=cp1252',  WTF?
343
 
                         )
344
 
        self.assertEqual(req.charset, 'cp1252')
345
 
 
346
 
    def test_charset_deleter_w_parameter(self):
347
 
        CT = 'application/xml+foobar;charset="utf8"'
348
 
        environ = {'CONTENT_TYPE': CT,
349
 
                  }
350
 
        req = BaseRequest(environ)
351
 
        del req.charset
352
 
        self.assertEqual(environ['CONTENT_TYPE'], 'application/xml+foobar')
353
 
        self.assertEqual(req.charset, 'UTF-8')
354
 
 
355
 
    def test_headers_getter_miss(self):
356
 
        CONTENT_TYPE = 'application/xml+foobar;charset="utf8"'
357
 
        environ = {'CONTENT_TYPE': CONTENT_TYPE,
358
 
                   'CONTENT_LENGTH': '123',
359
 
                  }
360
 
        req = BaseRequest(environ)
361
 
        headers = req.headers
362
 
        self.assertEqual(headers,
363
 
                        {'Content-Type': CONTENT_TYPE,
364
 
                         'Content-Length': '123'})
365
 
        self.assertEqual(req._headers, headers)
366
 
 
367
 
    def test_headers_getter_hit(self):
368
 
        CONTENT_TYPE = 'application/xml+foobar;charset="utf8"'
369
 
        environ = {'CONTENT_TYPE': CONTENT_TYPE,
370
 
                   'CONTENT_LENGTH': '123',
371
 
                  }
372
 
        req = BaseRequest(environ)
373
 
        req._headers = {'Foo': 'Bar'}
374
 
        self.assertEqual(req.headers,
375
 
                        {'Foo': 'Bar'})
376
 
 
377
 
    def test_headers_setter(self):
378
 
        CONTENT_TYPE = 'application/xml+foobar;charset="utf8"'
379
 
        environ = {'CONTENT_TYPE': CONTENT_TYPE,
380
 
                   'CONTENT_LENGTH': '123',
381
 
                  }
382
 
        req = BaseRequest(environ)
383
 
        req._headers = {'Foo': 'Bar'}
384
 
        req.headers = {'Qux': 'Spam'}
385
 
        self.assertEqual(req.headers,
386
 
                        {'Qux': 'Spam'})
387
 
 
388
 
    def test_no_headers_deleter(self):
389
 
        CONTENT_TYPE = 'application/xml+foobar;charset="utf8"'
390
 
        environ = {'CONTENT_TYPE': CONTENT_TYPE,
391
 
                   'CONTENT_LENGTH': '123',
392
 
                  }
393
 
        req = BaseRequest(environ)
394
 
        def _test():
395
 
            del req.headers
396
 
        self.assertRaises(AttributeError, _test)
397
 
 
398
 
    def test_host_url_w_http_host_and_no_port(self):
399
 
        environ = {'wsgi.url_scheme': 'http',
400
 
                   'HTTP_HOST': 'example.com',
401
 
                  }
402
 
        req = BaseRequest(environ)
403
 
        self.assertEqual(req.host_url, 'http://example.com')
404
 
 
405
 
    def test_host_url_w_http_host_and_standard_port(self):
406
 
        environ = {'wsgi.url_scheme': 'http',
407
 
                   'HTTP_HOST': 'example.com:80',
408
 
                  }
409
 
        req = BaseRequest(environ)
410
 
        self.assertEqual(req.host_url, 'http://example.com')
411
 
 
412
 
    def test_host_url_w_http_host_and_oddball_port(self):
413
 
        environ = {'wsgi.url_scheme': 'http',
414
 
                   'HTTP_HOST': 'example.com:8888',
415
 
                  }
416
 
        req = BaseRequest(environ)
417
 
        self.assertEqual(req.host_url, 'http://example.com:8888')
418
 
 
419
 
    def test_host_url_w_http_host_https_and_no_port(self):
420
 
        environ = {'wsgi.url_scheme': 'https',
421
 
                   'HTTP_HOST': 'example.com',
422
 
                  }
423
 
        req = BaseRequest(environ)
424
 
        self.assertEqual(req.host_url, 'https://example.com')
425
 
 
426
 
    def test_host_url_w_http_host_https_and_standard_port(self):
427
 
        environ = {'wsgi.url_scheme': 'https',
428
 
                   'HTTP_HOST': 'example.com:443',
429
 
                  }
430
 
        req = BaseRequest(environ)
431
 
        self.assertEqual(req.host_url, 'https://example.com')
432
 
 
433
 
    def test_host_url_w_http_host_https_and_oddball_port(self):
434
 
        environ = {'wsgi.url_scheme': 'https',
435
 
                   'HTTP_HOST': 'example.com:4333',
436
 
                  }
437
 
        req = BaseRequest(environ)
438
 
        self.assertEqual(req.host_url, 'https://example.com:4333')
439
 
 
440
 
    def test_host_url_wo_http_host(self):
441
 
        environ = {'wsgi.url_scheme': 'https',
442
 
                   'SERVER_NAME': 'example.com',
443
 
                   'SERVER_PORT': '4333',
444
 
                  }
445
 
        req = BaseRequest(environ)
446
 
        self.assertEqual(req.host_url, 'https://example.com:4333')
447
 
 
448
 
    def test_application_url(self):
449
 
        environ = {'wsgi.url_scheme': 'http',
450
 
                   'SERVER_NAME': 'example.com',
451
 
                   'SERVER_PORT': '80',
452
 
                   'SCRIPT_NAME': '/script',
453
 
                  }
454
 
        req = BaseRequest(environ)
455
 
        self.assertEqual(req.application_url, 'http://example.com/script')
456
 
 
457
 
    def test_path_url(self):
458
 
        environ = {'wsgi.url_scheme': 'http',
459
 
                   'SERVER_NAME': 'example.com',
460
 
                   'SERVER_PORT': '80',
461
 
                   'SCRIPT_NAME': '/script',
462
 
                   'PATH_INFO': '/path/info',
463
 
                  }
464
 
        req = BaseRequest(environ)
465
 
        self.assertEqual(req.path_url, 'http://example.com/script/path/info')
466
 
 
467
 
    def test_path(self):
468
 
        environ = {'wsgi.url_scheme': 'http',
469
 
                   'SERVER_NAME': 'example.com',
470
 
                   'SERVER_PORT': '80',
471
 
                   'SCRIPT_NAME': '/script',
472
 
                   'PATH_INFO': '/path/info',
473
 
                  }
474
 
        req = BaseRequest(environ)
475
 
        self.assertEqual(req.path, '/script/path/info')
476
 
 
477
 
    def test_path_qs_no_qs(self):
478
 
        environ = {'wsgi.url_scheme': 'http',
479
 
                   'SERVER_NAME': 'example.com',
480
 
                   'SERVER_PORT': '80',
481
 
                   'SCRIPT_NAME': '/script',
482
 
                   'PATH_INFO': '/path/info',
483
 
                  }
484
 
        req = BaseRequest(environ)
485
 
        self.assertEqual(req.path_qs, '/script/path/info')
486
 
 
487
 
    def test_path_qs_w_qs(self):
488
 
        environ = {'wsgi.url_scheme': 'http',
489
 
                   'SERVER_NAME': 'example.com',
490
 
                   'SERVER_PORT': '80',
491
 
                   'SCRIPT_NAME': '/script',
492
 
                   'PATH_INFO': '/path/info',
493
 
                   'QUERY_STRING': 'foo=bar&baz=bam'
494
 
                  }
495
 
        req = BaseRequest(environ)
496
 
        self.assertEqual(req.path_qs, '/script/path/info?foo=bar&baz=bam')
497
 
 
498
 
    def test_url_no_qs(self):
499
 
        environ = {'wsgi.url_scheme': 'http',
500
 
                   'SERVER_NAME': 'example.com',
501
 
                   'SERVER_PORT': '80',
502
 
                   'SCRIPT_NAME': '/script',
503
 
                   'PATH_INFO': '/path/info',
504
 
                  }
505
 
        req = BaseRequest(environ)
506
 
        self.assertEqual(req.url, 'http://example.com/script/path/info')
507
 
 
508
 
    def test_url_w_qs(self):
509
 
        environ = {'wsgi.url_scheme': 'http',
510
 
                   'SERVER_NAME': 'example.com',
511
 
                   'SERVER_PORT': '80',
512
 
                   'SCRIPT_NAME': '/script',
513
 
                   'PATH_INFO': '/path/info',
514
 
                   'QUERY_STRING': 'foo=bar&baz=bam'
515
 
                  }
516
 
        req = BaseRequest(environ)
517
 
        self.assertEqual(req.url,
518
 
                         'http://example.com/script/path/info?foo=bar&baz=bam')
519
 
 
520
 
    def test_relative_url_to_app_true_wo_leading_slash(self):
521
 
        environ = {'wsgi.url_scheme': 'http',
522
 
                   'SERVER_NAME': 'example.com',
523
 
                   'SERVER_PORT': '80',
524
 
                   'SCRIPT_NAME': '/script',
525
 
                   'PATH_INFO': '/path/info',
526
 
                   'QUERY_STRING': 'foo=bar&baz=bam'
527
 
                  }
528
 
        req = BaseRequest(environ)
529
 
        self.assertEqual(req.relative_url('other/page', True),
530
 
                         'http://example.com/script/other/page')
531
 
 
532
 
    def test_relative_url_to_app_true_w_leading_slash(self):
533
 
        environ = {'wsgi.url_scheme': 'http',
534
 
                   'SERVER_NAME': 'example.com',
535
 
                   'SERVER_PORT': '80',
536
 
                   'SCRIPT_NAME': '/script',
537
 
                   'PATH_INFO': '/path/info',
538
 
                   'QUERY_STRING': 'foo=bar&baz=bam'
539
 
                  }
540
 
        req = BaseRequest(environ)
541
 
        self.assertEqual(req.relative_url('/other/page', True),
542
 
                         'http://example.com/other/page')
543
 
 
544
 
    def test_relative_url_to_app_false_other_w_leading_slash(self):
545
 
        environ = {'wsgi.url_scheme': 'http',
546
 
                   'SERVER_NAME': 'example.com',
547
 
                   'SERVER_PORT': '80',
548
 
                   'SCRIPT_NAME': '/script',
549
 
                   'PATH_INFO': '/path/info',
550
 
                   'QUERY_STRING': 'foo=bar&baz=bam'
551
 
                  }
552
 
        req = BaseRequest(environ)
553
 
        self.assertEqual(req.relative_url('/other/page', False),
554
 
                         'http://example.com/other/page')
555
 
 
556
 
    def test_relative_url_to_app_false_other_wo_leading_slash(self):
557
 
        environ = {'wsgi.url_scheme': 'http',
558
 
                   'SERVER_NAME': 'example.com',
559
 
                   'SERVER_PORT': '80',
560
 
                   'SCRIPT_NAME': '/script',
561
 
                   'PATH_INFO': '/path/info',
562
 
                   'QUERY_STRING': 'foo=bar&baz=bam'
563
 
                  }
564
 
        req = BaseRequest(environ)
565
 
        self.assertEqual(req.relative_url('other/page', False),
566
 
                         'http://example.com/script/path/other/page')
567
 
 
568
 
    def test_path_info_pop_empty(self):
569
 
        environ = {'wsgi.url_scheme': 'http',
570
 
                   'SERVER_NAME': 'example.com',
571
 
                   'SERVER_PORT': '80',
572
 
                   'SCRIPT_NAME': '/script',
573
 
                   'PATH_INFO': '',
574
 
                  }
575
 
        req = BaseRequest(environ)
576
 
        popped = req.path_info_pop()
577
 
        self.assertEqual(popped, None)
578
 
        self.assertEqual(environ['SCRIPT_NAME'], '/script')
579
 
 
580
 
    def test_path_info_pop_just_leading_slash(self):
581
 
        environ = {'wsgi.url_scheme': 'http',
582
 
                   'SERVER_NAME': 'example.com',
583
 
                   'SERVER_PORT': '80',
584
 
                   'SCRIPT_NAME': '/script',
585
 
                   'PATH_INFO': '/',
586
 
                  }
587
 
        req = BaseRequest(environ)
588
 
        popped = req.path_info_pop()
589
 
        self.assertEqual(popped, '')
590
 
        self.assertEqual(environ['SCRIPT_NAME'], '/script/')
591
 
        self.assertEqual(environ['PATH_INFO'], '')
592
 
 
593
 
    def test_path_info_pop_non_empty_no_pattern(self):
594
 
        environ = {'wsgi.url_scheme': 'http',
595
 
                   'SERVER_NAME': 'example.com',
596
 
                   'SERVER_PORT': '80',
597
 
                   'SCRIPT_NAME': '/script',
598
 
                   'PATH_INFO': '/path/info',
599
 
                  }
600
 
        req = BaseRequest(environ)
601
 
        popped = req.path_info_pop()
602
 
        self.assertEqual(popped, 'path')
603
 
        self.assertEqual(environ['SCRIPT_NAME'], '/script/path')
604
 
        self.assertEqual(environ['PATH_INFO'], '/info')
605
 
 
606
 
    def test_path_info_pop_non_empty_w_pattern_miss(self):
607
 
        import re
608
 
        PATTERN = re.compile('miss')
609
 
        environ = {'wsgi.url_scheme': 'http',
610
 
                   'SERVER_NAME': 'example.com',
611
 
                   'SERVER_PORT': '80',
612
 
                   'SCRIPT_NAME': '/script',
613
 
                   'PATH_INFO': '/path/info',
614
 
                  }
615
 
        req = BaseRequest(environ)
616
 
        popped = req.path_info_pop(PATTERN)
617
 
        self.assertEqual(popped, None)
618
 
        self.assertEqual(environ['SCRIPT_NAME'], '/script')
619
 
        self.assertEqual(environ['PATH_INFO'], '/path/info')
620
 
 
621
 
    def test_path_info_pop_non_empty_w_pattern_hit(self):
622
 
        import re
623
 
        PATTERN = re.compile('path')
624
 
        environ = {'wsgi.url_scheme': 'http',
625
 
                   'SERVER_NAME': 'example.com',
626
 
                   'SERVER_PORT': '80',
627
 
                   'SCRIPT_NAME': '/script',
628
 
                   'PATH_INFO': '/path/info',
629
 
                  }
630
 
        req = BaseRequest(environ)
631
 
        popped = req.path_info_pop(PATTERN)
632
 
        self.assertEqual(popped, 'path')
633
 
        self.assertEqual(environ['SCRIPT_NAME'], '/script/path')
634
 
        self.assertEqual(environ['PATH_INFO'], '/info')
635
 
 
636
 
    def test_path_info_pop_skips_empty_elements(self):
637
 
        environ = {'wsgi.url_scheme': 'http',
638
 
                   'SERVER_NAME': 'example.com',
639
 
                   'SERVER_PORT': '80',
640
 
                   'SCRIPT_NAME': '/script',
641
 
                   'PATH_INFO': '//path/info',
642
 
                  }
643
 
        req = BaseRequest(environ)
644
 
        popped = req.path_info_pop()
645
 
        self.assertEqual(popped, 'path')
646
 
        self.assertEqual(environ['SCRIPT_NAME'], '/script//path')
647
 
        self.assertEqual(environ['PATH_INFO'], '/info')
648
 
 
649
 
    def test_path_info_peek_empty(self):
650
 
        environ = {'wsgi.url_scheme': 'http',
651
 
                   'SERVER_NAME': 'example.com',
652
 
                   'SERVER_PORT': '80',
653
 
                   'SCRIPT_NAME': '/script',
654
 
                   'PATH_INFO': '',
655
 
                  }
656
 
        req = BaseRequest(environ)
657
 
        peeked = req.path_info_peek()
658
 
        self.assertEqual(peeked, None)
659
 
        self.assertEqual(environ['SCRIPT_NAME'], '/script')
660
 
        self.assertEqual(environ['PATH_INFO'], '')
661
 
 
662
 
    def test_path_info_peek_just_leading_slash(self):
663
 
        environ = {'wsgi.url_scheme': 'http',
664
 
                   'SERVER_NAME': 'example.com',
665
 
                   'SERVER_PORT': '80',
666
 
                   'SCRIPT_NAME': '/script',
667
 
                   'PATH_INFO': '/',
668
 
                  }
669
 
        req = BaseRequest(environ)
670
 
        peeked = req.path_info_peek()
671
 
        self.assertEqual(peeked, '')
672
 
        self.assertEqual(environ['SCRIPT_NAME'], '/script')
673
 
        self.assertEqual(environ['PATH_INFO'], '/')
674
 
 
675
 
    def test_path_info_peek_non_empty(self):
676
 
        environ = {'wsgi.url_scheme': 'http',
677
 
                   'SERVER_NAME': 'example.com',
678
 
                   'SERVER_PORT': '80',
679
 
                   'SCRIPT_NAME': '/script',
680
 
                   'PATH_INFO': '/path',
681
 
                  }
682
 
        req = BaseRequest(environ)
683
 
        peeked = req.path_info_peek()
684
 
        self.assertEqual(peeked, 'path')
685
 
        self.assertEqual(environ['SCRIPT_NAME'], '/script')
686
 
        self.assertEqual(environ['PATH_INFO'], '/path')
 
158
        self.assertTrue(seekable is INPUT)
687
159
 
688
160
    def test_urlvars_getter_w_paste_key(self):
689
161
        environ = {'paste.urlvars': {'foo': 'bar'},
690
162
                  }
691
 
        req = BaseRequest(environ)
 
163
        req = self._makeOne(environ)
692
164
        self.assertEqual(req.urlvars, {'foo': 'bar'})
693
165
 
694
166
    def test_urlvars_getter_w_wsgiorg_key(self):
695
167
        environ = {'wsgiorg.routing_args': ((), {'foo': 'bar'}),
696
168
                  }
697
 
        req = BaseRequest(environ)
 
169
        req = self._makeOne(environ)
698
170
        self.assertEqual(req.urlvars, {'foo': 'bar'})
699
171
 
700
172
    def test_urlvars_getter_wo_keys(self):
701
173
        environ = {}
702
 
        req = BaseRequest(environ)
 
174
        req = self._makeOne(environ)
703
175
        self.assertEqual(req.urlvars, {})
704
176
        self.assertEqual(environ['wsgiorg.routing_args'], ((), {}))
705
177
 
706
178
    def test_urlvars_setter_w_paste_key(self):
707
179
        environ = {'paste.urlvars': {'foo': 'bar'},
708
180
                  }
709
 
        req = BaseRequest(environ)
 
181
        req = self._makeOne(environ)
710
182
        req.urlvars = {'baz': 'bam'}
711
183
        self.assertEqual(req.urlvars, {'baz': 'bam'})
712
184
        self.assertEqual(environ['paste.urlvars'], {'baz': 'bam'})
713
 
        self.assert_('wsgiorg.routing_args' not in environ)
 
185
        self.assertTrue('wsgiorg.routing_args' not in environ)
714
186
 
715
187
    def test_urlvars_setter_w_wsgiorg_key(self):
716
188
        environ = {'wsgiorg.routing_args': ((), {'foo': 'bar'}),
717
189
                   'paste.urlvars': {'qux': 'spam'},
718
190
                  }
719
 
        req = BaseRequest(environ)
 
191
        req = self._makeOne(environ)
720
192
        req.urlvars = {'baz': 'bam'}
721
193
        self.assertEqual(req.urlvars, {'baz': 'bam'})
722
194
        self.assertEqual(environ['wsgiorg.routing_args'], ((), {'baz': 'bam'}))
723
 
        self.assert_('paste.urlvars' not in environ)
 
195
        self.assertTrue('paste.urlvars' not in environ)
724
196
 
725
197
    def test_urlvars_setter_wo_keys(self):
726
198
        environ = {}
727
 
        req = BaseRequest(environ)
 
199
        req = self._makeOne(environ)
728
200
        req.urlvars = {'baz': 'bam'}
729
201
        self.assertEqual(req.urlvars, {'baz': 'bam'})
730
202
        self.assertEqual(environ['wsgiorg.routing_args'], ((), {'baz': 'bam'}))
731
 
        self.assert_('paste.urlvars' not in environ)
 
203
        self.assertTrue('paste.urlvars' not in environ)
732
204
 
733
205
    def test_urlvars_deleter_w_paste_key(self):
734
206
        environ = {'paste.urlvars': {'foo': 'bar'},
735
207
                  }
736
 
        req = BaseRequest(environ)
 
208
        req = self._makeOne(environ)
737
209
        del req.urlvars
738
210
        self.assertEqual(req.urlvars, {})
739
 
        self.assert_('paste.urlvars' not in environ)
 
211
        self.assertTrue('paste.urlvars' not in environ)
740
212
        self.assertEqual(environ['wsgiorg.routing_args'], ((), {}))
741
213
 
742
214
    def test_urlvars_deleter_w_wsgiorg_key_non_empty_tuple(self):
743
215
        environ = {'wsgiorg.routing_args': (('a', 'b'), {'foo': 'bar'}),
744
216
                   'paste.urlvars': {'qux': 'spam'},
745
217
                  }
746
 
        req = BaseRequest(environ)
 
218
        req = self._makeOne(environ)
747
219
        del req.urlvars
748
220
        self.assertEqual(req.urlvars, {})
749
221
        self.assertEqual(environ['wsgiorg.routing_args'], (('a', 'b'), {}))
750
 
        self.assert_('paste.urlvars' not in environ)
 
222
        self.assertTrue('paste.urlvars' not in environ)
751
223
 
752
224
    def test_urlvars_deleter_w_wsgiorg_key_empty_tuple(self):
753
225
        environ = {'wsgiorg.routing_args': ((), {'foo': 'bar'}),
754
226
                   'paste.urlvars': {'qux': 'spam'},
755
227
                  }
756
 
        req = BaseRequest(environ)
 
228
        req = self._makeOne(environ)
757
229
        del req.urlvars
758
230
        self.assertEqual(req.urlvars, {})
759
231
        self.assertEqual(environ['wsgiorg.routing_args'], ((), {}))
760
 
        self.assert_('paste.urlvars' not in environ)
 
232
        self.assertTrue('paste.urlvars' not in environ)
761
233
 
762
234
    def test_urlvars_deleter_wo_keys(self):
763
235
        environ = {}
764
 
        req = BaseRequest(environ)
 
236
        req = self._makeOne(environ)
765
237
        del req.urlvars
766
238
        self.assertEqual(req.urlvars, {})
767
239
        self.assertEqual(environ['wsgiorg.routing_args'], ((), {}))
768
 
        self.assert_('paste.urlvars' not in environ)
 
240
        self.assertTrue('paste.urlvars' not in environ)
769
241
 
770
242
    def test_urlargs_getter_w_paste_key(self):
771
243
        environ = {'paste.urlvars': {'foo': 'bar'},
772
244
                  }
773
 
        req = BaseRequest(environ)
 
245
        req = self._makeOne(environ)
774
246
        self.assertEqual(req.urlargs, ())
775
247
 
776
248
    def test_urlargs_getter_w_wsgiorg_key(self):
777
249
        environ = {'wsgiorg.routing_args': (('a', 'b'), {'foo': 'bar'}),
778
250
                  }
779
 
        req = BaseRequest(environ)
 
251
        req = self._makeOne(environ)
780
252
        self.assertEqual(req.urlargs, ('a', 'b'))
781
253
 
782
254
    def test_urlargs_getter_wo_keys(self):
783
255
        environ = {}
784
 
        req = BaseRequest(environ)
 
256
        req = self._makeOne(environ)
785
257
        self.assertEqual(req.urlargs, ())
786
 
        self.assert_('wsgiorg.routing_args' not in environ)
 
258
        self.assertTrue('wsgiorg.routing_args' not in environ)
787
259
 
788
260
    def test_urlargs_setter_w_paste_key(self):
789
261
        environ = {'paste.urlvars': {'foo': 'bar'},
790
262
                  }
791
 
        req = BaseRequest(environ)
 
263
        req = self._makeOne(environ)
792
264
        req.urlargs = ('a', 'b')
793
265
        self.assertEqual(req.urlargs, ('a', 'b'))
794
266
        self.assertEqual(environ['wsgiorg.routing_args'],
795
267
                         (('a', 'b'), {'foo': 'bar'}))
796
 
        self.assert_('paste.urlvars' not in environ)
 
268
        self.assertTrue('paste.urlvars' not in environ)
797
269
 
798
270
    def test_urlargs_setter_w_wsgiorg_key(self):
799
271
        environ = {'wsgiorg.routing_args': ((), {'foo': 'bar'}),
800
272
                  }
801
 
        req = BaseRequest(environ)
 
273
        req = self._makeOne(environ)
802
274
        req.urlargs = ('a', 'b')
803
275
        self.assertEqual(req.urlargs, ('a', 'b'))
804
276
        self.assertEqual(environ['wsgiorg.routing_args'],
806
278
 
807
279
    def test_urlargs_setter_wo_keys(self):
808
280
        environ = {}
809
 
        req = BaseRequest(environ)
 
281
        req = self._makeOne(environ)
810
282
        req.urlargs = ('a', 'b')
811
283
        self.assertEqual(req.urlargs, ('a', 'b'))
812
284
        self.assertEqual(environ['wsgiorg.routing_args'],
813
285
                         (('a', 'b'), {}))
814
 
        self.assert_('paste.urlvars' not in environ)
 
286
        self.assertTrue('paste.urlvars' not in environ)
815
287
 
816
288
    def test_urlargs_deleter_w_wsgiorg_key(self):
817
289
        environ = {'wsgiorg.routing_args': (('a', 'b'), {'foo': 'bar'}),
818
290
                  }
819
 
        req = BaseRequest(environ)
 
291
        req = self._makeOne(environ)
820
292
        del req.urlargs
821
293
        self.assertEqual(req.urlargs, ())
822
294
        self.assertEqual(environ['wsgiorg.routing_args'],
825
297
    def test_urlargs_deleter_w_wsgiorg_key_empty(self):
826
298
        environ = {'wsgiorg.routing_args': ((), {}),
827
299
                  }
828
 
        req = BaseRequest(environ)
 
300
        req = self._makeOne(environ)
829
301
        del req.urlargs
830
302
        self.assertEqual(req.urlargs, ())
831
 
        self.assert_('paste.urlvars' not in environ)
832
 
        self.assert_('wsgiorg.routing_args' not in environ)
 
303
        self.assertTrue('paste.urlvars' not in environ)
 
304
        self.assertTrue('wsgiorg.routing_args' not in environ)
833
305
 
834
306
    def test_urlargs_deleter_wo_keys(self):
835
307
        environ = {}
836
 
        req = BaseRequest(environ)
 
308
        req = self._makeOne(environ)
837
309
        del req.urlargs
838
310
        self.assertEqual(req.urlargs, ())
839
 
        self.assert_('paste.urlvars' not in environ)
840
 
        self.assert_('wsgiorg.routing_args' not in environ)
841
 
 
842
 
    def test_str_cookies_empty_environ(self):
843
 
        req = BaseRequest({})
844
 
        self.assertEqual(req.str_cookies, {})
845
 
 
846
 
    def test_str_cookies_w_webob_parsed_cookies_matching_source(self):
 
311
        self.assertTrue('paste.urlvars' not in environ)
 
312
        self.assertTrue('wsgiorg.routing_args' not in environ)
 
313
 
 
314
    def test_cookies_empty_environ(self):
 
315
        req = self._makeOne({})
 
316
        self.assertEqual(req.cookies, {})
 
317
 
 
318
    def test_cookies_is_mutable(self):
 
319
        req = self._makeOne({})
 
320
        cookies = req.cookies
 
321
        cookies['a'] = '1'
 
322
        self.assertEqual(req.cookies['a'], '1')
 
323
 
 
324
    def test_cookies_w_webob_parsed_cookies_matching_source(self):
847
325
        environ = {
848
326
            'HTTP_COOKIE': 'a=b',
849
327
            'webob._parsed_cookies': ('a=b', {'a': 'b'}),
850
328
        }
851
 
        req = BaseRequest(environ)
852
 
        self.assertEqual(req.str_cookies, {'a': 'b'})
 
329
        req = self._makeOne(environ)
 
330
        self.assertEqual(req.cookies, {'a': 'b'})
853
331
 
854
 
    def test_str_cookies_w_webob_parsed_cookies_mismatched_source(self):
 
332
    def test_cookies_w_webob_parsed_cookies_mismatched_source(self):
855
333
        environ = {
856
334
            'HTTP_COOKIE': 'a=b',
857
335
            'webob._parsed_cookies': ('a=b;c=d', {'a': 'b', 'c': 'd'}),
858
336
        }
859
 
        req = BaseRequest(environ)
860
 
        self.assertEqual(req.str_cookies, {'a': 'b'})
861
 
 
862
 
    def test_is_xhr_no_header(self):
863
 
        req = BaseRequest({})
864
 
        self.assert_(not req.is_xhr)
865
 
 
866
 
    def test_is_xhr_header_miss(self):
867
 
        environ = {'HTTP_X_REQUESTED_WITH': 'notAnXMLHTTPRequest'}
868
 
        req = BaseRequest(environ)
869
 
        self.assert_(not req.is_xhr)
870
 
 
871
 
    def test_is_xhr_header_hit(self):
872
 
        environ = {'HTTP_X_REQUESTED_WITH': 'XMLHttpRequest'}
873
 
        req = BaseRequest(environ)
874
 
        self.assert_(req.is_xhr)
875
 
 
876
 
    # host
877
 
    def test_host_getter_w_HTTP_HOST(self):
878
 
        environ = {'HTTP_HOST': 'example.com:8888'}
879
 
        req = BaseRequest(environ)
880
 
        self.assertEqual(req.host, 'example.com:8888')
881
 
 
882
 
    def test_host_getter_wo_HTTP_HOST(self):
883
 
        environ = {'SERVER_NAME': 'example.com',
884
 
                   'SERVER_PORT': '8888'}
885
 
        req = BaseRequest(environ)
886
 
        self.assertEqual(req.host, 'example.com:8888')
887
 
 
888
 
    def test_host_setter(self):
889
 
        environ = {}
890
 
        req = BaseRequest(environ)
891
 
        req.host = 'example.com:8888'
892
 
        self.assertEqual(environ['HTTP_HOST'], 'example.com:8888')
893
 
 
894
 
    def test_host_deleter_hit(self):
895
 
        environ = {'HTTP_HOST': 'example.com:8888'}
896
 
        req = BaseRequest(environ)
897
 
        del req.host
898
 
        self.assert_('HTTP_HOST' not in environ)
899
 
 
900
 
    def test_host_deleter_miss(self):
901
 
        environ = {}
902
 
        req = BaseRequest(environ)
903
 
        del req.host # doesn't raise
 
337
        req = self._makeOne(environ)
 
338
        self.assertEqual(req.cookies, {'a': 'b'})
 
339
 
 
340
    def test_set_cookies(self):
 
341
        environ = {
 
342
            'HTTP_COOKIE': 'a=b',
 
343
        }
 
344
        req = self._makeOne(environ)
 
345
        req.cookies = {'a':'1', 'b': '2'}
 
346
        self.assertEqual(req.cookies, {'a': '1', 'b':'2'})
 
347
        rcookies = [x.strip() for x in environ['HTTP_COOKIE'].split(';')]
 
348
        self.assertEqual(sorted(rcookies), ['a=1', 'b=2'])
904
349
 
905
350
    # body
906
351
    def test_body_getter(self):
907
 
        INPUT = self._makeStringIO('input')
 
352
        INPUT = BytesIO(b'input')
908
353
        environ = {'wsgi.input': INPUT,
909
354
                   'webob.is_body_seekable': True,
910
355
                   'CONTENT_LENGTH': len('input'),
911
356
                   'REQUEST_METHOD': 'POST'
912
357
                  }
913
 
        req = BaseRequest(environ)
914
 
        self.assertEqual(req.body, 'input')
915
 
        self.assertEqual(req.content_length, len('input'))
 
358
        req = self._makeOne(environ)
 
359
        self.assertEqual(req.body, b'input')
 
360
        self.assertEqual(req.content_length, len(b'input'))
 
361
 
916
362
    def test_body_setter_None(self):
917
 
        INPUT = self._makeStringIO('input')
 
363
        INPUT = BytesIO(b'input')
918
364
        environ = {'wsgi.input': INPUT,
919
365
                   'webob.is_body_seekable': True,
920
 
                   'CONTENT_LENGTH': len('input'),
 
366
                   'CONTENT_LENGTH': len(b'input'),
921
367
                   'REQUEST_METHOD': 'POST'
922
368
                  }
923
 
        req = BaseRequest(environ)
 
369
        req = self._makeOne(environ)
924
370
        req.body = None
925
 
        self.assertEqual(req.body, '')
 
371
        self.assertEqual(req.body, b'')
926
372
        self.assertEqual(req.content_length, 0)
927
 
        self.assert_(req.is_body_seekable)
 
373
        self.assertTrue(req.is_body_seekable)
 
374
 
928
375
    def test_body_setter_non_string_raises(self):
929
 
        req = BaseRequest({})
 
376
        req = self._makeOne({})
930
377
        def _test():
931
378
            req.body = object()
932
379
        self.assertRaises(TypeError, _test)
 
380
 
933
381
    def test_body_setter_value(self):
934
 
        BEFORE = self._makeStringIO('before')
 
382
        BEFORE = BytesIO(b'before')
935
383
        environ = {'wsgi.input': BEFORE,
936
384
                   'webob.is_body_seekable': True,
937
385
                   'CONTENT_LENGTH': len('before'),
938
386
                   'REQUEST_METHOD': 'POST'
939
387
                  }
940
 
        req = BaseRequest(environ)
941
 
        req.body = 'after'
942
 
        self.assertEqual(req.body, 'after')
943
 
        self.assertEqual(req.content_length, len('after'))
944
 
        self.assert_(req.is_body_seekable)
 
388
        req = self._makeOne(environ)
 
389
        req.body = b'after'
 
390
        self.assertEqual(req.body, b'after')
 
391
        self.assertEqual(req.content_length, len(b'after'))
 
392
        self.assertTrue(req.is_body_seekable)
 
393
 
945
394
    def test_body_deleter_None(self):
946
 
        INPUT = self._makeStringIO('input')
 
395
        data = b'input'
 
396
        INPUT = BytesIO(data)
947
397
        environ = {'wsgi.input': INPUT,
948
398
                   'webob.is_body_seekable': True,
949
 
                   'CONTENT_LENGTH': len('input'),
 
399
                   'CONTENT_LENGTH': len(data),
950
400
                   'REQUEST_METHOD': 'POST',
951
401
                  }
952
 
        req = BaseRequest(environ)
 
402
        req = self._makeOne(environ)
953
403
        del req.body
954
 
        self.assertEqual(req.body, '')
 
404
        self.assertEqual(req.body, b'')
955
405
        self.assertEqual(req.content_length, 0)
956
 
        self.assert_(req.is_body_seekable)
957
 
 
958
 
    def test_str_POST_not_POST_or_PUT(self):
 
406
        self.assertTrue(req.is_body_seekable)
 
407
 
 
408
    # JSON
 
409
 
 
410
    def test_json_body(self):
 
411
        body = b'{"a":1}'
 
412
        INPUT = BytesIO(body)
 
413
        environ = {'wsgi.input': INPUT, 'CONTENT_LENGTH': str(len(body))}
 
414
        req = self._makeOne(environ)
 
415
        self.assertEqual(req.json, {"a": 1})
 
416
        self.assertEqual(req.json_body, {"a": 1})
 
417
        req.json = {"b": 2}
 
418
        self.assertEqual(req.body, b'{"b":2}')
 
419
        del req.json
 
420
        self.assertEqual(req.body, b'')
 
421
 
 
422
    # .text
 
423
 
 
424
    def test_text_body(self):
 
425
        body = b'test'
 
426
        INPUT = BytesIO(body)
 
427
        environ = {'wsgi.input': INPUT, 'CONTENT_LENGTH': str(len(body))}
 
428
        req = self._makeOne(environ)
 
429
        self.assertEqual(req.body, b'test')
 
430
        self.assertEqual(req.text, 'test')
 
431
        req.text = text_('\u1000')
 
432
        self.assertEqual(req.body, '\u1000'.encode(req.charset))
 
433
        del req.text
 
434
        self.assertEqual(req.body, b'')
 
435
        def set_bad_text():
 
436
            req.text = 1
 
437
        self.assertRaises(TypeError, set_bad_text)
 
438
 
 
439
    def test__text_get_without_charset(self):
 
440
        body = b'test'
 
441
        INPUT = BytesIO(body)
 
442
        environ = {'wsgi.input': INPUT, 'CONTENT_LENGTH': str(len(body))}
 
443
        req = self._makeOne(environ)
 
444
        req._charset = ''
 
445
        self.assertRaises(AttributeError, getattr, req, 'text')
 
446
 
 
447
    def test__text_set_without_charset(self):
 
448
        body = b'test'
 
449
        INPUT = BytesIO(body)
 
450
        environ = {'wsgi.input': INPUT, 'CONTENT_LENGTH': str(len(body))}
 
451
        req = self._makeOne(environ)
 
452
        req._charset = ''
 
453
        self.assertRaises(AttributeError, setattr, req, 'text', 'abc')
 
454
 
 
455
    # POST
 
456
    def test_POST_not_POST_or_PUT(self):
959
457
        from webob.multidict import NoVars
960
458
        environ = {'REQUEST_METHOD': 'GET',
961
459
                  }
962
 
        req = BaseRequest(environ)
963
 
        result = req.str_POST
964
 
        self.assert_(isinstance(result, NoVars))
965
 
        self.assert_(result.reason.startswith('Not a form request'))
 
460
        req = self._makeOne(environ)
 
461
        result = req.POST
 
462
        self.assertTrue(isinstance(result, NoVars))
 
463
        self.assertTrue(result.reason.startswith('Not a form request'))
966
464
 
967
 
    def test_str_POST_existing_cache_hit(self):
968
 
        INPUT = self._makeStringIO('input')
 
465
    def test_POST_existing_cache_hit(self):
 
466
        data = b'input'
 
467
        INPUT = BytesIO(data)
969
468
        environ = {'wsgi.input': INPUT,
970
469
                   'REQUEST_METHOD': 'POST',
971
470
                   'webob._parsed_post_vars': ({'foo': 'bar'}, INPUT),
972
471
                  }
973
 
        req = BaseRequest(environ)
974
 
        result = req.str_POST
 
472
        req = self._makeOne(environ)
 
473
        result = req.POST
975
474
        self.assertEqual(result, {'foo': 'bar'})
976
475
 
977
 
    def test_str_PUT_missing_content_type(self):
 
476
    def test_PUT_missing_content_type(self):
978
477
        from webob.multidict import NoVars
979
 
        INPUT = self._makeStringIO('input')
 
478
        data = b'input'
 
479
        INPUT = BytesIO(data)
980
480
        environ = {'wsgi.input': INPUT,
981
481
                   'REQUEST_METHOD': 'PUT',
982
482
                  }
983
 
        req = BaseRequest(environ)
984
 
        result = req.str_POST
985
 
        self.assert_(isinstance(result, NoVars))
986
 
        self.assert_(result.reason.startswith('Not an HTML form submission'))
 
483
        req = self._makeOne(environ)
 
484
        result = req.POST
 
485
        self.assertTrue(isinstance(result, NoVars))
 
486
        self.assertTrue(result.reason.startswith('Not an HTML form submission'))
987
487
 
988
 
    def test_str_PUT_bad_content_type(self):
 
488
    def test_PUT_bad_content_type(self):
989
489
        from webob.multidict import NoVars
990
 
        INPUT = self._makeStringIO('input')
 
490
        data = b'input'
 
491
        INPUT = BytesIO(data)
991
492
        environ = {'wsgi.input': INPUT,
992
493
                   'REQUEST_METHOD': 'PUT',
993
494
                   'CONTENT_TYPE': 'text/plain',
994
495
                  }
995
 
        req = BaseRequest(environ)
996
 
        result = req.str_POST
997
 
        self.assert_(isinstance(result, NoVars))
998
 
        self.assert_(result.reason.startswith('Not an HTML form submission'))
 
496
        req = self._makeOne(environ)
 
497
        result = req.POST
 
498
        self.assertTrue(isinstance(result, NoVars))
 
499
        self.assertTrue(result.reason.startswith('Not an HTML form submission'))
999
500
 
1000
 
    def test_str_POST_multipart(self):
 
501
    def test_POST_multipart(self):
1001
502
        BODY_TEXT = (
1002
 
            '------------------------------deb95b63e42a\n'
1003
 
            'Content-Disposition: form-data; name="foo"\n'
1004
 
            '\n'
1005
 
            'foo\n'
1006
 
            '------------------------------deb95b63e42a\n'
1007
 
            'Content-Disposition: form-data; name="bar"; filename="bar.txt"\n'
1008
 
            'Content-type: application/octet-stream\n'
1009
 
            '\n'
1010
 
            'these are the contents of the file "bar.txt"\n'
1011
 
            '\n'
1012
 
            '------------------------------deb95b63e42a--\n')
1013
 
        INPUT = self._makeStringIO(BODY_TEXT)
 
503
            b'------------------------------deb95b63e42a\n'
 
504
            b'Content-Disposition: form-data; name="foo"\n'
 
505
            b'\n'
 
506
            b'foo\n'
 
507
            b'------------------------------deb95b63e42a\n'
 
508
            b'Content-Disposition: form-data; name="bar"; filename="bar.txt"\n'
 
509
            b'Content-type: application/octet-stream\n'
 
510
            b'\n'
 
511
            b'these are the contents of the file "bar.txt"\n'
 
512
            b'\n'
 
513
            b'------------------------------deb95b63e42a--\n')
 
514
        INPUT = BytesIO(BODY_TEXT)
1014
515
        environ = {'wsgi.input': INPUT,
1015
516
                   'webob.is_body_seekable': True,
1016
517
                   'REQUEST_METHOD': 'POST',
1018
519
                      'boundary=----------------------------deb95b63e42a',
1019
520
                   'CONTENT_LENGTH': len(BODY_TEXT),
1020
521
                  }
1021
 
        req = BaseRequest(environ)
1022
 
        result = req.str_POST
 
522
        req = self._makeOne(environ)
 
523
        result = req.POST
1023
524
        self.assertEqual(result['foo'], 'foo')
1024
525
        bar = result['bar']
1025
526
        self.assertEqual(bar.name, 'bar')
1026
527
        self.assertEqual(bar.filename, 'bar.txt')
1027
528
        self.assertEqual(bar.file.read(),
1028
 
                         'these are the contents of the file "bar.txt"\n')
 
529
                         b'these are the contents of the file "bar.txt"\n')
1029
530
 
1030
 
    # POST
1031
 
    # str_GET
1032
 
    def test_str_GET_reflects_query_string(self):
 
531
    # GET
 
532
    def test_GET_reflects_query_string(self):
1033
533
        environ = {
1034
534
            'QUERY_STRING': 'foo=123',
1035
535
        }
1036
 
        req = BaseRequest(environ)
1037
 
        result = req.str_GET
 
536
        req = self._makeOne(environ)
 
537
        result = req.GET
1038
538
        self.assertEqual(result, {'foo': '123'})
1039
539
        req.query_string = 'foo=456'
1040
 
        result = req.str_GET
 
540
        result = req.GET
1041
541
        self.assertEqual(result, {'foo': '456'})
1042
542
        req.query_string = ''
1043
 
        result = req.str_GET
 
543
        result = req.GET
1044
544
        self.assertEqual(result, {})
1045
545
 
1046
 
    def test_str_GET_updates_query_string(self):
1047
 
        environ = {
1048
 
        }
1049
 
        req = BaseRequest(environ)
 
546
    def test_GET_updates_query_string(self):
 
547
        req = self._makeOne({})
1050
548
        result = req.query_string
1051
549
        self.assertEqual(result, '')
1052
 
        req.str_GET['foo'] = '123'
 
550
        req.GET['foo'] = '123'
1053
551
        result = req.query_string
1054
552
        self.assertEqual(result, 'foo=123')
1055
 
        del req.str_GET['foo']
 
553
        del req.GET['foo']
1056
554
        result = req.query_string
1057
555
        self.assertEqual(result, '')
1058
556
 
1059
 
    # GET
1060
 
    # str_postvars
1061
 
    # postvars
1062
 
    # str_queryvars
1063
 
    # queryvars
1064
 
    # is_xhr
1065
 
    # str_params
1066
 
    # params
1067
 
 
1068
 
    def test_str_cookies_wo_webob_parsed_cookies(self):
1069
 
        environ = {
1070
 
            'HTTP_COOKIE': 'a=b',
1071
 
        }
1072
 
        req = Request.blank('/', environ)
1073
 
        self.assertEqual(req.str_cookies, {'a': 'b'})
1074
 
 
1075
557
    # cookies
 
558
    def test_cookies_wo_webob_parsed_cookies(self):
 
559
        environ = {
 
560
            'HTTP_COOKIE': 'a=b',
 
561
        }
 
562
        req = self._blankOne('/', environ)
 
563
        self.assertEqual(req.cookies, {'a': 'b'})
 
564
 
1076
565
    # copy
1077
 
 
1078
566
    def test_copy_get(self):
1079
567
        environ = {
1080
568
            'HTTP_COOKIE': 'a=b',
1081
569
        }
1082
 
        req = Request.blank('/', environ)
 
570
        req = self._blankOne('/', environ)
1083
571
        clone = req.copy_get()
1084
572
        for k, v in req.environ.items():
1085
573
            if k in ('CONTENT_LENGTH', 'webob.is_body_seekable'):
1086
 
                self.assert_(k not in clone.environ)
 
574
                self.assertTrue(k not in clone.environ)
1087
575
            elif k == 'wsgi.input':
1088
 
                self.assert_(clone.environ[k] is not v)
 
576
                self.assertTrue(clone.environ[k] is not v)
1089
577
            else:
1090
578
                self.assertEqual(clone.environ[k], v)
1091
579
 
1092
580
    def test_remove_conditional_headers_accept_encoding(self):
1093
 
        req = Request.blank('/')
 
581
        req = self._blankOne('/')
1094
582
        req.accept_encoding='gzip,deflate'
1095
583
        req.remove_conditional_headers()
1096
584
        self.assertEqual(bool(req.accept_encoding), False)
1097
585
 
1098
586
    def test_remove_conditional_headers_if_modified_since(self):
 
587
        from webob.datetime_utils import UTC
1099
588
        from datetime import datetime
1100
 
        req = Request.blank('/')
 
589
        req = self._blankOne('/')
1101
590
        req.if_modified_since = datetime(2006, 1, 1, 12, 0, tzinfo=UTC)
1102
591
        req.remove_conditional_headers()
1103
592
        self.assertEqual(req.if_modified_since, None)
1104
593
 
1105
594
    def test_remove_conditional_headers_if_none_match(self):
1106
 
        req = Request.blank('/')
1107
 
        req.if_none_match = 'foo, bar'
 
595
        req = self._blankOne('/')
 
596
        req.if_none_match = 'foo'
 
597
        assert req.if_none_match
1108
598
        req.remove_conditional_headers()
1109
 
        self.assertEqual(bool(req.if_none_match), False)
 
599
        assert not req.if_none_match
1110
600
 
1111
601
    def test_remove_conditional_headers_if_range(self):
1112
 
        req = Request.blank('/')
 
602
        req = self._blankOne('/')
1113
603
        req.if_range = 'foo, bar'
1114
604
        req.remove_conditional_headers()
1115
605
        self.assertEqual(bool(req.if_range), False)
1116
606
 
1117
607
    def test_remove_conditional_headers_range(self):
1118
 
        req = Request.blank('/')
 
608
        req = self._blankOne('/')
1119
609
        req.range = 'bytes=0-100'
1120
610
        req.remove_conditional_headers()
1121
611
        self.assertEqual(req.range, None)
1122
612
 
1123
613
    def test_is_body_readable_POST(self):
1124
 
        req = Request.blank('/', environ={'REQUEST_METHOD':'POST'})
 
614
        req = self._blankOne('/', environ={'REQUEST_METHOD':'POST'})
1125
615
        self.assertTrue(req.is_body_readable)
1126
616
 
1127
617
    def test_is_body_readable_GET(self):
1128
 
        req = Request.blank('/', environ={'REQUEST_METHOD':'GET'})
 
618
        req = self._blankOne('/', environ={'REQUEST_METHOD':'GET'})
1129
619
        self.assertFalse(req.is_body_readable)
1130
620
 
1131
621
    def test_is_body_readable_unknown_method_and_content_length(self):
1132
 
        req = Request.blank('/', environ={'REQUEST_METHOD':'WTF'})
 
622
        req = self._blankOne('/', environ={'REQUEST_METHOD':'WTF'})
1133
623
        req.content_length = 10
1134
624
        self.assertTrue(req.is_body_readable)
1135
625
 
1136
626
    def test_is_body_readable_special_flag(self):
1137
 
        req = Request.blank('/', environ={'REQUEST_METHOD':'WTF',
 
627
        req = self._blankOne('/', environ={'REQUEST_METHOD':'WTF',
1138
628
                                          'webob.is_body_readable': True})
1139
629
        self.assertTrue(req.is_body_readable)
1140
630
 
1155
645
        environ = {
1156
646
            'HTTP_CACHE_CONTROL': 'max-age=5',
1157
647
        }
1158
 
        req = BaseRequest(environ)
 
648
        req = self._makeOne(environ)
1159
649
        result = req.cache_control
1160
650
        self.assertEqual(result.properties, {'max-age': 5})
1161
651
        req.environ.update(HTTP_CACHE_CONTROL='max-age=10')
1167
657
 
1168
658
    def test_cache_control_updates_environ(self):
1169
659
        environ = {}
1170
 
        req = BaseRequest(environ)
 
660
        req = self._makeOne(environ)
1171
661
        req.cache_control.max_age = 5
1172
662
        result = req.environ['HTTP_CACHE_CONTROL']
1173
663
        self.assertEqual(result, 'max-age=5')
1178
668
        result = req.environ['HTTP_CACHE_CONTROL']
1179
669
        self.assertEqual(result, '')
1180
670
        del req.cache_control
1181
 
        self.assert_('HTTP_CACHE_CONTROL' not in req.environ)
 
671
        self.assertTrue('HTTP_CACHE_CONTROL' not in req.environ)
1182
672
 
1183
673
    def test_cache_control_set_dict(self):
1184
674
        environ = {}
1185
 
        req = BaseRequest(environ)
 
675
        req = self._makeOne(environ)
1186
676
        req.cache_control = {'max-age': 5}
1187
677
        result = req.cache_control
1188
678
        self.assertEqual(result.max_age, 5)
1190
680
    def test_cache_control_set_object(self):
1191
681
        from webob.cachecontrol import CacheControl
1192
682
        environ = {}
1193
 
        req = BaseRequest(environ)
 
683
        req = self._makeOne(environ)
1194
684
        req.cache_control = CacheControl({'max-age': 5}, type='request')
1195
685
        result = req.cache_control
1196
686
        self.assertEqual(result.max_age, 5)
1197
687
 
1198
688
    def test_cache_control_gets_cached(self):
1199
689
        environ = {}
1200
 
        req = BaseRequest(environ)
1201
 
        self.assert_(req.cache_control is req.cache_control)
 
690
        req = self._makeOne(environ)
 
691
        self.assertTrue(req.cache_control is req.cache_control)
1202
692
 
1203
693
    #if_match
1204
694
    #if_none_match
1220
710
    #call_application
1221
711
    def test_call_application_calls_application(self):
1222
712
        environ = {}
1223
 
        req = BaseRequest(environ)
 
713
        req = self._makeOne(environ)
1224
714
        def application(environ, start_response):
1225
715
            start_response('200 OK', [('content-type', 'text/plain')])
1226
716
            return ['...\n']
1231
721
 
1232
722
    def test_call_application_provides_write(self):
1233
723
        environ = {}
1234
 
        req = BaseRequest(environ)
 
724
        req = self._makeOne(environ)
1235
725
        def application(environ, start_response):
1236
726
            write = start_response('200 OK', [('content-type', 'text/plain')])
1237
727
            write('...\n')
1245
735
        environ = {
1246
736
            'test._call_application_called_close': False
1247
737
        }
1248
 
        req = BaseRequest(environ)
 
738
        req = self._makeOne(environ)
1249
739
        def application(environ, start_response):
1250
740
            write = start_response('200 OK', [('content-type', 'text/plain')])
1251
741
            class AppIter(object):
1261
751
 
1262
752
    def test_call_application_raises_exc_info(self):
1263
753
        environ = {}
1264
 
        req = BaseRequest(environ)
 
754
        req = self._makeOne(environ)
1265
755
        def application(environ, start_response):
1266
756
            try:
1267
757
                raise RuntimeError('OH NOES')
1268
758
            except:
1269
 
                import sys
1270
759
                exc_info = sys.exc_info()
1271
760
            start_response('200 OK', [('content-type', 'text/plain')], exc_info)
1272
761
            return ['...\n']
1274
763
 
1275
764
    def test_call_application_returns_exc_info(self):
1276
765
        environ = {}
1277
 
        req = BaseRequest(environ)
 
766
        req = self._makeOne(environ)
1278
767
        def application(environ, start_response):
1279
768
            try:
1280
769
                raise RuntimeError('OH NOES')
1281
770
            except:
1282
 
                import sys
1283
771
                exc_info = sys.exc_info()
1284
772
            start_response('200 OK', [('content-type', 'text/plain')], exc_info)
1285
773
            return ['...\n']
1286
 
        status, headers, output, exc_info = req.call_application(application, True)
 
774
        status, headers, output, exc_info = req.call_application(
 
775
            application, True)
1287
776
        self.assertEqual(status, '200 OK')
1288
777
        self.assertEqual(headers, [('content-type', 'text/plain')])
1289
778
        self.assertEqual(''.join(output), '...\n')
1291
780
 
1292
781
    #get_response
1293
782
    def test_blank__method_subtitution(self):
1294
 
        request = BaseRequest.blank('/', environ={'REQUEST_METHOD': 'PUT'})
1295
 
        self.assertEqual(request.method, 'PUT')
1296
 
 
1297
 
        request = BaseRequest.blank('/', environ={'REQUEST_METHOD': 'PUT'}, POST={})
1298
 
        self.assertEqual(request.method, 'PUT')
1299
 
 
1300
 
        request = BaseRequest.blank('/', environ={'REQUEST_METHOD': 'HEAD'}, POST={})
 
783
        request = self._blankOne('/', environ={'REQUEST_METHOD': 'PUT'})
 
784
        self.assertEqual(request.method, 'PUT')
 
785
 
 
786
        request = self._blankOne(
 
787
            '/', environ={'REQUEST_METHOD': 'PUT'}, POST={})
 
788
        self.assertEqual(request.method, 'PUT')
 
789
 
 
790
        request = self._blankOne(
 
791
            '/', environ={'REQUEST_METHOD': 'HEAD'}, POST={})
1301
792
        self.assertEqual(request.method, 'POST')
1302
793
 
1303
794
    def test_blank__ctype_in_env(self):
1304
 
        request = BaseRequest.blank('/', environ={'CONTENT_TYPE': 'application/json'})
 
795
        request = self._blankOne(
 
796
            '/', environ={'CONTENT_TYPE': 'application/json'})
1305
797
        self.assertEqual(request.content_type, 'application/json')
1306
798
        self.assertEqual(request.method, 'GET')
1307
799
 
1308
 
        request = BaseRequest.blank('/', environ={'CONTENT_TYPE': 'application/json'},
1309
 
                                         POST='')
 
800
        request = self._blankOne(
 
801
            '/', environ={'CONTENT_TYPE': 'application/json'}, POST='')
1310
802
        self.assertEqual(request.content_type, 'application/json')
1311
803
        self.assertEqual(request.method, 'POST')
1312
804
 
1313
805
    def test_blank__ctype_in_headers(self):
1314
 
        request = BaseRequest.blank('/', headers={'Content-type': 'application/json'})
 
806
        request = self._blankOne(
 
807
            '/', headers={'Content-type': 'application/json'})
1315
808
        self.assertEqual(request.content_type, 'application/json')
1316
809
        self.assertEqual(request.method, 'GET')
1317
810
 
1318
 
        request = BaseRequest.blank('/', headers={'Content-Type': 'application/json'},
1319
 
                                         POST='')
 
811
        request = self._blankOne(
 
812
            '/', headers={'Content-Type': 'application/json'}, POST='')
1320
813
        self.assertEqual(request.content_type, 'application/json')
1321
814
        self.assertEqual(request.method, 'POST')
1322
815
 
1323
816
    def test_blank__ctype_as_kw(self):
1324
 
        request = BaseRequest.blank('/', content_type='application/json')
 
817
        request = self._blankOne('/', content_type='application/json')
1325
818
        self.assertEqual(request.content_type, 'application/json')
1326
819
        self.assertEqual(request.method, 'GET')
1327
820
 
1328
 
        request = BaseRequest.blank('/', content_type='application/json',
 
821
        request = self._blankOne('/', content_type='application/json',
1329
822
                                         POST='')
1330
823
        self.assertEqual(request.content_type, 'application/json')
1331
824
        self.assertEqual(request.method, 'POST')
1332
825
 
1333
826
    def test_blank__str_post_data_for_unsupported_ctype(self):
1334
 
        self.assertRaises(ValueError, BaseRequest.blank, '/', content_type='application/json',
1335
 
                                                              POST={})
 
827
        self.assertRaises(ValueError,
 
828
                          self._blankOne,
 
829
                          '/', content_type='application/json', POST={})
1336
830
 
1337
831
    def test_blank__post_urlencoded(self):
1338
 
        request = Request.blank('/', POST={'first':1, 'second':2})
 
832
        request = self._blankOne('/', POST={'first':1, 'second':2})
1339
833
        self.assertEqual(request.method, 'POST')
1340
 
        self.assertEqual(request.content_type, 'application/x-www-form-urlencoded')
1341
 
        self.assertEqual(request.body, 'first=1&second=2')
 
834
        self.assertEqual(request.content_type,
 
835
                         'application/x-www-form-urlencoded')
 
836
        self.assertEqual(request.body, b'first=1&second=2')
1342
837
        self.assertEqual(request.content_length, 16)
1343
838
 
1344
839
    def test_blank__post_multipart(self):
1345
 
        request = Request.blank('/', POST={'first':'1', 'second':'2'},
1346
 
                                     content_type='multipart/form-data; boundary=boundary')
 
840
        request = self._blankOne(
 
841
            '/', POST={'first':'1', 'second':'2'},
 
842
            content_type='multipart/form-data; boundary=boundary')
1347
843
        self.assertEqual(request.method, 'POST')
1348
844
        self.assertEqual(request.content_type, 'multipart/form-data')
1349
 
        self.assertEqual(request.body, '--boundary\r\n'
1350
 
                                       'Content-Disposition: form-data; name="first"\r\n\r\n'
1351
 
                                       '1\r\n'
1352
 
                                       '--boundary\r\n'
1353
 
                                       'Content-Disposition: form-data; name="second"\r\n\r\n'
1354
 
                                       '2\r\n'
1355
 
                                       '--boundary--')
 
845
        expected = (
 
846
            b'--boundary\r\n'
 
847
            b'Content-Disposition: form-data; name="first"\r\n\r\n'
 
848
            b'1\r\n'
 
849
            b'--boundary\r\n'
 
850
            b'Content-Disposition: form-data; name="second"\r\n\r\n'
 
851
            b'2\r\n'
 
852
            b'--boundary--')
 
853
        self.assertEqual(request.body, expected)
1356
854
        self.assertEqual(request.content_length, 139)
1357
855
 
1358
856
    def test_blank__post_files(self):
1359
857
        import cgi
1360
 
        from StringIO import StringIO
1361
858
        from webob.request import _get_multipart_boundary
1362
 
        request = Request.blank('/', POST={'first':('filename1', StringIO('1')),
1363
 
                                           'second':('filename2', '2'),
1364
 
                                           'third': '3'})
 
859
        POST = {'first':('filename1', BytesIO(b'1')),
 
860
                       'second':('filename2', '2'),
 
861
                       'third': '3'}
 
862
        request = self._blankOne('/', POST=POST)
1365
863
        self.assertEqual(request.method, 'POST')
1366
864
        self.assertEqual(request.content_type, 'multipart/form-data')
1367
 
        boundary = _get_multipart_boundary(request.headers['content-type'])
1368
 
        body_norm = request.body.replace(boundary, 'boundary')
1369
 
        self.assertEqual(body_norm, '--boundary\r\n'
1370
 
                                       'Content-Disposition: form-data; name="first"; filename="filename1"\r\n\r\n'
1371
 
                                       '1\r\n'
1372
 
                                       '--boundary\r\n'
1373
 
                                       'Content-Disposition: form-data; name="second"; filename="filename2"\r\n\r\n'
1374
 
                                       '2\r\n'
1375
 
                                       '--boundary\r\n'
1376
 
                                       'Content-Disposition: form-data; name="third"\r\n\r\n'
1377
 
                                       '3\r\n'
1378
 
                                       '--boundary--')
 
865
        boundary = bytes_(
 
866
            _get_multipart_boundary(request.headers['content-type']))
 
867
        body_norm = request.body.replace(boundary, b'boundary')
 
868
        expected = (
 
869
            b'--boundary\r\n'
 
870
            b'Content-Disposition: form-data; name="first"; filename="filename1"\r\n\r\n'
 
871
            b'1\r\n'
 
872
            b'--boundary\r\n'
 
873
            b'Content-Disposition: form-data; name="second"; filename="filename2"\r\n\r\n'
 
874
            b'2\r\n'
 
875
            b'--boundary\r\n'
 
876
            b'Content-Disposition: form-data; name="third"\r\n\r\n'
 
877
            b'3\r\n'
 
878
            b'--boundary--'
 
879
            )
 
880
        self.assertEqual(body_norm, expected)
1379
881
        self.assertEqual(request.content_length, 294)
1380
882
        self.assertTrue(isinstance(request.POST['first'], cgi.FieldStorage))
1381
883
        self.assertTrue(isinstance(request.POST['second'], cgi.FieldStorage))
1382
 
        self.assertEqual(request.POST['first'].value, '1')
1383
 
        self.assertEqual(request.POST['second'].value, '2')
 
884
        self.assertEqual(request.POST['first'].value, b'1')
 
885
        self.assertEqual(request.POST['second'].value, b'2')
1384
886
        self.assertEqual(request.POST['third'], '3')
1385
887
 
1386
888
    def test_blank__post_file_w_wrong_ctype(self):
1387
 
        self.assertRaises(ValueError, Request.blank, '/', POST={'first':('filename1', '1')},
1388
 
                                                          content_type='application/x-www-form-urlencoded')
1389
 
 
1390
 
    #from_string
1391
 
    def test_from_string_extra_data(self):
1392
 
        from webob import BaseRequest
1393
 
        _test_req_copy = _test_req.replace('Content-Type',
1394
 
                            'Content-Length: 337\r\nContent-Type')
1395
 
        self.assertRaises(ValueError, BaseRequest.from_string,
1396
 
                _test_req_copy+'EXTRA!')
1397
 
 
1398
 
    #as_string
 
889
        self.assertRaises(
 
890
            ValueError, self._blankOne, '/', POST={'first':('filename1', '1')},
 
891
            content_type='application/x-www-form-urlencoded')
 
892
 
 
893
    #from_bytes
 
894
    def test_from_bytes_extra_data(self):
 
895
        _test_req_copy = _test_req.replace(
 
896
            b'Content-Type',
 
897
            b'Content-Length: 337\r\nContent-Type')
 
898
        cls = self._getTargetClass()
 
899
        self.assertRaises(ValueError, cls.from_bytes,
 
900
                _test_req_copy+b'EXTRA!')
 
901
 
 
902
    #as_bytes
 
903
    def test_as_bytes_skip_body(self):
 
904
        cls = self._getTargetClass()
 
905
        req = cls.from_bytes(_test_req)
 
906
        body = req.as_bytes(skip_body=True)
 
907
        self.assertEqual(body.count(b'\r\n\r\n'), 0)
 
908
        self.assertEqual(req.as_bytes(skip_body=337), req.as_bytes())
 
909
        body = req.as_bytes(337-1).split(b'\r\n\r\n', 1)[1]
 
910
        self.assertEqual(body, b'<body skipped (len=337)>')
 
911
 
1399
912
    def test_as_string_skip_body(self):
1400
 
        from webob import BaseRequest
1401
 
        req = BaseRequest.from_string(_test_req)
1402
 
        body = req.as_string(skip_body=True)
1403
 
        self.assertEqual(body.count('\r\n\r\n'), 0)
1404
 
        self.assertEqual(req.as_string(skip_body=337), req.as_string())
1405
 
        body = req.as_string(337-1).split('\r\n\r\n', 1)[1]
1406
 
        self.assertEqual(body, '<body skipped (len=337)>')
 
913
        with warnings.catch_warnings(record=True):
 
914
            cls = self._getTargetClass()
 
915
            req = cls.from_string(_test_req)
 
916
            body = req.as_string(skip_body=True)
 
917
            self.assertEqual(body.count(b'\r\n\r\n'), 0)
 
918
            self.assertEqual(req.as_string(skip_body=337), req.as_string())
 
919
            body = req.as_string(337-1).split(b'\r\n\r\n', 1)[1]
 
920
            self.assertEqual(body, b'<body skipped (len=337)>')
 
921
 
 
922
class TestBaseRequest(unittest.TestCase):
 
923
    # tests of methods of a base request which are encoding-specific
 
924
    def _getTargetClass(self):
 
925
        from webob.request import BaseRequest
 
926
        return BaseRequest
 
927
 
 
928
    def _makeOne(self, *arg, **kw):
 
929
        cls = self._getTargetClass()
 
930
        return cls(*arg, **kw)
 
931
 
 
932
    def _blankOne(self, *arg, **kw):
 
933
        cls = self._getTargetClass()
 
934
        return cls.blank(*arg, **kw)
 
935
 
 
936
    def test_method(self):
 
937
        environ = {'REQUEST_METHOD': 'OPTIONS',
 
938
                  }
 
939
        req = self._makeOne(environ)
 
940
        result = req.method
 
941
        self.assertEqual(result.__class__, str)
 
942
        self.assertEqual(result, 'OPTIONS')
 
943
 
 
944
    def test_http_version(self):
 
945
        environ = {'SERVER_PROTOCOL': '1.1',
 
946
                  }
 
947
        req = self._makeOne(environ)
 
948
        result = req.http_version
 
949
        self.assertEqual(result, '1.1')
 
950
 
 
951
    def test_script_name(self):
 
952
        environ = {'SCRIPT_NAME': '/script',
 
953
                  }
 
954
        req = self._makeOne(environ)
 
955
        self.assertEqual(req.script_name, '/script')
 
956
 
 
957
    def test_path_info(self):
 
958
        environ = {'PATH_INFO': '/path/info',
 
959
                  }
 
960
        req = self._makeOne(environ)
 
961
        self.assertEqual(req.path_info, '/path/info')
 
962
 
 
963
    def test_content_length_getter(self):
 
964
        environ = {'CONTENT_LENGTH': '1234',
 
965
                  }
 
966
        req = self._makeOne(environ)
 
967
        self.assertEqual(req.content_length, 1234)
 
968
 
 
969
    def test_content_length_setter_w_str(self):
 
970
        environ = {'CONTENT_LENGTH': '1234',
 
971
                  }
 
972
        req = self._makeOne(environ)
 
973
        req.content_length = '3456'
 
974
        self.assertEqual(req.content_length, 3456)
 
975
 
 
976
    def test_remote_user(self):
 
977
        environ = {'REMOTE_USER': 'phred',
 
978
                  }
 
979
        req = self._makeOne(environ)
 
980
        self.assertEqual(req.remote_user, 'phred')
 
981
 
 
982
    def test_remote_addr(self):
 
983
        environ = {'REMOTE_ADDR': '1.2.3.4',
 
984
                  }
 
985
        req = self._makeOne(environ)
 
986
        self.assertEqual(req.remote_addr, '1.2.3.4')
 
987
 
 
988
    def test_query_string(self):
 
989
        environ = {'QUERY_STRING': 'foo=bar&baz=bam',
 
990
                  }
 
991
        req = self._makeOne(environ)
 
992
        self.assertEqual(req.query_string, 'foo=bar&baz=bam')
 
993
 
 
994
    def test_server_name(self):
 
995
        environ = {'SERVER_NAME': 'somehost.tld',
 
996
                  }
 
997
        req = self._makeOne(environ)
 
998
        self.assertEqual(req.server_name, 'somehost.tld')
 
999
 
 
1000
    def test_server_port_getter(self):
 
1001
        environ = {'SERVER_PORT': '6666',
 
1002
                  }
 
1003
        req = self._makeOne(environ)
 
1004
        self.assertEqual(req.server_port, 6666)
 
1005
 
 
1006
    def test_server_port_setter_with_string(self):
 
1007
        environ = {'SERVER_PORT': '6666',
 
1008
                  }
 
1009
        req = self._makeOne(environ)
 
1010
        req.server_port = '6667'
 
1011
        self.assertEqual(req.server_port, 6667)
 
1012
 
 
1013
    def test_uscript_name(self):
 
1014
        environ = {'SCRIPT_NAME': '/script',
 
1015
                  }
 
1016
        req = self._makeOne(environ)
 
1017
        self.assertTrue(isinstance(req.uscript_name, text_type))
 
1018
        self.assertEqual(req.uscript_name, '/script')
 
1019
 
 
1020
    def test_upath_info(self):
 
1021
        environ = {'PATH_INFO': '/path/info',
 
1022
                  }
 
1023
        req = self._makeOne(environ)
 
1024
        self.assertTrue(isinstance(req.upath_info, text_type))
 
1025
        self.assertEqual(req.upath_info, '/path/info')
 
1026
 
 
1027
    def test_upath_info_set_unicode(self):
 
1028
        environ = {'PATH_INFO': '/path/info',
 
1029
                  }
 
1030
        req = self._makeOne(environ)
 
1031
        req.upath_info = text_('/another')
 
1032
        self.assertTrue(isinstance(req.upath_info, text_type))
 
1033
        self.assertEqual(req.upath_info, '/another')
 
1034
 
 
1035
    def test_content_type_getter_no_parameters(self):
 
1036
        environ = {'CONTENT_TYPE': 'application/xml+foobar',
 
1037
                  }
 
1038
        req = self._makeOne(environ)
 
1039
        self.assertEqual(req.content_type, 'application/xml+foobar')
 
1040
 
 
1041
    def test_content_type_getter_w_parameters(self):
 
1042
        environ = {'CONTENT_TYPE': 'application/xml+foobar;charset="utf8"',
 
1043
                  }
 
1044
        req = self._makeOne(environ)
 
1045
        self.assertEqual(req.content_type, 'application/xml+foobar')
 
1046
 
 
1047
    def test_content_type_setter_w_None(self):
 
1048
        environ = {'CONTENT_TYPE': 'application/xml+foobar;charset="utf8"',
 
1049
                  }
 
1050
        req = self._makeOne(environ)
 
1051
        req.content_type = None
 
1052
        self.assertEqual(req.content_type, '')
 
1053
        self.assertTrue('CONTENT_TYPE' not in environ)
 
1054
 
 
1055
    def test_content_type_setter_existing_paramter_no_new_paramter(self):
 
1056
        environ = {'CONTENT_TYPE': 'application/xml+foobar;charset="utf8"',
 
1057
                  }
 
1058
        req = self._makeOne(environ)
 
1059
        req.content_type = 'text/xml'
 
1060
        self.assertEqual(req.content_type, 'text/xml')
 
1061
        self.assertEqual(environ['CONTENT_TYPE'], 'text/xml;charset="utf8"')
 
1062
 
 
1063
    def test_content_type_deleter_clears_environ_value(self):
 
1064
        environ = {'CONTENT_TYPE': 'application/xml+foobar;charset="utf8"',
 
1065
                  }
 
1066
        req = self._makeOne(environ)
 
1067
        del req.content_type
 
1068
        self.assertEqual(req.content_type, '')
 
1069
        self.assertTrue('CONTENT_TYPE' not in environ)
 
1070
 
 
1071
    def test_content_type_deleter_no_environ_value(self):
 
1072
        environ = {}
 
1073
        req = self._makeOne(environ)
 
1074
        del req.content_type
 
1075
        self.assertEqual(req.content_type, '')
 
1076
        self.assertTrue('CONTENT_TYPE' not in environ)
 
1077
 
 
1078
    def test_headers_getter(self):
 
1079
        CONTENT_TYPE = 'application/xml+foobar;charset="utf8"'
 
1080
        environ = {'CONTENT_TYPE': CONTENT_TYPE,
 
1081
                   'CONTENT_LENGTH': '123',
 
1082
                  }
 
1083
        req = self._makeOne(environ)
 
1084
        headers = req.headers
 
1085
        self.assertEqual(headers,
 
1086
                        {'Content-Type': CONTENT_TYPE,
 
1087
                         'Content-Length': '123'})
 
1088
 
 
1089
    def test_headers_setter(self):
 
1090
        CONTENT_TYPE = 'application/xml+foobar;charset="utf8"'
 
1091
        environ = {'CONTENT_TYPE': CONTENT_TYPE,
 
1092
                   'CONTENT_LENGTH': '123',
 
1093
                  }
 
1094
        req = self._makeOne(environ)
 
1095
        req.headers = {'Qux': 'Spam'}
 
1096
        self.assertEqual(req.headers,
 
1097
                        {'Qux': 'Spam'})
 
1098
        self.assertEqual(environ, {'HTTP_QUX': 'Spam'})
 
1099
 
 
1100
    def test_no_headers_deleter(self):
 
1101
        CONTENT_TYPE = 'application/xml+foobar;charset="utf8"'
 
1102
        environ = {'CONTENT_TYPE': CONTENT_TYPE,
 
1103
                   'CONTENT_LENGTH': '123',
 
1104
                  }
 
1105
        req = self._makeOne(environ)
 
1106
        def _test():
 
1107
            del req.headers
 
1108
        self.assertRaises(AttributeError, _test)
 
1109
 
 
1110
    def test_client_addr_xff_singleval(self):
 
1111
        environ = {
 
1112
                   'HTTP_X_FORWARDED_FOR': '192.168.1.1',
 
1113
                  }
 
1114
        req = self._makeOne(environ)
 
1115
        self.assertEqual(req.client_addr, '192.168.1.1')
 
1116
 
 
1117
    def test_client_addr_xff_multival(self):
 
1118
        environ = {
 
1119
                   'HTTP_X_FORWARDED_FOR': '192.168.1.1, 192.168.1.2',
 
1120
                  }
 
1121
        req = self._makeOne(environ)
 
1122
        self.assertEqual(req.client_addr, '192.168.1.1')
 
1123
 
 
1124
    def test_client_addr_prefers_xff(self):
 
1125
        environ = {'REMOTE_ADDR': '192.168.1.2',
 
1126
                   'HTTP_X_FORWARDED_FOR': '192.168.1.1',
 
1127
                  }
 
1128
        req = self._makeOne(environ)
 
1129
        self.assertEqual(req.client_addr, '192.168.1.1')
 
1130
 
 
1131
    def test_client_addr_no_xff(self):
 
1132
        environ = {'REMOTE_ADDR': '192.168.1.2',
 
1133
                  }
 
1134
        req = self._makeOne(environ)
 
1135
        self.assertEqual(req.client_addr, '192.168.1.2')
 
1136
 
 
1137
    def test_client_addr_no_xff_no_remote_addr(self):
 
1138
        environ = {}
 
1139
        req = self._makeOne(environ)
 
1140
        self.assertEqual(req.client_addr, None)
 
1141
 
 
1142
    def test_host_port_w_http_host_and_no_port(self):
 
1143
        environ = {'wsgi.url_scheme': 'http',
 
1144
                   'HTTP_HOST': 'example.com',
 
1145
                  }
 
1146
        req = self._makeOne(environ)
 
1147
        self.assertEqual(req.host_port, '80')
 
1148
 
 
1149
    def test_host_port_w_http_host_and_standard_port(self):
 
1150
        environ = {'wsgi.url_scheme': 'http',
 
1151
                   'HTTP_HOST': 'example.com:80',
 
1152
                  }
 
1153
        req = self._makeOne(environ)
 
1154
        self.assertEqual(req.host_port, '80')
 
1155
 
 
1156
    def test_host_port_w_http_host_and_oddball_port(self):
 
1157
        environ = {'wsgi.url_scheme': 'http',
 
1158
                   'HTTP_HOST': 'example.com:8888',
 
1159
                  }
 
1160
        req = self._makeOne(environ)
 
1161
        self.assertEqual(req.host_port, '8888')
 
1162
 
 
1163
    def test_host_port_w_http_host_https_and_no_port(self):
 
1164
        environ = {'wsgi.url_scheme': 'https',
 
1165
                   'HTTP_HOST': 'example.com',
 
1166
                  }
 
1167
        req = self._makeOne(environ)
 
1168
        self.assertEqual(req.host_port, '443')
 
1169
 
 
1170
    def test_host_port_w_http_host_https_and_standard_port(self):
 
1171
        environ = {'wsgi.url_scheme': 'https',
 
1172
                   'HTTP_HOST': 'example.com:443',
 
1173
                  }
 
1174
        req = self._makeOne(environ)
 
1175
        self.assertEqual(req.host_port, '443')
 
1176
 
 
1177
    def test_host_port_w_http_host_https_and_oddball_port(self):
 
1178
        environ = {'wsgi.url_scheme': 'https',
 
1179
                   'HTTP_HOST': 'example.com:8888',
 
1180
                  }
 
1181
        req = self._makeOne(environ)
 
1182
        self.assertEqual(req.host_port, '8888')
 
1183
 
 
1184
    def test_host_port_wo_http_host(self):
 
1185
        environ = {'wsgi.url_scheme': 'https',
 
1186
                   'SERVER_PORT': '4333',
 
1187
                  }
 
1188
        req = self._makeOne(environ)
 
1189
        self.assertEqual(req.host_port, '4333')
 
1190
 
 
1191
    def test_host_url_w_http_host_and_no_port(self):
 
1192
        environ = {'wsgi.url_scheme': 'http',
 
1193
                   'HTTP_HOST': 'example.com',
 
1194
                  }
 
1195
        req = self._makeOne(environ)
 
1196
        self.assertEqual(req.host_url, 'http://example.com')
 
1197
 
 
1198
    def test_host_url_w_http_host_and_standard_port(self):
 
1199
        environ = {'wsgi.url_scheme': 'http',
 
1200
                   'HTTP_HOST': 'example.com:80',
 
1201
                  }
 
1202
        req = self._makeOne(environ)
 
1203
        self.assertEqual(req.host_url, 'http://example.com')
 
1204
 
 
1205
    def test_host_url_w_http_host_and_oddball_port(self):
 
1206
        environ = {'wsgi.url_scheme': 'http',
 
1207
                   'HTTP_HOST': 'example.com:8888',
 
1208
                  }
 
1209
        req = self._makeOne(environ)
 
1210
        self.assertEqual(req.host_url, 'http://example.com:8888')
 
1211
 
 
1212
    def test_host_url_w_http_host_https_and_no_port(self):
 
1213
        environ = {'wsgi.url_scheme': 'https',
 
1214
                   'HTTP_HOST': 'example.com',
 
1215
                  }
 
1216
        req = self._makeOne(environ)
 
1217
        self.assertEqual(req.host_url, 'https://example.com')
 
1218
 
 
1219
    def test_host_url_w_http_host_https_and_standard_port(self):
 
1220
        environ = {'wsgi.url_scheme': 'https',
 
1221
                   'HTTP_HOST': 'example.com:443',
 
1222
                  }
 
1223
        req = self._makeOne(environ)
 
1224
        self.assertEqual(req.host_url, 'https://example.com')
 
1225
 
 
1226
    def test_host_url_w_http_host_https_and_oddball_port(self):
 
1227
        environ = {'wsgi.url_scheme': 'https',
 
1228
                   'HTTP_HOST': 'example.com:4333',
 
1229
                  }
 
1230
        req = self._makeOne(environ)
 
1231
        self.assertEqual(req.host_url, 'https://example.com:4333')
 
1232
 
 
1233
    def test_host_url_wo_http_host(self):
 
1234
        environ = {'wsgi.url_scheme': 'https',
 
1235
                   'SERVER_NAME': 'example.com',
 
1236
                   'SERVER_PORT': '4333',
 
1237
                  }
 
1238
        req = self._makeOne(environ)
 
1239
        self.assertEqual(req.host_url, 'https://example.com:4333')
 
1240
 
 
1241
    def test_application_url(self):
 
1242
        inst = self._blankOne('/%C3%AB')
 
1243
        inst.script_name = text_(b'/\xc3\xab', 'utf-8')
 
1244
        app_url = inst.application_url
 
1245
        self.assertEqual(app_url.__class__, str)
 
1246
        self.assertEqual(app_url, 'http://localhost/%C3%AB')
 
1247
 
 
1248
    def test_path_url(self):
 
1249
        inst = self._blankOne('/%C3%AB')
 
1250
        inst.script_name = text_(b'/\xc3\xab', 'utf-8')
 
1251
        app_url = inst.path_url
 
1252
        self.assertEqual(app_url.__class__, str)
 
1253
        self.assertEqual(app_url, 'http://localhost/%C3%AB/%C3%AB')
 
1254
 
 
1255
    def test_path(self):
 
1256
        inst = self._blankOne('/%C3%AB')
 
1257
        inst.script_name = text_(b'/\xc3\xab', 'utf-8')
 
1258
        app_url = inst.path
 
1259
        self.assertEqual(app_url.__class__, str)
 
1260
        self.assertEqual(app_url, '/%C3%AB/%C3%AB')
 
1261
 
 
1262
    def test_path_qs_no_qs(self):
 
1263
        environ = {'wsgi.url_scheme': 'http',
 
1264
                   'SERVER_NAME': 'example.com',
 
1265
                   'SERVER_PORT': '80',
 
1266
                   'SCRIPT_NAME': '/script',
 
1267
                   'PATH_INFO': '/path/info',
 
1268
                  }
 
1269
        req = self._makeOne(environ)
 
1270
        self.assertEqual(req.path_qs, '/script/path/info')
 
1271
 
 
1272
    def test_path_qs_w_qs(self):
 
1273
        environ = {'wsgi.url_scheme': 'http',
 
1274
                   'SERVER_NAME': 'example.com',
 
1275
                   'SERVER_PORT': '80',
 
1276
                   'SCRIPT_NAME': '/script',
 
1277
                   'PATH_INFO': '/path/info',
 
1278
                   'QUERY_STRING': 'foo=bar&baz=bam'
 
1279
                  }
 
1280
        req = self._makeOne(environ)
 
1281
        self.assertEqual(req.path_qs, '/script/path/info?foo=bar&baz=bam')
 
1282
 
 
1283
    def test_url_no_qs(self):
 
1284
        environ = {'wsgi.url_scheme': 'http',
 
1285
                   'SERVER_NAME': 'example.com',
 
1286
                   'SERVER_PORT': '80',
 
1287
                   'SCRIPT_NAME': '/script',
 
1288
                   'PATH_INFO': '/path/info',
 
1289
                  }
 
1290
        req = self._makeOne(environ)
 
1291
        self.assertEqual(req.url, 'http://example.com/script/path/info')
 
1292
 
 
1293
    def test_url_w_qs(self):
 
1294
        environ = {'wsgi.url_scheme': 'http',
 
1295
                   'SERVER_NAME': 'example.com',
 
1296
                   'SERVER_PORT': '80',
 
1297
                   'SCRIPT_NAME': '/script',
 
1298
                   'PATH_INFO': '/path/info',
 
1299
                   'QUERY_STRING': 'foo=bar&baz=bam'
 
1300
                  }
 
1301
        req = self._makeOne(environ)
 
1302
        self.assertEqual(req.url,
 
1303
                         'http://example.com/script/path/info?foo=bar&baz=bam')
 
1304
 
 
1305
    def test_relative_url_to_app_true_wo_leading_slash(self):
 
1306
        environ = {'wsgi.url_scheme': 'http',
 
1307
                   'SERVER_NAME': 'example.com',
 
1308
                   'SERVER_PORT': '80',
 
1309
                   'SCRIPT_NAME': '/script',
 
1310
                   'PATH_INFO': '/path/info',
 
1311
                   'QUERY_STRING': 'foo=bar&baz=bam'
 
1312
                  }
 
1313
        req = self._makeOne(environ)
 
1314
        self.assertEqual(req.relative_url('other/page', True),
 
1315
                         'http://example.com/script/other/page')
 
1316
 
 
1317
    def test_relative_url_to_app_true_w_leading_slash(self):
 
1318
        environ = {'wsgi.url_scheme': 'http',
 
1319
                   'SERVER_NAME': 'example.com',
 
1320
                   'SERVER_PORT': '80',
 
1321
                   'SCRIPT_NAME': '/script',
 
1322
                   'PATH_INFO': '/path/info',
 
1323
                   'QUERY_STRING': 'foo=bar&baz=bam'
 
1324
                  }
 
1325
        req = self._makeOne(environ)
 
1326
        self.assertEqual(req.relative_url('/other/page', True),
 
1327
                         'http://example.com/other/page')
 
1328
 
 
1329
    def test_relative_url_to_app_false_other_w_leading_slash(self):
 
1330
        environ = {'wsgi.url_scheme': 'http',
 
1331
                   'SERVER_NAME': 'example.com',
 
1332
                   'SERVER_PORT': '80',
 
1333
                   'SCRIPT_NAME': '/script',
 
1334
                   'PATH_INFO': '/path/info',
 
1335
                   'QUERY_STRING': 'foo=bar&baz=bam'
 
1336
                  }
 
1337
        req = self._makeOne(environ)
 
1338
        self.assertEqual(req.relative_url('/other/page', False),
 
1339
                         'http://example.com/other/page')
 
1340
 
 
1341
    def test_relative_url_to_app_false_other_wo_leading_slash(self):
 
1342
        environ = {'wsgi.url_scheme': 'http',
 
1343
                   'SERVER_NAME': 'example.com',
 
1344
                   'SERVER_PORT': '80',
 
1345
                   'SCRIPT_NAME': '/script',
 
1346
                   'PATH_INFO': '/path/info',
 
1347
                   'QUERY_STRING': 'foo=bar&baz=bam'
 
1348
                  }
 
1349
        req = self._makeOne(environ)
 
1350
        self.assertEqual(req.relative_url('other/page', False),
 
1351
                         'http://example.com/script/path/other/page')
 
1352
 
 
1353
    def test_path_info_pop_empty(self):
 
1354
        environ = {'wsgi.url_scheme': 'http',
 
1355
                   'SERVER_NAME': 'example.com',
 
1356
                   'SERVER_PORT': '80',
 
1357
                   'SCRIPT_NAME': '/script',
 
1358
                   'PATH_INFO': '',
 
1359
                  }
 
1360
        req = self._makeOne(environ)
 
1361
        popped = req.path_info_pop()
 
1362
        self.assertEqual(popped, None)
 
1363
        self.assertEqual(environ['SCRIPT_NAME'], '/script')
 
1364
 
 
1365
    def test_path_info_pop_just_leading_slash(self):
 
1366
        environ = {'wsgi.url_scheme': 'http',
 
1367
                   'SERVER_NAME': 'example.com',
 
1368
                   'SERVER_PORT': '80',
 
1369
                   'SCRIPT_NAME': '/script',
 
1370
                   'PATH_INFO': '/',
 
1371
                  }
 
1372
        req = self._makeOne(environ)
 
1373
        popped = req.path_info_pop()
 
1374
        self.assertEqual(popped, '')
 
1375
        self.assertEqual(environ['SCRIPT_NAME'], '/script/')
 
1376
        self.assertEqual(environ['PATH_INFO'], '')
 
1377
 
 
1378
    def test_path_info_pop_non_empty_no_pattern(self):
 
1379
        environ = {'wsgi.url_scheme': 'http',
 
1380
                   'SERVER_NAME': 'example.com',
 
1381
                   'SERVER_PORT': '80',
 
1382
                   'SCRIPT_NAME': '/script',
 
1383
                   'PATH_INFO': '/path/info',
 
1384
                  }
 
1385
        req = self._makeOne(environ)
 
1386
        popped = req.path_info_pop()
 
1387
        self.assertEqual(popped, 'path')
 
1388
        self.assertEqual(environ['SCRIPT_NAME'], '/script/path')
 
1389
        self.assertEqual(environ['PATH_INFO'], '/info')
 
1390
 
 
1391
    def test_path_info_pop_non_empty_w_pattern_miss(self):
 
1392
        import re
 
1393
        PATTERN = re.compile('miss')
 
1394
        environ = {'wsgi.url_scheme': 'http',
 
1395
                   'SERVER_NAME': 'example.com',
 
1396
                   'SERVER_PORT': '80',
 
1397
                   'SCRIPT_NAME': '/script',
 
1398
                   'PATH_INFO': '/path/info',
 
1399
                  }
 
1400
        req = self._makeOne(environ)
 
1401
        popped = req.path_info_pop(PATTERN)
 
1402
        self.assertEqual(popped, None)
 
1403
        self.assertEqual(environ['SCRIPT_NAME'], '/script')
 
1404
        self.assertEqual(environ['PATH_INFO'], '/path/info')
 
1405
 
 
1406
    def test_path_info_pop_non_empty_w_pattern_hit(self):
 
1407
        import re
 
1408
        PATTERN = re.compile('path')
 
1409
        environ = {'wsgi.url_scheme': 'http',
 
1410
                   'SERVER_NAME': 'example.com',
 
1411
                   'SERVER_PORT': '80',
 
1412
                   'SCRIPT_NAME': '/script',
 
1413
                   'PATH_INFO': '/path/info',
 
1414
                  }
 
1415
        req = self._makeOne(environ)
 
1416
        popped = req.path_info_pop(PATTERN)
 
1417
        self.assertEqual(popped, 'path')
 
1418
        self.assertEqual(environ['SCRIPT_NAME'], '/script/path')
 
1419
        self.assertEqual(environ['PATH_INFO'], '/info')
 
1420
 
 
1421
    def test_path_info_pop_skips_empty_elements(self):
 
1422
        environ = {'wsgi.url_scheme': 'http',
 
1423
                   'SERVER_NAME': 'example.com',
 
1424
                   'SERVER_PORT': '80',
 
1425
                   'SCRIPT_NAME': '/script',
 
1426
                   'PATH_INFO': '//path/info',
 
1427
                  }
 
1428
        req = self._makeOne(environ)
 
1429
        popped = req.path_info_pop()
 
1430
        self.assertEqual(popped, 'path')
 
1431
        self.assertEqual(environ['SCRIPT_NAME'], '/script//path')
 
1432
        self.assertEqual(environ['PATH_INFO'], '/info')
 
1433
 
 
1434
    def test_path_info_peek_empty(self):
 
1435
        environ = {'wsgi.url_scheme': 'http',
 
1436
                   'SERVER_NAME': 'example.com',
 
1437
                   'SERVER_PORT': '80',
 
1438
                   'SCRIPT_NAME': '/script',
 
1439
                   'PATH_INFO': '',
 
1440
                  }
 
1441
        req = self._makeOne(environ)
 
1442
        peeked = req.path_info_peek()
 
1443
        self.assertEqual(peeked, None)
 
1444
        self.assertEqual(environ['SCRIPT_NAME'], '/script')
 
1445
        self.assertEqual(environ['PATH_INFO'], '')
 
1446
 
 
1447
    def test_path_info_peek_just_leading_slash(self):
 
1448
        environ = {'wsgi.url_scheme': 'http',
 
1449
                   'SERVER_NAME': 'example.com',
 
1450
                   'SERVER_PORT': '80',
 
1451
                   'SCRIPT_NAME': '/script',
 
1452
                   'PATH_INFO': '/',
 
1453
                  }
 
1454
        req = self._makeOne(environ)
 
1455
        peeked = req.path_info_peek()
 
1456
        self.assertEqual(peeked, '')
 
1457
        self.assertEqual(environ['SCRIPT_NAME'], '/script')
 
1458
        self.assertEqual(environ['PATH_INFO'], '/')
 
1459
 
 
1460
    def test_path_info_peek_non_empty(self):
 
1461
        environ = {'wsgi.url_scheme': 'http',
 
1462
                   'SERVER_NAME': 'example.com',
 
1463
                   'SERVER_PORT': '80',
 
1464
                   'SCRIPT_NAME': '/script',
 
1465
                   'PATH_INFO': '/path',
 
1466
                  }
 
1467
        req = self._makeOne(environ)
 
1468
        peeked = req.path_info_peek()
 
1469
        self.assertEqual(peeked, 'path')
 
1470
        self.assertEqual(environ['SCRIPT_NAME'], '/script')
 
1471
        self.assertEqual(environ['PATH_INFO'], '/path')
 
1472
 
 
1473
    def test_is_xhr_no_header(self):
 
1474
        req = self._makeOne({})
 
1475
        self.assertTrue(not req.is_xhr)
 
1476
 
 
1477
    def test_is_xhr_header_miss(self):
 
1478
        environ = {'HTTP_X_REQUESTED_WITH': 'notAnXMLHTTPRequest'}
 
1479
        req = self._makeOne(environ)
 
1480
        self.assertTrue(not req.is_xhr)
 
1481
 
 
1482
    def test_is_xhr_header_hit(self):
 
1483
        environ = {'HTTP_X_REQUESTED_WITH': 'XMLHttpRequest'}
 
1484
        req = self._makeOne(environ)
 
1485
        self.assertTrue(req.is_xhr)
 
1486
 
 
1487
    # host
 
1488
    def test_host_getter_w_HTTP_HOST(self):
 
1489
        environ = {'HTTP_HOST': 'example.com:8888'}
 
1490
        req = self._makeOne(environ)
 
1491
        self.assertEqual(req.host, 'example.com:8888')
 
1492
 
 
1493
    def test_host_getter_wo_HTTP_HOST(self):
 
1494
        environ = {'SERVER_NAME': 'example.com',
 
1495
                   'SERVER_PORT': '8888'}
 
1496
        req = self._makeOne(environ)
 
1497
        self.assertEqual(req.host, 'example.com:8888')
 
1498
 
 
1499
    def test_host_setter(self):
 
1500
        environ = {}
 
1501
        req = self._makeOne(environ)
 
1502
        req.host = 'example.com:8888'
 
1503
        self.assertEqual(environ['HTTP_HOST'], 'example.com:8888')
 
1504
 
 
1505
    def test_host_deleter_hit(self):
 
1506
        environ = {'HTTP_HOST': 'example.com:8888'}
 
1507
        req = self._makeOne(environ)
 
1508
        del req.host
 
1509
        self.assertTrue('HTTP_HOST' not in environ)
 
1510
 
 
1511
    def test_host_deleter_miss(self):
 
1512
        environ = {}
 
1513
        req = self._makeOne(environ)
 
1514
        del req.host # doesn't raise
 
1515
 
 
1516
    def test_encget_raises_without_default(self):
 
1517
        inst = self._makeOne({})
 
1518
        self.assertRaises(KeyError, inst.encget, 'a')
 
1519
 
 
1520
    def test_encget_doesnt_raises_with_default(self):
 
1521
        inst = self._makeOne({})
 
1522
        self.assertEqual(inst.encget('a', None), None)
 
1523
 
 
1524
    def test_encget_with_encattr(self):
 
1525
        if PY3:
 
1526
            val = b'\xc3\xab'.decode('latin-1')
 
1527
        else:
 
1528
            val = b'\xc3\xab'
 
1529
        inst = self._makeOne({'a':val})
 
1530
        self.assertEqual(inst.encget('a', encattr='url_encoding'),
 
1531
                         text_(b'\xc3\xab', 'utf-8'))
 
1532
 
 
1533
    def test_encget_with_encattr_latin_1(self):
 
1534
        if PY3:
 
1535
            val = b'\xc3\xab'.decode('latin-1')
 
1536
        else:
 
1537
            val = b'\xc3\xab'
 
1538
        inst = self._makeOne({'a':val})
 
1539
        inst.my_encoding = 'latin-1'
 
1540
        self.assertEqual(inst.encget('a', encattr='my_encoding'),
 
1541
                         text_(b'\xc3\xab', 'latin-1'))
 
1542
 
 
1543
    def test_encget_no_encattr(self):
 
1544
        if PY3:
 
1545
            val = b'\xc3\xab'.decode('latin-1')
 
1546
        else:
 
1547
            val = b'\xc3\xab'
 
1548
        inst = self._makeOne({'a':val})
 
1549
        self.assertEqual(inst.encget('a'), val)
 
1550
 
 
1551
    def test_relative_url(self):
 
1552
        inst = self._blankOne('/%C3%AB/c')
 
1553
        result = inst.relative_url('a')
 
1554
        self.assertEqual(result.__class__, str)
 
1555
        self.assertEqual(result, 'http://localhost/%C3%AB/a')
 
1556
 
 
1557
    def test_header_getter(self):
 
1558
        if PY3:
 
1559
            val = b'abc'.decode('latin-1')
 
1560
        else:
 
1561
            val = b'abc'
 
1562
        inst = self._makeOne({'HTTP_FLUB':val})
 
1563
        result = inst.headers['Flub']
 
1564
        self.assertEqual(result.__class__, str)
 
1565
        self.assertEqual(result, 'abc')
 
1566
 
 
1567
    def test_json_body(self):
 
1568
        inst = self._makeOne({})
 
1569
        inst.body = b'{"a":"1"}'
 
1570
        self.assertEqual(inst.json_body, {'a':'1'})
 
1571
        inst.json_body = {'a': '2'}
 
1572
        self.assertEqual(inst.body, b'{"a":"2"}')
 
1573
 
 
1574
    def test_host_get(self):
 
1575
        inst = self._makeOne({'HTTP_HOST':'example.com'})
 
1576
        result = inst.host
 
1577
        self.assertEqual(result.__class__, str)
 
1578
        self.assertEqual(result, 'example.com')
 
1579
 
 
1580
    def test_host_get_w_no_http_host(self):
 
1581
        inst = self._makeOne({'SERVER_NAME':'example.com', 'SERVER_PORT':'80'})
 
1582
        result = inst.host
 
1583
        self.assertEqual(result.__class__, str)
 
1584
        self.assertEqual(result, 'example.com:80')
 
1585
 
 
1586
class TestLegacyRequest(unittest.TestCase):
 
1587
    # tests of methods of a bytesrequest which deal with http environment vars
 
1588
    def _getTargetClass(self):
 
1589
        from webob.request import LegacyRequest
 
1590
        return LegacyRequest
 
1591
 
 
1592
    def _makeOne(self, *arg, **kw):
 
1593
        cls = self._getTargetClass()
 
1594
        return cls(*arg, **kw)
 
1595
 
 
1596
    def _blankOne(self, *arg, **kw):
 
1597
        cls = self._getTargetClass()
 
1598
        return cls.blank(*arg, **kw)
 
1599
 
 
1600
    def test_method(self):
 
1601
        environ = {'REQUEST_METHOD': 'OPTIONS',
 
1602
                  }
 
1603
        req = self._makeOne(environ)
 
1604
        self.assertEqual(req.method, 'OPTIONS')
 
1605
 
 
1606
    def test_http_version(self):
 
1607
        environ = {'SERVER_PROTOCOL': '1.1',
 
1608
                  }
 
1609
        req = self._makeOne(environ)
 
1610
        self.assertEqual(req.http_version, '1.1')
 
1611
 
 
1612
    def test_script_name(self):
 
1613
        environ = {'SCRIPT_NAME': '/script',
 
1614
                  }
 
1615
        req = self._makeOne(environ)
 
1616
        self.assertEqual(req.script_name, '/script')
 
1617
 
 
1618
    def test_path_info(self):
 
1619
        environ = {'PATH_INFO': '/path/info',
 
1620
                  }
 
1621
        req = self._makeOne(environ)
 
1622
        self.assertEqual(req.path_info, '/path/info')
 
1623
 
 
1624
    def test_content_length_getter(self):
 
1625
        environ = {'CONTENT_LENGTH': '1234',
 
1626
                  }
 
1627
        req = self._makeOne(environ)
 
1628
        self.assertEqual(req.content_length, 1234)
 
1629
 
 
1630
    def test_content_length_setter_w_str(self):
 
1631
        environ = {'CONTENT_LENGTH': '1234',
 
1632
                  }
 
1633
        req = self._makeOne(environ)
 
1634
        req.content_length = '3456'
 
1635
        self.assertEqual(req.content_length, 3456)
 
1636
 
 
1637
    def test_remote_user(self):
 
1638
        environ = {'REMOTE_USER': 'phred',
 
1639
                  }
 
1640
        req = self._makeOne(environ)
 
1641
        self.assertEqual(req.remote_user, 'phred')
 
1642
 
 
1643
    def test_remote_addr(self):
 
1644
        environ = {'REMOTE_ADDR': '1.2.3.4',
 
1645
                  }
 
1646
        req = self._makeOne(environ)
 
1647
        self.assertEqual(req.remote_addr, '1.2.3.4')
 
1648
 
 
1649
    def test_query_string(self):
 
1650
        environ = {'QUERY_STRING': 'foo=bar&baz=bam',
 
1651
                  }
 
1652
        req = self._makeOne(environ)
 
1653
        self.assertEqual(req.query_string, 'foo=bar&baz=bam')
 
1654
 
 
1655
    def test_server_name(self):
 
1656
        environ = {'SERVER_NAME': 'somehost.tld',
 
1657
                  }
 
1658
        req = self._makeOne(environ)
 
1659
        self.assertEqual(req.server_name, 'somehost.tld')
 
1660
 
 
1661
    def test_server_port_getter(self):
 
1662
        environ = {'SERVER_PORT': '6666',
 
1663
                  }
 
1664
        req = self._makeOne(environ)
 
1665
        self.assertEqual(req.server_port, 6666)
 
1666
 
 
1667
    def test_server_port_setter_with_string(self):
 
1668
        environ = {'SERVER_PORT': '6666',
 
1669
                  }
 
1670
        req = self._makeOne(environ)
 
1671
        req.server_port = '6667'
 
1672
        self.assertEqual(req.server_port, 6667)
 
1673
 
 
1674
    def test_uscript_name(self):
 
1675
        environ = {'SCRIPT_NAME': '/script',
 
1676
                  }
 
1677
        req = self._makeOne(environ)
 
1678
        self.assertTrue(isinstance(req.uscript_name, text_type))
 
1679
        result = req.uscript_name
 
1680
        self.assertEqual(result.__class__, text_type)
 
1681
        self.assertEqual(result, '/script')
 
1682
 
 
1683
    def test_upath_info(self):
 
1684
        environ = {'PATH_INFO': '/path/info',
 
1685
                  }
 
1686
        req = self._makeOne(environ)
 
1687
        result = req.upath_info
 
1688
        self.assertTrue(isinstance(result, text_type))
 
1689
        self.assertEqual(result, '/path/info')
 
1690
 
 
1691
    def test_upath_info_set_unicode(self):
 
1692
        environ = {'PATH_INFO': '/path/info',
 
1693
                  }
 
1694
        req = self._makeOne(environ)
 
1695
        req.upath_info = text_('/another')
 
1696
        result = req.upath_info
 
1697
        self.assertTrue(isinstance(result, text_type))
 
1698
        self.assertEqual(result, '/another')
 
1699
 
 
1700
    def test_content_type_getter_no_parameters(self):
 
1701
        environ = {'CONTENT_TYPE': 'application/xml+foobar',
 
1702
                  }
 
1703
        req = self._makeOne(environ)
 
1704
        self.assertEqual(req.content_type, 'application/xml+foobar')
 
1705
 
 
1706
    def test_content_type_getter_w_parameters(self):
 
1707
        environ = {'CONTENT_TYPE': 'application/xml+foobar;charset="utf8"',
 
1708
                  }
 
1709
        req = self._makeOne(environ)
 
1710
        self.assertEqual(req.content_type, 'application/xml+foobar')
 
1711
 
 
1712
    def test_content_type_setter_w_None(self):
 
1713
        environ = {'CONTENT_TYPE': 'application/xml+foobar;charset="utf8"',
 
1714
                  }
 
1715
        req = self._makeOne(environ)
 
1716
        req.content_type = None
 
1717
        self.assertEqual(req.content_type, '')
 
1718
        self.assertTrue('CONTENT_TYPE' not in environ)
 
1719
 
 
1720
    def test_content_type_setter_existing_paramter_no_new_paramter(self):
 
1721
        environ = {'CONTENT_TYPE': 'application/xml+foobar;charset="utf8"',
 
1722
                  }
 
1723
        req = self._makeOne(environ)
 
1724
        req.content_type = 'text/xml'
 
1725
        self.assertEqual(req.content_type, 'text/xml')
 
1726
        self.assertEqual(environ['CONTENT_TYPE'], 'text/xml;charset="utf8"')
 
1727
 
 
1728
    def test_content_type_deleter_clears_environ_value(self):
 
1729
        environ = {'CONTENT_TYPE': 'application/xml+foobar;charset="utf8"',
 
1730
                  }
 
1731
        req = self._makeOne(environ)
 
1732
        del req.content_type
 
1733
        self.assertEqual(req.content_type, '')
 
1734
        self.assertTrue('CONTENT_TYPE' not in environ)
 
1735
 
 
1736
    def test_content_type_deleter_no_environ_value(self):
 
1737
        environ = {}
 
1738
        req = self._makeOne(environ)
 
1739
        del req.content_type
 
1740
        self.assertEqual(req.content_type, '')
 
1741
        self.assertTrue('CONTENT_TYPE' not in environ)
 
1742
 
 
1743
    def test_headers_getter(self):
 
1744
        CONTENT_TYPE = 'application/xml+foobar;charset="utf8"'
 
1745
        environ = {'CONTENT_TYPE': CONTENT_TYPE,
 
1746
                   'CONTENT_LENGTH': '123',
 
1747
                  }
 
1748
        req = self._makeOne(environ)
 
1749
        headers = req.headers
 
1750
        self.assertEqual(headers,
 
1751
                        {'Content-Type':CONTENT_TYPE,
 
1752
                         'Content-Length': '123'})
 
1753
 
 
1754
    def test_headers_setter(self):
 
1755
        CONTENT_TYPE = 'application/xml+foobar;charset="utf8"'
 
1756
        environ = {'CONTENT_TYPE': CONTENT_TYPE,
 
1757
                   'CONTENT_LENGTH': '123',
 
1758
                  }
 
1759
        req = self._makeOne(environ)
 
1760
        req.headers = {'Qux': 'Spam'}
 
1761
        self.assertEqual(req.headers,
 
1762
                        {'Qux': 'Spam'})
 
1763
        self.assertEqual(environ['HTTP_QUX'], native_('Spam'))
 
1764
        self.assertEqual(environ, {'HTTP_QUX': 'Spam'})
 
1765
 
 
1766
    def test_no_headers_deleter(self):
 
1767
        CONTENT_TYPE = 'application/xml+foobar;charset="utf8"'
 
1768
        environ = {'CONTENT_TYPE': CONTENT_TYPE,
 
1769
                   'CONTENT_LENGTH': '123',
 
1770
                  }
 
1771
        req = self._makeOne(environ)
 
1772
        def _test():
 
1773
            del req.headers
 
1774
        self.assertRaises(AttributeError, _test)
 
1775
 
 
1776
    def test_client_addr_xff_singleval(self):
 
1777
        environ = {
 
1778
                   'HTTP_X_FORWARDED_FOR': '192.168.1.1',
 
1779
                  }
 
1780
        req = self._makeOne(environ)
 
1781
        self.assertEqual(req.client_addr, '192.168.1.1')
 
1782
 
 
1783
    def test_client_addr_xff_multival(self):
 
1784
        environ = {
 
1785
                   'HTTP_X_FORWARDED_FOR': '192.168.1.1, 192.168.1.2',
 
1786
                  }
 
1787
        req = self._makeOne(environ)
 
1788
        self.assertEqual(req.client_addr, '192.168.1.1')
 
1789
 
 
1790
    def test_client_addr_prefers_xff(self):
 
1791
        environ = {'REMOTE_ADDR': '192.168.1.2',
 
1792
                   'HTTP_X_FORWARDED_FOR': '192.168.1.1',
 
1793
                  }
 
1794
        req = self._makeOne(environ)
 
1795
        self.assertEqual(req.client_addr, '192.168.1.1')
 
1796
 
 
1797
    def test_client_addr_no_xff(self):
 
1798
        environ = {'REMOTE_ADDR': '192.168.1.2',
 
1799
                  }
 
1800
        req = self._makeOne(environ)
 
1801
        self.assertEqual(req.client_addr, '192.168.1.2')
 
1802
 
 
1803
    def test_client_addr_no_xff_no_remote_addr(self):
 
1804
        environ = {}
 
1805
        req = self._makeOne(environ)
 
1806
        self.assertEqual(req.client_addr, None)
 
1807
 
 
1808
    def test_host_port_w_http_host_and_no_port(self):
 
1809
        environ = {'wsgi.url_scheme': 'http',
 
1810
                   'HTTP_HOST': 'example.com',
 
1811
                  }
 
1812
        req = self._makeOne(environ)
 
1813
        self.assertEqual(req.host_port, '80')
 
1814
 
 
1815
    def test_host_port_w_http_host_and_standard_port(self):
 
1816
        environ = {'wsgi.url_scheme': 'http',
 
1817
                   'HTTP_HOST': 'example.com:80',
 
1818
                  }
 
1819
        req = self._makeOne(environ)
 
1820
        self.assertEqual(req.host_port, '80')
 
1821
 
 
1822
    def test_host_port_w_http_host_and_oddball_port(self):
 
1823
        environ = {'wsgi.url_scheme': 'http',
 
1824
                   'HTTP_HOST': 'example.com:8888',
 
1825
                  }
 
1826
        req = self._makeOne(environ)
 
1827
        self.assertEqual(req.host_port, '8888')
 
1828
 
 
1829
    def test_host_port_w_http_host_https_and_no_port(self):
 
1830
        environ = {'wsgi.url_scheme': 'https',
 
1831
                   'HTTP_HOST': 'example.com',
 
1832
                  }
 
1833
        req = self._makeOne(environ)
 
1834
        self.assertEqual(req.host_port, '443')
 
1835
 
 
1836
    def test_host_port_w_http_host_https_and_standard_port(self):
 
1837
        environ = {'wsgi.url_scheme': 'https',
 
1838
                   'HTTP_HOST': 'example.com:443',
 
1839
                  }
 
1840
        req = self._makeOne(environ)
 
1841
        self.assertEqual(req.host_port, '443')
 
1842
 
 
1843
    def test_host_port_w_http_host_https_and_oddball_port(self):
 
1844
        environ = {'wsgi.url_scheme': 'https',
 
1845
                   'HTTP_HOST': 'example.com:8888',
 
1846
                  }
 
1847
        req = self._makeOne(environ)
 
1848
        self.assertEqual(req.host_port, '8888')
 
1849
 
 
1850
    def test_host_port_wo_http_host(self):
 
1851
        environ = {'wsgi.url_scheme': 'https',
 
1852
                   'SERVER_PORT': '4333',
 
1853
                  }
 
1854
        req = self._makeOne(environ)
 
1855
        self.assertEqual(req.host_port, '4333')
 
1856
 
 
1857
    def test_host_url_w_http_host_and_no_port(self):
 
1858
        environ = {'wsgi.url_scheme': 'http',
 
1859
                   'HTTP_HOST': 'example.com',
 
1860
                  }
 
1861
        req = self._makeOne(environ)
 
1862
        self.assertEqual(req.host_url, 'http://example.com')
 
1863
 
 
1864
    def test_host_url_w_http_host_and_standard_port(self):
 
1865
        environ = {'wsgi.url_scheme': 'http',
 
1866
                   'HTTP_HOST': 'example.com:80',
 
1867
                  }
 
1868
        req = self._makeOne(environ)
 
1869
        self.assertEqual(req.host_url, 'http://example.com')
 
1870
 
 
1871
    def test_host_url_w_http_host_and_oddball_port(self):
 
1872
        environ = {'wsgi.url_scheme': 'http',
 
1873
                   'HTTP_HOST': 'example.com:8888',
 
1874
                  }
 
1875
        req = self._makeOne(environ)
 
1876
        self.assertEqual(req.host_url, 'http://example.com:8888')
 
1877
 
 
1878
    def test_host_url_w_http_host_https_and_no_port(self):
 
1879
        environ = {'wsgi.url_scheme': 'https',
 
1880
                   'HTTP_HOST': 'example.com',
 
1881
                  }
 
1882
        req = self._makeOne(environ)
 
1883
        self.assertEqual(req.host_url, 'https://example.com')
 
1884
 
 
1885
    def test_host_url_w_http_host_https_and_standard_port(self):
 
1886
        environ = {'wsgi.url_scheme': 'https',
 
1887
                   'HTTP_HOST': 'example.com:443',
 
1888
                  }
 
1889
        req = self._makeOne(environ)
 
1890
        self.assertEqual(req.host_url, 'https://example.com')
 
1891
 
 
1892
    def test_host_url_w_http_host_https_and_oddball_port(self):
 
1893
        environ = {'wsgi.url_scheme': 'https',
 
1894
                   'HTTP_HOST': 'example.com:4333',
 
1895
                  }
 
1896
        req = self._makeOne(environ)
 
1897
        self.assertEqual(req.host_url, 'https://example.com:4333')
 
1898
 
 
1899
    def test_host_url_wo_http_host(self):
 
1900
        environ = {'wsgi.url_scheme': 'https',
 
1901
                   'SERVER_NAME': 'example.com',
 
1902
                   'SERVER_PORT': '4333',
 
1903
                  }
 
1904
        req = self._makeOne(environ)
 
1905
        self.assertEqual(req.host_url, 'https://example.com:4333')
 
1906
 
 
1907
    def test_application_url(self):
 
1908
        inst = self._blankOne('/%C3%AB')
 
1909
        inst.script_name = b'/\xc3\xab'
 
1910
        app_url = inst.application_url
 
1911
        if PY3: # pragma: no cover
 
1912
            # this result is why you should not use legacyrequest under py 3
 
1913
            self.assertEqual(app_url, 'http://localhost/%C3%83%C2%AB')
 
1914
        else:
 
1915
            self.assertEqual(app_url, 'http://localhost/%C3%AB')
 
1916
 
 
1917
    def test_path_url(self):
 
1918
        inst = self._blankOne('/%C3%AB')
 
1919
        inst.script_name = b'/\xc3\xab'
 
1920
        result = inst.path_url
 
1921
        if PY3: # pragma: no cover
 
1922
            # this result is why you should not use legacyrequest under py 3
 
1923
            self.assertEqual(result,
 
1924
                             'http://localhost/%C3%83%C2%AB/%C3%83%C2%AB')
 
1925
        else:
 
1926
            self.assertEqual(result, 'http://localhost/%C3%AB/%C3%AB')
 
1927
 
 
1928
    def test_path(self):
 
1929
        inst = self._blankOne('/%C3%AB')
 
1930
        inst.script_name = b'/\xc3\xab'
 
1931
        result = inst.path
 
1932
        if PY3: # pragma: no cover
 
1933
            # this result is why you should not use legacyrequest under py 3
 
1934
            self.assertEqual(result, '/%C3%83%C2%AB/%C3%83%C2%AB')
 
1935
        else:
 
1936
            self.assertEqual(result, '/%C3%AB/%C3%AB')
 
1937
 
 
1938
    def test_path_qs_no_qs(self):
 
1939
        environ = {'wsgi.url_scheme': 'http',
 
1940
                   'SERVER_NAME': 'example.com',
 
1941
                   'SERVER_PORT': '80',
 
1942
                   'SCRIPT_NAME': '/script',
 
1943
                   'PATH_INFO': '/path/info',
 
1944
                  }
 
1945
        req = self._makeOne(environ)
 
1946
        self.assertEqual(req.path_qs, '/script/path/info')
 
1947
 
 
1948
    def test_path_qs_w_qs(self):
 
1949
        environ = {'wsgi.url_scheme': 'http',
 
1950
                   'SERVER_NAME': 'example.com',
 
1951
                   'SERVER_PORT': '80',
 
1952
                   'SCRIPT_NAME': '/script',
 
1953
                   'PATH_INFO': '/path/info',
 
1954
                   'QUERY_STRING': 'foo=bar&baz=bam'
 
1955
                  }
 
1956
        req = self._makeOne(environ)
 
1957
        self.assertEqual(req.path_qs, '/script/path/info?foo=bar&baz=bam')
 
1958
 
 
1959
    def test_url_no_qs(self):
 
1960
        environ = {'wsgi.url_scheme': 'http',
 
1961
                   'SERVER_NAME': 'example.com',
 
1962
                   'SERVER_PORT': '80',
 
1963
                   'SCRIPT_NAME': '/script',
 
1964
                   'PATH_INFO': '/path/info',
 
1965
                  }
 
1966
        req = self._makeOne(environ)
 
1967
        self.assertEqual(req.url, 'http://example.com/script/path/info')
 
1968
 
 
1969
    def test_url_w_qs(self):
 
1970
        environ = {'wsgi.url_scheme': 'http',
 
1971
                   'SERVER_NAME': 'example.com',
 
1972
                   'SERVER_PORT': '80',
 
1973
                   'SCRIPT_NAME': '/script',
 
1974
                   'PATH_INFO': '/path/info',
 
1975
                   'QUERY_STRING': 'foo=bar&baz=bam'
 
1976
                  }
 
1977
        req = self._makeOne(environ)
 
1978
        self.assertEqual(req.url,
 
1979
                         'http://example.com/script/path/info?foo=bar&baz=bam')
 
1980
 
 
1981
    def test_relative_url_to_app_true_wo_leading_slash(self):
 
1982
        environ = {'wsgi.url_scheme': 'http',
 
1983
                   'SERVER_NAME': 'example.com',
 
1984
                   'SERVER_PORT': '80',
 
1985
                   'SCRIPT_NAME': '/script',
 
1986
                   'PATH_INFO': '/path/info',
 
1987
                   'QUERY_STRING': 'foo=bar&baz=bam'
 
1988
                  }
 
1989
        req = self._makeOne(environ)
 
1990
        self.assertEqual(req.relative_url('other/page', True),
 
1991
                         'http://example.com/script/other/page')
 
1992
 
 
1993
    def test_relative_url_to_app_true_w_leading_slash(self):
 
1994
        environ = {'wsgi.url_scheme': 'http',
 
1995
                   'SERVER_NAME': 'example.com',
 
1996
                   'SERVER_PORT': '80',
 
1997
                   'SCRIPT_NAME': '/script',
 
1998
                   'PATH_INFO': '/path/info',
 
1999
                   'QUERY_STRING': 'foo=bar&baz=bam'
 
2000
                  }
 
2001
        req = self._makeOne(environ)
 
2002
        self.assertEqual(req.relative_url('/other/page', True),
 
2003
                         'http://example.com/other/page')
 
2004
 
 
2005
    def test_relative_url_to_app_false_other_w_leading_slash(self):
 
2006
        environ = {'wsgi.url_scheme': 'http',
 
2007
                   'SERVER_NAME': 'example.com',
 
2008
                   'SERVER_PORT': '80',
 
2009
                   'SCRIPT_NAME': '/script',
 
2010
                   'PATH_INFO': '/path/info',
 
2011
                   'QUERY_STRING': 'foo=bar&baz=bam'
 
2012
                  }
 
2013
        req = self._makeOne(environ)
 
2014
        self.assertEqual(req.relative_url('/other/page', False),
 
2015
                         'http://example.com/other/page')
 
2016
 
 
2017
    def test_relative_url_to_app_false_other_wo_leading_slash(self):
 
2018
        environ = {'wsgi.url_scheme': 'http',
 
2019
                   'SERVER_NAME': 'example.com',
 
2020
                   'SERVER_PORT': '80',
 
2021
                   'SCRIPT_NAME': '/script',
 
2022
                   'PATH_INFO': '/path/info',
 
2023
                   'QUERY_STRING': 'foo=bar&baz=bam'
 
2024
                  }
 
2025
        req = self._makeOne(environ)
 
2026
        self.assertEqual(req.relative_url('other/page', False),
 
2027
                         'http://example.com/script/path/other/page')
 
2028
 
 
2029
    def test_path_info_pop_empty(self):
 
2030
        environ = {'wsgi.url_scheme': 'http',
 
2031
                   'SERVER_NAME': 'example.com',
 
2032
                   'SERVER_PORT': '80',
 
2033
                   'SCRIPT_NAME': '/script',
 
2034
                   'PATH_INFO': '',
 
2035
                  }
 
2036
        req = self._makeOne(environ)
 
2037
        popped = req.path_info_pop()
 
2038
        self.assertEqual(popped, None)
 
2039
        self.assertEqual(environ['SCRIPT_NAME'], '/script')
 
2040
 
 
2041
    def test_path_info_pop_just_leading_slash(self):
 
2042
        environ = {'wsgi.url_scheme': 'http',
 
2043
                   'SERVER_NAME': 'example.com',
 
2044
                   'SERVER_PORT': '80',
 
2045
                   'SCRIPT_NAME': '/script',
 
2046
                   'PATH_INFO': '/',
 
2047
                  }
 
2048
        req = self._makeOne(environ)
 
2049
        popped = req.path_info_pop()
 
2050
        self.assertEqual(popped, '')
 
2051
        self.assertEqual(environ['SCRIPT_NAME'], '/script/')
 
2052
        self.assertEqual(environ['PATH_INFO'], '')
 
2053
 
 
2054
    def test_path_info_pop_non_empty_no_pattern(self):
 
2055
        environ = {'wsgi.url_scheme': 'http',
 
2056
                   'SERVER_NAME': 'example.com',
 
2057
                   'SERVER_PORT': '80',
 
2058
                   'SCRIPT_NAME': '/script',
 
2059
                   'PATH_INFO': '/path/info',
 
2060
                  }
 
2061
        req = self._makeOne(environ)
 
2062
        popped = req.path_info_pop()
 
2063
        self.assertEqual(popped, 'path')
 
2064
        self.assertEqual(environ['SCRIPT_NAME'], '/script/path')
 
2065
        self.assertEqual(environ['PATH_INFO'], '/info')
 
2066
 
 
2067
    def test_path_info_pop_non_empty_w_pattern_miss(self):
 
2068
        import re
 
2069
        PATTERN = re.compile('miss')
 
2070
        environ = {'wsgi.url_scheme': 'http',
 
2071
                   'SERVER_NAME': 'example.com',
 
2072
                   'SERVER_PORT': '80',
 
2073
                   'SCRIPT_NAME': '/script',
 
2074
                   'PATH_INFO': '/path/info',
 
2075
                  }
 
2076
        req = self._makeOne(environ)
 
2077
        popped = req.path_info_pop(PATTERN)
 
2078
        self.assertEqual(popped, None)
 
2079
        self.assertEqual(environ['SCRIPT_NAME'], '/script')
 
2080
        self.assertEqual(environ['PATH_INFO'], '/path/info')
 
2081
 
 
2082
    def test_path_info_pop_non_empty_w_pattern_hit(self):
 
2083
        import re
 
2084
        PATTERN = re.compile('path')
 
2085
        environ = {'wsgi.url_scheme': 'http',
 
2086
                   'SERVER_NAME': 'example.com',
 
2087
                   'SERVER_PORT': '80',
 
2088
                   'SCRIPT_NAME': '/script',
 
2089
                   'PATH_INFO': '/path/info',
 
2090
                  }
 
2091
        req = self._makeOne(environ)
 
2092
        popped = req.path_info_pop(PATTERN)
 
2093
        self.assertEqual(popped, 'path')
 
2094
        self.assertEqual(environ['SCRIPT_NAME'], '/script/path')
 
2095
        self.assertEqual(environ['PATH_INFO'], '/info')
 
2096
 
 
2097
    def test_path_info_pop_skips_empty_elements(self):
 
2098
        environ = {'wsgi.url_scheme': 'http',
 
2099
                   'SERVER_NAME': 'example.com',
 
2100
                   'SERVER_PORT': '80',
 
2101
                   'SCRIPT_NAME': '/script',
 
2102
                   'PATH_INFO': '//path/info',
 
2103
                  }
 
2104
        req = self._makeOne(environ)
 
2105
        popped = req.path_info_pop()
 
2106
        self.assertEqual(popped, 'path')
 
2107
        self.assertEqual(environ['SCRIPT_NAME'], '/script//path')
 
2108
        self.assertEqual(environ['PATH_INFO'], '/info')
 
2109
 
 
2110
    def test_path_info_peek_empty(self):
 
2111
        environ = {'wsgi.url_scheme': 'http',
 
2112
                   'SERVER_NAME': 'example.com',
 
2113
                   'SERVER_PORT': '80',
 
2114
                   'SCRIPT_NAME': '/script',
 
2115
                   'PATH_INFO': '',
 
2116
                  }
 
2117
        req = self._makeOne(environ)
 
2118
        peeked = req.path_info_peek()
 
2119
        self.assertEqual(peeked, None)
 
2120
        self.assertEqual(environ['SCRIPT_NAME'], '/script')
 
2121
        self.assertEqual(environ['PATH_INFO'], '')
 
2122
 
 
2123
    def test_path_info_peek_just_leading_slash(self):
 
2124
        environ = {'wsgi.url_scheme': 'http',
 
2125
                   'SERVER_NAME': 'example.com',
 
2126
                   'SERVER_PORT': '80',
 
2127
                   'SCRIPT_NAME': '/script',
 
2128
                   'PATH_INFO': '/',
 
2129
                  }
 
2130
        req = self._makeOne(environ)
 
2131
        peeked = req.path_info_peek()
 
2132
        self.assertEqual(peeked, '')
 
2133
        self.assertEqual(environ['SCRIPT_NAME'], '/script')
 
2134
        self.assertEqual(environ['PATH_INFO'], '/')
 
2135
 
 
2136
    def test_path_info_peek_non_empty(self):
 
2137
        environ = {'wsgi.url_scheme': 'http',
 
2138
                   'SERVER_NAME': 'example.com',
 
2139
                   'SERVER_PORT': '80',
 
2140
                   'SCRIPT_NAME': '/script',
 
2141
                   'PATH_INFO': '/path',
 
2142
                  }
 
2143
        req = self._makeOne(environ)
 
2144
        peeked = req.path_info_peek()
 
2145
        self.assertEqual(peeked, 'path')
 
2146
        self.assertEqual(environ['SCRIPT_NAME'], '/script')
 
2147
        self.assertEqual(environ['PATH_INFO'], '/path')
 
2148
 
 
2149
    def test_is_xhr_no_header(self):
 
2150
        req = self._makeOne({})
 
2151
        self.assertTrue(not req.is_xhr)
 
2152
 
 
2153
    def test_is_xhr_header_miss(self):
 
2154
        environ = {'HTTP_X_REQUESTED_WITH': 'notAnXMLHTTPRequest'}
 
2155
        req = self._makeOne(environ)
 
2156
        self.assertTrue(not req.is_xhr)
 
2157
 
 
2158
    def test_is_xhr_header_hit(self):
 
2159
        environ = {'HTTP_X_REQUESTED_WITH': 'XMLHttpRequest'}
 
2160
        req = self._makeOne(environ)
 
2161
        self.assertTrue(req.is_xhr)
 
2162
 
 
2163
    # host
 
2164
    def test_host_getter_w_HTTP_HOST(self):
 
2165
        environ = {'HTTP_HOST': 'example.com:8888'}
 
2166
        req = self._makeOne(environ)
 
2167
        self.assertEqual(req.host, 'example.com:8888')
 
2168
 
 
2169
    def test_host_getter_wo_HTTP_HOST(self):
 
2170
        environ = {'SERVER_NAME': 'example.com',
 
2171
                   'SERVER_PORT': '8888'}
 
2172
        req = self._makeOne(environ)
 
2173
        self.assertEqual(req.host, 'example.com:8888')
 
2174
 
 
2175
    def test_host_setter(self):
 
2176
        environ = {}
 
2177
        req = self._makeOne(environ)
 
2178
        req.host = 'example.com:8888'
 
2179
        self.assertEqual(environ['HTTP_HOST'], 'example.com:8888')
 
2180
 
 
2181
    def test_host_deleter_hit(self):
 
2182
        environ = {'HTTP_HOST': 'example.com:8888'}
 
2183
        req = self._makeOne(environ)
 
2184
        del req.host
 
2185
        self.assertTrue('HTTP_HOST' not in environ)
 
2186
 
 
2187
    def test_host_deleter_miss(self):
 
2188
        environ = {}
 
2189
        req = self._makeOne(environ)
 
2190
        del req.host # doesn't raise
 
2191
 
 
2192
    def test_encget_raises_without_default(self):
 
2193
        inst = self._makeOne({})
 
2194
        self.assertRaises(KeyError, inst.encget, 'a')
 
2195
 
 
2196
    def test_encget_doesnt_raises_with_default(self):
 
2197
        inst = self._makeOne({})
 
2198
        self.assertEqual(inst.encget('a', None), None)
 
2199
 
 
2200
    def test_encget_with_encattr(self):
 
2201
        if PY3:
 
2202
            val = b'\xc3\xab'.decode('latin-1')
 
2203
        else:
 
2204
            val = b'\xc3\xab'
 
2205
        inst = self._makeOne({'a':val})
 
2206
        self.assertEqual(inst.encget('a', encattr='url_encoding'),
 
2207
                         native_(b'\xc3\xab', 'latin-1'))
 
2208
 
 
2209
    def test_encget_no_encattr(self):
 
2210
        if PY3:
 
2211
            val = b'\xc3\xab'.decode('latin-1')
 
2212
        else:
 
2213
            val = b'\xc3\xab'
 
2214
        inst = self._makeOne({'a':val})
 
2215
        self.assertEqual(inst.encget('a'), native_(b'\xc3\xab', 'latin-1'))
 
2216
 
 
2217
    def test_relative_url(self):
 
2218
        inst = self._blankOne('/%C3%AB/c')
 
2219
        result = inst.relative_url('a')
 
2220
        if PY3: # pragma: no cover
 
2221
            # this result is why you should not use legacyrequest under py 3
 
2222
            self.assertEqual(result, 'http://localhost/%C3%83%C2%AB/a')
 
2223
        else:
 
2224
            self.assertEqual(result, 'http://localhost/%C3%AB/a')
 
2225
 
 
2226
    def test_header_getter(self):
 
2227
        if PY3:
 
2228
            val = b'abc'.decode('latin-1')
 
2229
        else:
 
2230
            val = b'abc'
 
2231
        inst = self._makeOne({'HTTP_FLUB':val})
 
2232
        result = inst.headers['Flub']
 
2233
        self.assertEqual(result, 'abc')
 
2234
 
 
2235
    def test_json_body(self):
 
2236
        inst = self._makeOne({})
 
2237
        inst.body = b'{"a":"1"}'
 
2238
        self.assertEqual(inst.json_body, {'a':'1'})
 
2239
 
 
2240
    def test_host_get_w_http_host(self):
 
2241
        inst = self._makeOne({'HTTP_HOST':'example.com'})
 
2242
        result = inst.host
 
2243
        self.assertEqual(result, 'example.com')
 
2244
 
 
2245
    def test_host_get_w_no_http_host(self):
 
2246
        inst = self._makeOne({'SERVER_NAME':'example.com', 'SERVER_PORT':'80'})
 
2247
        result = inst.host
 
2248
        self.assertEqual(result, 'example.com:80')
 
2249
 
 
2250
class TestRequestConstructorWarnings(unittest.TestCase):
 
2251
    def _getTargetClass(self):
 
2252
        from webob.request import Request
 
2253
        return Request
 
2254
 
 
2255
    def _makeOne(self, *arg, **kw):
 
2256
        cls = self._getTargetClass()
 
2257
        return cls(*arg, **kw)
 
2258
 
 
2259
    def test_ctor_w_unicode_errors(self):
 
2260
        with warnings.catch_warnings(record=True) as w:
 
2261
            # still emit if warning was printed previously
 
2262
            warnings.simplefilter('always')
 
2263
            self._makeOne({}, unicode_errors=True)
 
2264
        self.assertEqual(len(w), 1)
 
2265
 
 
2266
    def test_ctor_w_decode_param_names(self):
 
2267
        with warnings.catch_warnings(record=True) as w:
 
2268
            # still emit if warning was printed previously
 
2269
            warnings.simplefilter('always')
 
2270
            self._makeOne({}, decode_param_names=True)
 
2271
        self.assertEqual(len(w), 1)
 
2272
 
 
2273
class TestRequestWithAdhocAttr(unittest.TestCase):
 
2274
    def _blankOne(self, *arg, **kw):
 
2275
        from webob.request import Request
 
2276
        return Request.blank(*arg, **kw)
1407
2277
 
1408
2278
    def test_adhoc_attrs_set(self):
1409
 
        req = Request.blank('/')
 
2279
        req = self._blankOne('/')
1410
2280
        req.foo = 1
1411
2281
        self.assertEqual(req.environ['webob.adhoc_attrs'], {'foo': 1})
1412
2282
 
1413
2283
    def test_adhoc_attrs_set_nonadhoc(self):
1414
 
        req = Request.blank('/', environ={'webob.adhoc_attrs':{}})
 
2284
        req = self._blankOne('/', environ={'webob.adhoc_attrs':{}})
1415
2285
        req.request_body_tempfile_limit = 1
1416
2286
        self.assertEqual(req.environ['webob.adhoc_attrs'], {})
1417
2287
 
1418
2288
    def test_adhoc_attrs_get(self):
1419
 
        req = Request.blank('/', environ={'webob.adhoc_attrs': {'foo': 1}})
 
2289
        req = self._blankOne('/', environ={'webob.adhoc_attrs': {'foo': 1}})
1420
2290
        self.assertEqual(req.foo, 1)
1421
2291
 
1422
2292
    def test_adhoc_attrs_get_missing(self):
1423
 
        req = Request.blank('/')
 
2293
        req = self._blankOne('/')
1424
2294
        self.assertRaises(AttributeError, getattr, req, 'some_attr')
1425
2295
 
1426
2296
    def test_adhoc_attrs_del(self):
1427
 
        req = Request.blank('/', environ={'webob.adhoc_attrs': {'foo': 1}})
 
2297
        req = self._blankOne('/', environ={'webob.adhoc_attrs': {'foo': 1}})
1428
2298
        del req.foo
1429
2299
        self.assertEqual(req.environ['webob.adhoc_attrs'], {})
1430
2300
 
1431
2301
    def test_adhoc_attrs_del_missing(self):
1432
 
        req = Request.blank('/')
 
2302
        req = self._blankOne('/')
1433
2303
        self.assertRaises(AttributeError, delattr, req, 'some_attr')
1434
2304
 
1435
 
class RequestTests_functional(unittest.TestCase):
 
2305
class TestRequest_functional(unittest.TestCase):
 
2306
    # functional tests of request
 
2307
    def _getTargetClass(self):
 
2308
        from webob.request import Request
 
2309
        return Request
 
2310
 
 
2311
    def _makeOne(self, *arg, **kw):
 
2312
        cls = self._getTargetClass()
 
2313
        return cls(*arg, **kw)
 
2314
 
 
2315
    def _blankOne(self, *arg, **kw):
 
2316
        cls = self._getTargetClass()
 
2317
        return cls.blank(*arg, **kw)
 
2318
 
1436
2319
    def test_gets(self):
1437
 
        from webtest import TestApp
1438
 
        app = TestApp(simpleapp)
1439
 
        res = app.get('/')
1440
 
        self.assert_('Hello' in res)
1441
 
        self.assert_("get is GET([])" in res)
1442
 
        self.assert_("post is <NoVars: Not a form request>" in res)
1443
 
 
1444
 
        res = app.get('/?name=george')
1445
 
        res.mustcontain("get is GET([('name', 'george')])")
1446
 
        res.mustcontain("Val is george")
1447
 
 
1448
 
    def test_language_parsing(self):
1449
 
        from webtest import TestApp
1450
 
        app = TestApp(simpleapp)
1451
 
        res = app.get('/')
1452
 
        self.assert_("The languages are: ['en-US']" in res)
1453
 
 
1454
 
        res = app.get('/',
1455
 
                      headers={'Accept-Language': 'da, en-gb;q=0.8, en;q=0.7'})
1456
 
        self.assert_("languages are: ['da', 'en-gb', 'en-US']" in res)
1457
 
 
1458
 
        res = app.get('/',
1459
 
                      headers={'Accept-Language': 'en-gb;q=0.8, da, en;q=0.7'})
1460
 
        self.assert_("languages are: ['da', 'en-gb', 'en-US']" in res)
1461
 
 
1462
 
    def test_mime_parsing(self):
1463
 
        from webtest import TestApp
1464
 
        app = TestApp(simpleapp)
1465
 
        res = app.get('/', headers={'Accept':'text/html'})
1466
 
        self.assert_("accepttypes is: text/html" in res)
1467
 
 
1468
 
        res = app.get('/', headers={'Accept':'application/xml'})
1469
 
        self.assert_("accepttypes is: application/xml" in res)
1470
 
 
1471
 
        res = app.get('/', headers={'Accept':'application/xml,*/*'})
1472
 
        self.assert_("accepttypes is: application/xml" in res)
 
2320
        request = self._blankOne('/')
 
2321
        status, headerlist, app_iter = request.call_application(simpleapp)
 
2322
        self.assertEqual(status, '200 OK')
 
2323
        res = b''.join(app_iter)
 
2324
        self.assertTrue(b'Hello' in res)
 
2325
        self.assertTrue(b"MultiDict([])" in res)
 
2326
        self.assertTrue(b"post is <NoVars: Not a form request>" in res)
 
2327
 
 
2328
    def test_gets_with_query_string(self):
 
2329
        request = self._blankOne('/?name=george')
 
2330
        status, headerlist, app_iter = request.call_application(simpleapp)
 
2331
        res = b''.join(app_iter)
 
2332
        self.assertTrue(b"MultiDict" in res)
 
2333
        self.assertTrue(b"'name'" in res)
 
2334
        self.assertTrue(b"'george'" in res)
 
2335
        self.assertTrue(b"Val is " in res)
 
2336
 
 
2337
    def test_language_parsing1(self):
 
2338
        request = self._blankOne('/')
 
2339
        status, headerlist, app_iter = request.call_application(simpleapp)
 
2340
        res = b''.join(app_iter)
 
2341
        self.assertTrue(b"The languages are: []" in res)
 
2342
 
 
2343
    def test_language_parsing2(self):
 
2344
        request = self._blankOne(
 
2345
            '/', headers={'Accept-Language': 'da, en-gb;q=0.8'})
 
2346
        status, headerlist, app_iter = request.call_application(simpleapp)
 
2347
        res = b''.join(app_iter)
 
2348
        self.assertTrue(b"languages are: ['da', 'en-gb']" in res)
 
2349
 
 
2350
    def test_language_parsing3(self):
 
2351
        request = self._blankOne(
 
2352
            '/',
 
2353
            headers={'Accept-Language': 'en-gb;q=0.8, da'})
 
2354
        status, headerlist, app_iter = request.call_application(simpleapp)
 
2355
        res = b''.join(app_iter)
 
2356
        self.assertTrue(b"languages are: ['da', 'en-gb']" in res)
 
2357
 
 
2358
    def test_mime_parsing1(self):
 
2359
        request = self._blankOne(
 
2360
            '/',
 
2361
            headers={'Accept':'text/html'})
 
2362
        status, headerlist, app_iter = request.call_application(simpleapp)
 
2363
        res = b''.join(app_iter)
 
2364
        self.assertTrue(b"accepttypes is: text/html" in res)
 
2365
 
 
2366
    def test_mime_parsing2(self):
 
2367
        request = self._blankOne(
 
2368
            '/',
 
2369
            headers={'Accept':'application/xml'})
 
2370
        status, headerlist, app_iter = request.call_application(simpleapp)
 
2371
        res = b''.join(app_iter)
 
2372
        self.assertTrue(b"accepttypes is: application/xml" in res)
 
2373
 
 
2374
    def test_mime_parsing3(self):
 
2375
        request = self._blankOne(
 
2376
            '/',
 
2377
            headers={'Accept':'application/xml,*/*'})
 
2378
        status, headerlist, app_iter = request.call_application(simpleapp)
 
2379
        res = b''.join(app_iter)
 
2380
        self.assertTrue(b"accepttypes is: application/xml" in res)
1473
2381
 
1474
2382
    def test_accept_best_match(self):
1475
 
        self.assert_(not Request.blank('/').accept)
1476
 
        self.assert_(not Request.blank('/', headers={'Accept': ''}).accept)
1477
 
        req = Request.blank('/', headers={'Accept':'text/plain'})
1478
 
        self.assert_(req.accept)
 
2383
        accept = self._blankOne('/').accept
 
2384
        self.assertTrue(not accept)
 
2385
        self.assertTrue(not self._blankOne('/', headers={'Accept': ''}).accept)
 
2386
        req = self._blankOne('/', headers={'Accept':'text/plain'})
 
2387
        self.assertTrue(req.accept)
1479
2388
        self.assertRaises(ValueError, req.accept.best_match, ['*/*'])
1480
 
        req = Request.blank('/', accept=['*/*','text/*'])
 
2389
        req = self._blankOne('/', accept=['*/*','text/*'])
1481
2390
        self.assertEqual(
1482
2391
            req.accept.best_match(['application/x-foo', 'text/plain']),
1483
2392
            'text/plain')
1484
2393
        self.assertEqual(
1485
2394
            req.accept.best_match(['text/plain', 'application/x-foo']),
1486
2395
            'text/plain')
1487
 
        req = Request.blank('/', accept=['text/plain', 'message/*'])
 
2396
        req = self._blankOne('/', accept=['text/plain', 'message/*'])
1488
2397
        self.assertEqual(
1489
2398
            req.accept.best_match(['message/x-foo', 'text/plain']),
1490
2399
            'text/plain')
1502
2411
                ('*/*', 'application/xbel+xml')]
1503
2412
 
1504
2413
        for accept, get in tests:
1505
 
            req = Request.blank('/', headers={'Accept':accept})
 
2414
            req = self._blankOne('/', headers={'Accept':accept})
1506
2415
            self.assertEqual(req.accept.best_match(supported), get)
1507
2416
 
1508
2417
        supported = ['application/xbel+xml', 'text/xml']
1510
2419
                ('text/html,application/atom+xml; q=0.9', None)]
1511
2420
 
1512
2421
        for accept, get in tests:
1513
 
            req = Request.blank('/', headers={'Accept':accept})
 
2422
            req = self._blankOne('/', headers={'Accept':accept})
1514
2423
            self.assertEqual(req.accept.best_match(supported), get)
1515
2424
 
1516
2425
        supported = ['application/json', 'text/html']
1520
2429
        ]
1521
2430
 
1522
2431
        for accept, get in tests:
1523
 
            req = Request.blank('/', headers={'Accept':accept})
 
2432
            req = self._blankOne('/', headers={'Accept':accept})
1524
2433
            self.assertEqual(req.accept.best_match(supported), get)
1525
2434
 
1526
2435
        offered = ['image/png', 'application/xml']
1531
2440
        ]
1532
2441
 
1533
2442
        for accept, get in tests:
1534
 
            req = Request.blank('/', accept=accept)
 
2443
            req = self._blankOne('/', accept=accept)
1535
2444
            self.assertEqual(req.accept.best_match(offered), get)
1536
2445
 
1537
2446
    def test_headers(self):
1538
 
        from webtest import TestApp
1539
 
        app = TestApp(simpleapp)
1540
2447
        headers = {
1541
2448
            'If-Modified-Since': 'Sat, 29 Oct 1994 19:43:31 GMT',
1542
2449
            'Cookie': 'var1=value1',
1544
2451
            'If-None-Match': '"etag001", "etag002"',
1545
2452
            'X-Requested-With': 'XMLHttpRequest',
1546
2453
            }
1547
 
        res = app.get('/?foo=bar&baz', headers=headers)
1548
 
        res.mustcontain(
 
2454
        request = self._blankOne('/?foo=bar&baz', headers=headers)
 
2455
        status, headerlist, app_iter = request.call_application(simpleapp)
 
2456
        res = b''.join(app_iter)
 
2457
        for thing in (
1549
2458
            'if_modified_since: ' +
1550
2459
                'datetime.datetime(1994, 10, 29, 19, 43, 31, tzinfo=UTC)',
1551
2460
            "user_agent: 'Mozilla",
1552
2461
            'is_xhr: True',
1553
 
            "cookies is {'var1': 'value1'}",
1554
 
            "params is NestedMultiDict([('foo', 'bar'), ('baz', '')])",
1555
 
            "if_none_match: <ETag etag001 or etag002>",
1556
 
            )
 
2462
            "cookies is <RequestCookies",
 
2463
            'var1',
 
2464
            'value1',
 
2465
            'params is NestedMultiDict',
 
2466
            'foo',
 
2467
            'bar',
 
2468
            'baz',
 
2469
            'if_none_match: <ETag etag001 or etag002>',
 
2470
            ):
 
2471
            self.assertTrue(bytes_(thing) in res)
1557
2472
 
1558
2473
    def test_bad_cookie(self):
1559
 
        req = Request.blank('/')
 
2474
        req = self._blankOne('/')
1560
2475
        req.headers['Cookie'] = '070-it-:><?0'
1561
2476
        self.assertEqual(req.cookies, {})
1562
2477
        req.headers['Cookie'] = 'foo=bar'
1568
2483
        req.headers['Cookie'] = ('dismiss-top=6; CP=null*; '
1569
2484
            'PHPSESSID=0a539d42abc001cdc762809248d4beed; a=42')
1570
2485
        self.assertEqual(req.cookies, {
1571
 
            'CP':           u'null*',
1572
 
            'PHPSESSID':    u'0a539d42abc001cdc762809248d4beed',
1573
 
            'a':            u'42',
1574
 
            'dismiss-top':  u'6'
 
2486
            'CP':           'null*',
 
2487
            'PHPSESSID':    '0a539d42abc001cdc762809248d4beed',
 
2488
            'a':            '42',
 
2489
            'dismiss-top':  '6'
1575
2490
        })
1576
2491
        req.headers['Cookie'] = 'fo234{=bar blub=Blah'
1577
2492
        self.assertEqual(req.cookies, {'blub': 'Blah'})
1578
2493
 
1579
2494
    def test_cookie_quoting(self):
1580
 
        req = Request.blank('/')
 
2495
        req = self._blankOne('/')
1581
2496
        req.headers['Cookie'] = 'foo="?foo"; Path=/'
1582
2497
        self.assertEqual(req.cookies, {'foo': '?foo'})
1583
2498
 
1584
2499
    def test_path_quoting(self):
1585
2500
        path = '/:@&+$,/bar'
1586
 
        req = Request.blank(path)
 
2501
        req = self._blankOne(path)
1587
2502
        self.assertEqual(req.path, path)
1588
 
        self.assert_(req.url.endswith(path))
 
2503
        self.assertTrue(req.url.endswith(path))
1589
2504
 
1590
2505
    def test_params(self):
1591
 
        req = Request.blank('/?a=1&b=2')
 
2506
        req = self._blankOne('/?a=1&b=2')
1592
2507
        req.method = 'POST'
1593
 
        req.body = 'b=3'
1594
 
        self.assertEqual(req.params.items(),
 
2508
        req.body = b'b=3'
 
2509
        self.assertEqual(list(req.params.items()),
1595
2510
                         [('a', '1'), ('b', '2'), ('b', '3')])
1596
2511
        new_params = req.params.copy()
1597
 
        self.assertEqual(new_params.items(),
 
2512
        self.assertEqual(list(new_params.items()),
1598
2513
                         [('a', '1'), ('b', '2'), ('b', '3')])
1599
2514
        new_params['b'] = '4'
1600
 
        self.assertEqual(new_params.items(), [('a', '1'), ('b', '4')])
 
2515
        self.assertEqual(list(new_params.items()), [('a', '1'), ('b', '4')])
1601
2516
        # The key name is \u1000:
1602
 
        req = Request.blank('/?%E1%80%80=x',
1603
 
                            decode_param_names=True, charset='UTF-8')
1604
 
        self.assert_(req.decode_param_names)
1605
 
        self.assert_(u'\u1000' in req.GET.keys())
1606
 
        self.assertEqual(req.GET[u'\u1000'], 'x')
 
2517
        req = self._blankOne('/?%E1%80%80=x')
 
2518
        val = text_type(b'\u1000', 'unicode_escape')
 
2519
        self.assertTrue(val in list(req.GET.keys()))
 
2520
        self.assertEqual(req.GET[val], 'x')
1607
2521
 
1608
2522
    def test_copy_body(self):
1609
 
        req = Request.blank('/', method='POST', body='some text',
 
2523
        req = self._blankOne('/', method='POST', body=b'some text',
1610
2524
                            request_body_tempfile_limit=1)
1611
2525
        old_body_file = req.body_file_raw
1612
2526
        req.copy_body()
1613
 
        self.assert_(req.body_file_raw is not old_body_file)
1614
 
        req = Request.blank('/', method='POST',
1615
 
                body_file=UnseekableInput('0123456789'), content_length=10)
1616
 
        self.assert_(not hasattr(req.body_file_raw, 'seek'))
 
2527
        self.assertTrue(req.body_file_raw is not old_body_file)
 
2528
        req = self._blankOne('/', method='POST',
 
2529
                body_file=UnseekableInput(b'0123456789'), content_length=10)
 
2530
        self.assertTrue(not hasattr(req.body_file_raw, 'seek'))
1617
2531
        old_body_file = req.body_file_raw
1618
2532
        req.make_body_seekable()
1619
 
        self.assert_(req.body_file_raw is not old_body_file)
1620
 
        self.assertEqual(req.body, '0123456789')
 
2533
        self.assertTrue(req.body_file_raw is not old_body_file)
 
2534
        self.assertEqual(req.body, b'0123456789')
1621
2535
        old_body_file = req.body_file
1622
2536
        req.make_body_seekable()
1623
 
        self.assert_(req.body_file_raw is old_body_file)
1624
 
        self.assert_(req.body_file is old_body_file)
 
2537
        self.assertTrue(req.body_file_raw is old_body_file)
 
2538
        self.assertTrue(req.body_file is old_body_file)
1625
2539
 
1626
2540
    def test_broken_seek(self):
1627
2541
        # copy() should work even when the input has a broken seek method
1628
 
        req = Request.blank('/', method='POST',
1629
 
                body_file=UnseekableInputWithSeek('0123456789'),
 
2542
        req = self._blankOne('/', method='POST',
 
2543
                body_file=UnseekableInputWithSeek(b'0123456789'),
1630
2544
                content_length=10)
1631
 
        self.assert_(hasattr(req.body_file_raw, 'seek'))
 
2545
        self.assertTrue(hasattr(req.body_file_raw, 'seek'))
1632
2546
        self.assertRaises(IOError, req.body_file_raw.seek, 0)
1633
2547
        old_body_file = req.body_file
1634
2548
        req2 = req.copy()
1635
 
        self.assert_(req2.body_file_raw is req2.body_file is not old_body_file)
1636
 
        self.assertEqual(req2.body, '0123456789')
 
2549
        self.assertTrue(req2.body_file_raw is req2.body_file is not
 
2550
                        old_body_file)
 
2551
        self.assertEqual(req2.body, b'0123456789')
1637
2552
 
1638
2553
    def test_set_body(self):
1639
 
        from webob import BaseRequest
1640
 
        req = BaseRequest.blank('/', method='PUT', body='foo')
1641
 
        self.assert_(req.is_body_seekable)
1642
 
        self.assertEqual(req.body, 'foo')
 
2554
        req = self._blankOne('/', method='PUT', body=b'foo')
 
2555
        self.assertTrue(req.is_body_seekable)
 
2556
        self.assertEqual(req.body, b'foo')
1643
2557
        self.assertEqual(req.content_length, 3)
1644
2558
        del req.body
1645
 
        self.assertEqual(req.body, '')
 
2559
        self.assertEqual(req.body, b'')
1646
2560
        self.assertEqual(req.content_length, 0)
1647
2561
 
1648
2562
    def test_broken_clen_header(self):
1649
2563
        # if the UA sends "content_length: ..' header (the name is wrong)
1650
2564
        # it should not break the req.headers.items()
1651
 
        req = Request.blank('/')
 
2565
        req = self._blankOne('/')
1652
2566
        req.environ['HTTP_CONTENT_LENGTH'] = '0'
1653
2567
        req.headers.items()
1654
2568
 
1655
2569
    def test_nonstr_keys(self):
1656
2570
        # non-string env keys shouldn't break req.headers
1657
 
        req = Request.blank('/')
 
2571
        req = self._blankOne('/')
1658
2572
        req.environ[1] = 1
1659
2573
        req.headers.items()
1660
2574
 
1661
 
 
1662
2575
    def test_authorization(self):
1663
 
        req = Request.blank('/')
 
2576
        req = self._blankOne('/')
1664
2577
        req.authorization = 'Digest uri="/?a=b"'
1665
2578
        self.assertEqual(req.authorization, ('Digest', {'uri': '/?a=b'}))
1666
2579
 
1667
 
    def test_authorization2(self):
1668
 
        from webob.descriptors import parse_auth_params
1669
 
        for s, d in [
1670
 
            ('x=y', {'x': 'y'}),
1671
 
            ('x="y"', {'x': 'y'}),
1672
 
            ('x=y,z=z', {'x': 'y', 'z': 'z'}),
1673
 
            ('x=y, z=z', {'x': 'y', 'z': 'z'}),
1674
 
            ('x="y",z=z', {'x': 'y', 'z': 'z'}),
1675
 
            ('x="y", z=z', {'x': 'y', 'z': 'z'}),
1676
 
            ('x="y,x", z=z', {'x': 'y,x', 'z': 'z'}),
1677
 
        ]:
1678
 
            self.assertEqual(parse_auth_params(s), d)
1679
 
 
1680
 
 
1681
 
    def test_from_file(self):
1682
 
        req = Request.blank('http://example.com:8000/test.html?params')
1683
 
        self.equal_req(req)
1684
 
 
1685
 
        req = Request.blank('http://example.com/test2')
1686
 
        req.method = 'POST'
1687
 
        req.body = 'test=example'
1688
 
        self.equal_req(req)
 
2580
    def test_as_bytes(self):
 
2581
        req = self._blankOne('http://example.com:8000/test.html?params')
 
2582
        inp = BytesIO(req.as_bytes())
 
2583
        self.equal_req(req, inp)
 
2584
 
 
2585
        req = self._blankOne('http://example.com/test2')
 
2586
        req.method = 'POST'
 
2587
        req.body = b'test=example'
 
2588
        inp = BytesIO(req.as_bytes())
 
2589
        self.equal_req(req, inp)
 
2590
 
 
2591
    def test_as_text(self):
 
2592
        req = self._blankOne('http://example.com:8000/test.html?params')
 
2593
        inp = StringIO(req.as_text())
 
2594
        self.equal_req(req, inp)
 
2595
 
 
2596
        req = self._blankOne('http://example.com/test2')
 
2597
        req.method = 'POST'
 
2598
        req.body = b'test=example'
 
2599
        inp = StringIO(req.as_text())
 
2600
        self.equal_req(req, inp)
1689
2601
 
1690
2602
    def test_req_kw_none_val(self):
1691
 
        request = Request({}, content_length=None)
1692
 
        self.assert_('content-length' not in request.headers)
1693
 
        self.assert_('content-type' not in request.headers)
 
2603
        request = self._makeOne({}, content_length=None)
 
2604
        self.assertTrue('content-length' not in request.headers)
 
2605
        self.assertTrue('content-type' not in request.headers)
1694
2606
 
1695
2607
    def test_env_keys(self):
1696
 
        req = Request.blank('/')
 
2608
        req = self._blankOne('/')
1697
2609
        # SCRIPT_NAME can be missing
1698
2610
        del req.environ['SCRIPT_NAME']
1699
2611
        self.assertEqual(req.script_name, '')
1700
 
        self.assertEqual(req.uscript_name, u'')
 
2612
        self.assertEqual(req.uscript_name, '')
1701
2613
 
1702
2614
    def test_repr_nodefault(self):
1703
2615
        from webob.request import NoDefault
1706
2618
 
1707
2619
    def test_request_noenviron_param(self):
1708
2620
        # Environ is a a mandatory not null param in Request.
1709
 
        self.assertRaises(TypeError, Request, environ=None)
1710
 
 
1711
 
    def test_unicode_errors(self):
1712
 
        # Passing unicode_errors != NoDefault should assign value to
1713
 
        # dictionary['unicode_errors'], else not
1714
 
        r = Request({'a':1}, unicode_errors='strict')
1715
 
        self.assert_('unicode_errors' in r.__dict__)
1716
 
        r = Request({'a':1})
1717
 
        self.assert_('unicode_errors' not in r.__dict__)
 
2621
        self.assertRaises(TypeError, self._makeOne, environ=None)
1718
2622
 
1719
2623
    def test_unexpected_kw(self):
1720
2624
        # Passed an attr in kw that does not exist in the class, should
1721
2625
        # raise an error
1722
2626
        # Passed an attr in kw that does exist in the class, should be ok
1723
2627
        self.assertRaises(TypeError,
1724
 
                          Request, {'a':1}, this_does_not_exist=1)
1725
 
        r = Request({'a':1}, **{'charset':'utf-8', 'server_name':'127.0.0.1'})
1726
 
        self.assertEqual(getattr(r, 'charset', None), 'utf-8')
 
2628
                          self._makeOne, {'a':1}, this_does_not_exist=1)
 
2629
        r = self._makeOne({'a':1}, server_name='127.0.0.1')
1727
2630
        self.assertEqual(getattr(r, 'server_name', None), '127.0.0.1')
1728
2631
 
1729
2632
    def test_conttype_set_del(self):
1731
2634
        # environ dict
1732
2635
        # Assigning content_type should replace first option of the environ
1733
2636
        # dict
1734
 
        r = Request({'a':1}, **{'content_type':'text/html'})
1735
 
        self.assert_('CONTENT_TYPE' in r.environ)
1736
 
        self.assert_(hasattr(r, 'content_type'))
 
2637
        r = self._makeOne({'a':1}, **{'content_type':'text/html'})
 
2638
        self.assertTrue('CONTENT_TYPE' in r.environ)
 
2639
        self.assertTrue(hasattr(r, 'content_type'))
1737
2640
        del r.content_type
1738
 
        self.assert_('CONTENT_TYPE' not in r.environ)
1739
 
        a = Request({'a':1},
 
2641
        self.assertTrue('CONTENT_TYPE' not in r.environ)
 
2642
        a = self._makeOne({'a':1},
1740
2643
                content_type='charset=utf-8;application/atom+xml;type=entry')
1741
 
        self.assert_(a.environ['CONTENT_TYPE']==
 
2644
        self.assertTrue(a.environ['CONTENT_TYPE']==
1742
2645
                'charset=utf-8;application/atom+xml;type=entry')
1743
2646
        a.content_type = 'charset=utf-8'
1744
 
        self.assert_(a.environ['CONTENT_TYPE']==
 
2647
        self.assertTrue(a.environ['CONTENT_TYPE']==
1745
2648
                'charset=utf-8;application/atom+xml;type=entry')
1746
2649
 
1747
2650
    def test_headers2(self):
1754
2657
                'Keep-Alive': '115',
1755
2658
                'Connection': 'keep-alive',
1756
2659
                'Cache-Control': 'max-age=0'}
1757
 
        r = Request({'a':1}, headers=headers)
 
2660
        r = self._makeOne({'a':1}, headers=headers)
1758
2661
        for i in headers.keys():
1759
 
            self.assert_(i in r.headers and
 
2662
            self.assertTrue(i in r.headers and
1760
2663
                'HTTP_'+i.upper().replace('-', '_') in r.environ)
1761
2664
        r.headers = {'Server':'Apache'}
1762
 
        self.assertEqual(r.environ.keys(), ['a',  'HTTP_SERVER'])
 
2665
        self.assertEqual(list(r.environ.keys()), ['a',  'HTTP_SERVER'])
1763
2666
 
1764
2667
    def test_host_url(self):
1765
2668
        # Request has a read only property host_url that combines several
1766
2669
        # keys to create a host_url
1767
 
        a = Request({'wsgi.url_scheme':'http'}, **{'host':'www.example.com'})
 
2670
        a = self._makeOne(
 
2671
            {'wsgi.url_scheme':'http'}, **{'host':'www.example.com'})
1768
2672
        self.assertEqual(a.host_url, 'http://www.example.com')
1769
 
        a = Request({'wsgi.url_scheme':'http'}, **{'server_name':'localhost',
 
2673
        a = self._makeOne(
 
2674
            {'wsgi.url_scheme':'http'}, **{'server_name':'localhost',
1770
2675
                                                'server_port':5000})
1771
2676
        self.assertEqual(a.host_url, 'http://localhost:5000')
1772
 
        a = Request({'wsgi.url_scheme':'https'}, **{'server_name':'localhost',
1773
 
                                                    'server_port':443})
 
2677
        a = self._makeOne(
 
2678
            {'wsgi.url_scheme':'https'}, **{'server_name':'localhost',
 
2679
                                            'server_port':443})
1774
2680
        self.assertEqual(a.host_url, 'https://localhost')
1775
2681
 
1776
2682
    def test_path_info_p(self):
1777
2683
        # Peek path_info to see what's coming
1778
2684
        # Pop path_info until there's nothing remaining
1779
 
        a = Request({'a':1}, **{'path_info':'/foo/bar','script_name':''})
 
2685
        a = self._makeOne({'a':1}, **{'path_info':'/foo/bar','script_name':''})
1780
2686
        self.assertEqual(a.path_info_peek(), 'foo')
1781
2687
        self.assertEqual(a.path_info_pop(), 'foo')
1782
2688
        self.assertEqual(a.path_info_peek(), 'bar')
1786
2692
 
1787
2693
    def test_urlvars_property(self):
1788
2694
        # Testing urlvars setter/getter/deleter
1789
 
        a = Request({'wsgiorg.routing_args':((),{'x':'y'}),
1790
 
                    'paste.urlvars':{'test':'value'}})
 
2695
        a = self._makeOne({'wsgiorg.routing_args':((),{'x':'y'}),
 
2696
                           'paste.urlvars':{'test':'value'}})
1791
2697
        a.urlvars = {'hello':'world'}
1792
 
        self.assert_('paste.urlvars' not in a.environ)
 
2698
        self.assertTrue('paste.urlvars' not in a.environ)
1793
2699
        self.assertEqual(a.environ['wsgiorg.routing_args'],
1794
2700
                         ((), {'hello':'world'}))
1795
2701
        del a.urlvars
1796
 
        self.assert_('wsgiorg.routing_args' not in a.environ)
1797
 
        a = Request({'paste.urlvars':{'test':'value'}})
 
2702
        self.assertTrue('wsgiorg.routing_args' not in a.environ)
 
2703
        a = self._makeOne({'paste.urlvars':{'test':'value'}})
1798
2704
        self.assertEqual(a.urlvars, {'test':'value'})
1799
2705
        a.urlvars = {'hello':'world'}
1800
2706
        self.assertEqual(a.environ['paste.urlvars'], {'hello':'world'})
1801
2707
        del a.urlvars
1802
 
        self.assert_('paste.urlvars' not in a.environ)
 
2708
        self.assertTrue('paste.urlvars' not in a.environ)
1803
2709
 
1804
2710
    def test_urlargs_property(self):
1805
2711
        # Testing urlargs setter/getter/deleter
1806
 
        a = Request({'paste.urlvars':{'test':'value'}})
 
2712
        a = self._makeOne({'paste.urlvars':{'test':'value'}})
1807
2713
        self.assertEqual(a.urlargs, ())
1808
2714
        a.urlargs = {'hello':'world'}
1809
2715
        self.assertEqual(a.environ['wsgiorg.routing_args'],
1810
2716
                         ({'hello':'world'}, {'test':'value'}))
1811
 
        a = Request({'a':1})
 
2717
        a = self._makeOne({'a':1})
1812
2718
        a.urlargs = {'hello':'world'}
1813
2719
        self.assertEqual(a.environ['wsgiorg.routing_args'],
1814
2720
                         ({'hello':'world'}, {}))
1815
2721
        del a.urlargs
1816
 
        self.assert_('wsgiorg.routing_args' not in a.environ)
 
2722
        self.assertTrue('wsgiorg.routing_args' not in a.environ)
1817
2723
 
1818
2724
    def test_host_property(self):
1819
2725
        # Testing host setter/getter/deleter
1820
 
        a = Request({'wsgi.url_scheme':'http'}, server_name='localhost',
1821
 
                                                server_port=5000)
 
2726
        a = self._makeOne({'wsgi.url_scheme':'http'}, server_name='localhost',
 
2727
                          server_port=5000)
1822
2728
        self.assertEqual(a.host, "localhost:5000")
1823
2729
        a.host = "localhost:5000"
1824
 
        self.assert_('HTTP_HOST' in a.environ)
 
2730
        self.assertTrue('HTTP_HOST' in a.environ)
1825
2731
        del a.host
1826
 
        self.assert_('HTTP_HOST' not in a.environ)
 
2732
        self.assertTrue('HTTP_HOST' not in a.environ)
1827
2733
 
1828
2734
    def test_body_property(self):
1829
2735
        # Testing body setter/getter/deleter plus making sure body has a
1834
2740
        # either
1835
2741
        #self.assertEqual(a.body, '')
1836
2742
        # I need to implement a not seekable stringio like object.
 
2743
 
1837
2744
        import string
1838
 
        from cStringIO import StringIO
1839
2745
        class DummyIO(object):
1840
2746
            def __init__(self, txt):
1841
2747
                self.txt = txt
1842
2748
            def read(self, n=-1):
1843
2749
                return self.txt[0:n]
1844
 
        limit = BaseRequest.request_body_tempfile_limit
1845
 
        len_strl = limit // len(string.letters) + 1
1846
 
        r = Request({'a':1, 'REQUEST_METHOD': 'POST'}, body_file=DummyIO(string.letters * len_strl))
1847
 
        self.assertEqual(len(r.body), len(string.letters*len_strl)-1)
 
2750
        cls = self._getTargetClass()
 
2751
        limit = cls.request_body_tempfile_limit
 
2752
        len_strl = limit // len(string.ascii_letters) + 1
 
2753
        r = self._makeOne(
 
2754
            {'a':1, 'REQUEST_METHOD': 'POST'},
 
2755
            body_file=DummyIO(bytes_(string.ascii_letters) * len_strl))
 
2756
        self.assertEqual(len(r.body), len(string.ascii_letters*len_strl)-1)
1848
2757
        self.assertRaises(TypeError,
1849
 
                          setattr, r, 'body', unicode('hello world'))
 
2758
                          setattr, r, 'body', text_('hello world'))
1850
2759
        r.body = None
1851
 
        self.assertEqual(r.body, '')
1852
 
        r = Request({'a':1}, method='PUT', body_file=DummyIO(string.letters))
1853
 
        self.assert_(not hasattr(r.body_file_raw, 'seek'))
1854
 
        r.make_body_seekable()
1855
 
        self.assert_(hasattr(r.body_file_raw, 'seek'))
1856
 
        r = Request({'a':1}, method='PUT', body_file=StringIO(string.letters))
1857
 
        self.assert_(hasattr(r.body_file_raw, 'seek'))
1858
 
        r.make_body_seekable()
1859
 
        self.assert_(hasattr(r.body_file_raw, 'seek'))
 
2760
        self.assertEqual(r.body, b'')
 
2761
        r = self._makeOne({'a':1}, method='PUT', body_file=DummyIO(
 
2762
            bytes_(string.ascii_letters)))
 
2763
        self.assertTrue(not hasattr(r.body_file_raw, 'seek'))
 
2764
        r.make_body_seekable()
 
2765
        self.assertTrue(hasattr(r.body_file_raw, 'seek'))
 
2766
        r = self._makeOne({'a':1}, method='PUT',
 
2767
                          body_file=BytesIO(bytes_(string.ascii_letters)))
 
2768
        self.assertTrue(hasattr(r.body_file_raw, 'seek'))
 
2769
        r.make_body_seekable()
 
2770
        self.assertTrue(hasattr(r.body_file_raw, 'seek'))
1860
2771
 
1861
2772
    def test_repr_invalid(self):
1862
2773
        # If we have an invalid WSGI environ, the repr should tell us.
1863
 
        from webob import BaseRequest
1864
 
        req = BaseRequest({'CONTENT_LENGTH':'0', 'body':''})
1865
 
        self.assert_(repr(req).endswith('(invalid WSGI environ)>'))
 
2774
        req = self._makeOne({'CONTENT_LENGTH':'0', 'body':''})
 
2775
        self.assertTrue(repr(req).endswith('(invalid WSGI environ)>'))
1866
2776
 
1867
2777
    def test_from_garbage_file(self):
1868
2778
        # If we pass a file with garbage to from_file method it should
1869
2779
        # raise an error plus missing bits in from_file method
1870
 
        from cStringIO import StringIO
1871
 
        from webob import BaseRequest
1872
 
        self.assertRaises(ValueError,
1873
 
                          BaseRequest.from_file, StringIO('hello world'))
1874
 
        val_file = StringIO(
1875
 
            "GET /webob/ HTTP/1.1\n"
1876
 
            "Host: pythonpaste.org\n"
1877
 
            "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.2.13)"
1878
 
            "Gecko/20101206 Ubuntu/10.04 (lucid) Firefox/3.6.13\n"
1879
 
            "Accept: "
1880
 
                "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;"
1881
 
            "q=0.8\n"
1882
 
            "Accept-Language: en-us,en;q=0.5\n"
1883
 
            "Accept-Encoding: gzip,deflate\n"
1884
 
            "Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7\n"
 
2780
        io = BytesIO(b'hello world')
 
2781
 
 
2782
        cls = self._getTargetClass()
 
2783
        self.assertRaises(ValueError, cls.from_file, io)
 
2784
        val_file = BytesIO(
 
2785
            b"GET /webob/ HTTP/1.1\n"
 
2786
            b"Host: pythonpaste.org\n"
 
2787
            b"User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.2.13)"
 
2788
            b"Gecko/20101206 Ubuntu/10.04 (lucid) Firefox/3.6.13\n"
 
2789
            b"Accept: "
 
2790
            b"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;"
 
2791
            b"q=0.8\n"
 
2792
            b"Accept-Language: en-us,en;q=0.5\n"
 
2793
            b"Accept-Encoding: gzip,deflate\n"
 
2794
            b"Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7\n"
1885
2795
            # duplicate on purpose
1886
 
            "Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7\n"
1887
 
            "Keep-Alive: 115\n"
1888
 
            "Connection: keep-alive\n"
1889
 
        )
1890
 
        req = BaseRequest.from_file(val_file)
1891
 
        self.assert_(isinstance(req, BaseRequest))
1892
 
        self.assert_(not repr(req).endswith('(invalid WSGI environ)>'))
1893
 
        val_file = StringIO(
1894
 
            "GET /webob/ HTTP/1.1\n"
1895
 
            "Host pythonpaste.org\n"
1896
 
        )
1897
 
        self.assertRaises(ValueError, BaseRequest.from_file, val_file)
 
2796
            b"Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7\n"
 
2797
            b"Keep-Alive: 115\n"
 
2798
            b"Connection: keep-alive\n"
 
2799
        )
 
2800
        req = cls.from_file(val_file)
 
2801
        self.assertTrue(isinstance(req, cls))
 
2802
        self.assertTrue(not repr(req).endswith('(invalid WSGI environ)>'))
 
2803
        val_file = BytesIO(
 
2804
            b"GET /webob/ HTTP/1.1\n"
 
2805
            b"Host pythonpaste.org\n"
 
2806
        )
 
2807
        self.assertRaises(ValueError, cls.from_file, val_file)
1898
2808
 
1899
 
    def test_from_string(self):
 
2809
    def test_from_bytes(self):
1900
2810
        # A valid request without a Content-Length header should still read
1901
2811
        # the full body.
1902
 
        # Also test parity between as_string and from_string / from_file.
1903
 
        import cgi
1904
 
        from webob import BaseRequest
1905
 
        req = BaseRequest.from_string(_test_req)
1906
 
        self.assert_(isinstance(req, BaseRequest))
1907
 
        self.assert_(not repr(req).endswith('(invalid WSGI environ)>'))
1908
 
        self.assert_('\n' not in req.http_version or '\r' in req.http_version)
1909
 
        self.assert_(',' not in req.host)
1910
 
        self.assert_(req.content_length is not None)
1911
 
        self.assertEqual(req.content_length, 337)
1912
 
        self.assert_('foo' in req.body)
1913
 
        bar_contents = "these are the contents of the file 'bar.txt'\r\n"
1914
 
        self.assert_(bar_contents in req.body)
1915
 
        self.assertEqual(req.params['foo'], 'foo')
1916
 
        bar = req.params['bar']
1917
 
        self.assert_(isinstance(bar, cgi.FieldStorage))
1918
 
        self.assertEqual(bar.type, 'application/octet-stream')
1919
 
        bar.file.seek(0)
1920
 
        self.assertEqual(bar.file.read(), bar_contents)
1921
 
        # out should equal contents, except for the Content-Length header,
1922
 
        # so insert that.
1923
 
        _test_req_copy = _test_req.replace('Content-Type',
1924
 
                            'Content-Length: 337\r\nContent-Type')
1925
 
        self.assertEqual(str(req), _test_req_copy)
1926
 
 
1927
 
        req2 = BaseRequest.from_string(_test_req2)
1928
 
        self.assert_('host' not in req2.headers)
1929
 
        self.assertEqual(str(req2), _test_req2.rstrip())
1930
 
        self.assertRaises(ValueError,
1931
 
                          BaseRequest.from_string, _test_req2 + 'xx')
 
2812
        # Also test parity between as_string and from_bytes / from_file.
 
2813
        import cgi
 
2814
        cls = self._getTargetClass()
 
2815
        req = cls.from_bytes(_test_req)
 
2816
        self.assertTrue(isinstance(req, cls))
 
2817
        self.assertTrue(not repr(req).endswith('(invalid WSGI environ)>'))
 
2818
        self.assertTrue('\n' not in req.http_version or '\r' in
 
2819
                        req.http_version)
 
2820
        self.assertTrue(',' not in req.host)
 
2821
        self.assertTrue(req.content_length is not None)
 
2822
        self.assertEqual(req.content_length, 337)
 
2823
        self.assertTrue(b'foo' in req.body)
 
2824
        bar_contents = b"these are the contents of the file 'bar.txt'\r\n"
 
2825
        self.assertTrue(bar_contents in req.body)
 
2826
        self.assertEqual(req.params['foo'], 'foo')
 
2827
        bar = req.params['bar']
 
2828
        self.assertTrue(isinstance(bar, cgi.FieldStorage))
 
2829
        self.assertEqual(bar.type, 'application/octet-stream')
 
2830
        bar.file.seek(0)
 
2831
        self.assertEqual(bar.file.read(), bar_contents)
 
2832
        # out should equal contents, except for the Content-Length header,
 
2833
        # so insert that.
 
2834
        _test_req_copy = _test_req.replace(
 
2835
            b'Content-Type',
 
2836
            b'Content-Length: 337\r\nContent-Type'
 
2837
            )
 
2838
        self.assertEqual(req.as_bytes(), _test_req_copy)
 
2839
 
 
2840
        req2 = cls.from_bytes(_test_req2)
 
2841
        self.assertTrue('host' not in req2.headers)
 
2842
        self.assertEqual(req2.as_bytes(), _test_req2.rstrip())
 
2843
        self.assertRaises(ValueError, cls.from_bytes, _test_req2 + b'xx')
 
2844
 
 
2845
    def test_from_text(self):
 
2846
        import cgi
 
2847
        cls = self._getTargetClass()
 
2848
        req = cls.from_text(text_(_test_req, 'utf-8'))
 
2849
        self.assertTrue(isinstance(req, cls))
 
2850
        self.assertTrue(not repr(req).endswith('(invalid WSGI environ)>'))
 
2851
        self.assertTrue('\n' not in req.http_version or '\r' in
 
2852
                        req.http_version)
 
2853
        self.assertTrue(',' not in req.host)
 
2854
        self.assertTrue(req.content_length is not None)
 
2855
        self.assertEqual(req.content_length, 337)
 
2856
        self.assertTrue(b'foo' in req.body)
 
2857
        bar_contents = b"these are the contents of the file 'bar.txt'\r\n"
 
2858
        self.assertTrue(bar_contents in req.body)
 
2859
        self.assertEqual(req.params['foo'], 'foo')
 
2860
        bar = req.params['bar']
 
2861
        self.assertTrue(isinstance(bar, cgi.FieldStorage))
 
2862
        self.assertEqual(bar.type, 'application/octet-stream')
 
2863
        bar.file.seek(0)
 
2864
        self.assertEqual(bar.file.read(), bar_contents)
 
2865
        # out should equal contents, except for the Content-Length header,
 
2866
        # so insert that.
 
2867
        _test_req_copy = _test_req.replace(
 
2868
            b'Content-Type',
 
2869
            b'Content-Length: 337\r\nContent-Type'
 
2870
            )
 
2871
        self.assertEqual(req.as_bytes(), _test_req_copy)
 
2872
 
 
2873
        req2 = cls.from_bytes(_test_req2)
 
2874
        self.assertTrue('host' not in req2.headers)
 
2875
        self.assertEqual(req2.as_bytes(), _test_req2.rstrip())
 
2876
        self.assertRaises(ValueError, cls.from_bytes, _test_req2 + b'xx')
1932
2877
 
1933
2878
    def test_blank(self):
1934
2879
        # BaseRequest.blank class method
1935
 
        from webob import BaseRequest
1936
 
        self.assertRaises(ValueError, BaseRequest.blank,
 
2880
        self.assertRaises(ValueError, self._blankOne,
1937
2881
                    'www.example.com/foo?hello=world', None,
1938
2882
                    'www.example.com/foo?hello=world')
1939
 
        self.assertRaises(ValueError, BaseRequest.blank,
 
2883
        self.assertRaises(ValueError, self._blankOne,
1940
2884
                    'gopher.example.com/foo?hello=world', None,
1941
2885
                    'gopher://gopher.example.com')
1942
 
        req = BaseRequest.blank('www.example.com/foo?hello=world', None,
1943
 
                                'http://www.example.com')
 
2886
        req = self._blankOne('www.example.com/foo?hello=world', None,
 
2887
                             'http://www.example.com')
1944
2888
        self.assertEqual(req.environ.get('HTTP_HOST', None),
1945
2889
                         'www.example.com:80')
1946
2890
        self.assertEqual(req.environ.get('PATH_INFO', None),
1948
2892
        self.assertEqual(req.environ.get('QUERY_STRING', None),
1949
2893
                         'hello=world')
1950
2894
        self.assertEqual(req.environ.get('REQUEST_METHOD', None), 'GET')
1951
 
        req = BaseRequest.blank('www.example.com/secure?hello=world', None,
1952
 
                                'https://www.example.com/secure')
 
2895
        req = self._blankOne('www.example.com/secure?hello=world', None,
 
2896
                             'https://www.example.com/secure')
1953
2897
        self.assertEqual(req.environ.get('HTTP_HOST', None),
1954
2898
                         'www.example.com:443')
1955
2899
        self.assertEqual(req.environ.get('PATH_INFO', None),
1961
2905
                         'www.example.com')
1962
2906
        self.assertEqual(req.environ.get('SERVER_PORT', None), '443')
1963
2907
 
1964
 
    def test_environ_from_url(self):
1965
 
        # Generating an environ just from an url plus testing environ_add_POST
1966
 
        from webob.request import environ_add_POST
1967
 
        from webob.request import environ_from_url
1968
 
        self.assertRaises(TypeError, environ_from_url,
1969
 
                    'http://www.example.com/foo?bar=baz#qux')
1970
 
        self.assertRaises(TypeError, environ_from_url,
1971
 
                    'gopher://gopher.example.com')
1972
 
        req = environ_from_url('http://www.example.com/foo?bar=baz')
1973
 
        self.assertEqual(req.get('HTTP_HOST', None), 'www.example.com:80')
1974
 
        self.assertEqual(req.get('PATH_INFO', None), '/foo')
1975
 
        self.assertEqual(req.get('QUERY_STRING', None), 'bar=baz')
1976
 
        self.assertEqual(req.get('REQUEST_METHOD', None), 'GET')
1977
 
        self.assertEqual(req.get('SCRIPT_NAME', None), '')
1978
 
        self.assertEqual(req.get('SERVER_NAME', None), 'www.example.com')
1979
 
        self.assertEqual(req.get('SERVER_PORT', None), '80')
1980
 
        req = environ_from_url('https://www.example.com/foo?bar=baz')
1981
 
        self.assertEqual(req.get('HTTP_HOST', None), 'www.example.com:443')
1982
 
        self.assertEqual(req.get('PATH_INFO', None), '/foo')
1983
 
        self.assertEqual(req.get('QUERY_STRING', None), 'bar=baz')
1984
 
        self.assertEqual(req.get('REQUEST_METHOD', None), 'GET')
1985
 
        self.assertEqual(req.get('SCRIPT_NAME', None), '')
1986
 
        self.assertEqual(req.get('SERVER_NAME', None), 'www.example.com')
1987
 
        self.assertEqual(req.get('SERVER_PORT', None), '443')
1988
 
        environ_add_POST(req, None)
1989
 
        self.assert_('CONTENT_TYPE' not in req)
1990
 
        self.assert_('CONTENT_LENGTH' not in req)
1991
 
        environ_add_POST(req, {'hello':'world'})
1992
 
        self.assert_(req.get('HTTP_HOST', None), 'www.example.com:443')
1993
 
        self.assertEqual(req.get('PATH_INFO', None), '/foo')
1994
 
        self.assertEqual(req.get('QUERY_STRING', None), 'bar=baz')
1995
 
        self.assertEqual(req.get('REQUEST_METHOD', None), 'POST')
1996
 
        self.assertEqual(req.get('SCRIPT_NAME', None), '')
1997
 
        self.assertEqual(req.get('SERVER_NAME', None), 'www.example.com')
1998
 
        self.assertEqual(req.get('SERVER_PORT', None), '443')
1999
 
        self.assertEqual(req.get('CONTENT_LENGTH', None),'11')
2000
 
        self.assertEqual(req.get('CONTENT_TYPE', None),
2001
 
                         'application/x-www-form-urlencoded')
2002
 
        self.assertEqual(req['wsgi.input'].read(), 'hello=world')
2003
 
 
2004
2908
 
2005
2909
    def test_post_does_not_reparse(self):
2006
2910
        # test that there's no repetitive parsing is happening on every
2007
2911
        # req.POST access
2008
 
        req = Request.blank('/',
 
2912
        req = self._blankOne('/',
2009
2913
            content_type='multipart/form-data; boundary=boundary',
2010
2914
            POST=_cgi_escaping_body
2011
2915
        )
2012
2916
        f0 = req.body_file_raw
2013
 
        post1 = req.str_POST
 
2917
        post1 = req.POST
2014
2918
        f1 = req.body_file_raw
2015
 
        self.assert_(f1 is not f0)
2016
 
        post2 = req.str_POST
 
2919
        self.assertTrue(f1 is not f0)
 
2920
        post2 = req.POST
2017
2921
        f2 = req.body_file_raw
2018
 
        self.assert_(post1 is post2)
2019
 
        self.assert_(f1 is f2)
 
2922
        self.assertTrue(post1 is post2)
 
2923
        self.assertTrue(f1 is f2)
2020
2924
 
2021
2925
 
2022
2926
    def test_middleware_body(self):
2025
2929
            return [env['wsgi.input'].read()]
2026
2930
 
2027
2931
        def mw(env, sr):
2028
 
            req = Request(env)
 
2932
            req = self._makeOne(env)
2029
2933
            data = req.body_file.read()
2030
2934
            resp = req.get_response(app)
2031
2935
            resp.headers['x-data'] = data
2032
2936
            return resp(env, sr)
2033
2937
 
2034
 
        req = Request.blank('/', method='PUT', body='abc')
 
2938
        req = self._blankOne('/', method='PUT', body=b'abc')
2035
2939
        resp = req.get_response(mw)
2036
 
        self.assertEqual(resp.body, 'abc')
2037
 
        self.assertEqual(resp.headers['x-data'], 'abc')
 
2940
        self.assertEqual(resp.body, b'abc')
 
2941
        self.assertEqual(resp.headers['x-data'], b'abc')
2038
2942
 
2039
2943
    def test_body_file_noseek(self):
2040
 
        req = Request.blank('/', method='PUT', body='abc')
 
2944
        req = self._blankOne('/', method='PUT', body=b'abc')
2041
2945
        lst = [req.body_file.read(1) for i in range(3)]
2042
 
        self.assertEqual(lst, ['a','b','c'])
 
2946
        self.assertEqual(lst, [b'a', b'b', b'c'])
2043
2947
 
2044
2948
    def test_cgi_escaping_fix(self):
2045
 
        req = Request.blank('/',
 
2949
        req = self._blankOne('/',
2046
2950
            content_type='multipart/form-data; boundary=boundary',
2047
2951
            POST=_cgi_escaping_body
2048
2952
        )
2049
 
        self.assertEqual(req.POST.keys(), ['%20%22"'])
 
2953
        self.assertEqual(list(req.POST.keys()), ['%20%22"'])
2050
2954
        req.body_file.read()
2051
 
        self.assertEqual(req.POST.keys(), ['%20%22"'])
 
2955
        self.assertEqual(list(req.POST.keys()), ['%20%22"'])
2052
2956
 
2053
2957
    def test_content_type_none(self):
2054
 
        r = Request.blank('/', content_type='text/html')
 
2958
        r = self._blankOne('/', content_type='text/html')
2055
2959
        self.assertEqual(r.content_type, 'text/html')
2056
2960
        r.content_type = None
2057
2961
 
2058
 
    def test_charset_in_content_type(self):
2059
 
        r = Request({'CONTENT_TYPE':'text/html;charset=ascii'})
2060
 
        r.charset = 'shift-jis'
2061
 
        self.assertEqual(r.charset, 'shift-jis')
2062
 
 
2063
2962
    def test_body_file_seekable(self):
2064
 
        from cStringIO import StringIO
2065
 
        r = Request.blank('/', method='POST')
2066
 
        r.body_file = StringIO('body')
2067
 
        self.assertEqual(r.body_file_seekable.read(), 'body')
 
2963
        r = self._blankOne('/', method='POST')
 
2964
        r.body_file = BytesIO(b'body')
 
2965
        self.assertEqual(r.body_file_seekable.read(), b'body')
2068
2966
 
2069
2967
    def test_request_init(self):
2070
2968
        # port from doctest (docs/reference.txt)
2071
 
        req = Request.blank('/article?id=1')
 
2969
        req = self._blankOne('/article?id=1')
2072
2970
        self.assertEqual(req.environ['HTTP_HOST'], 'localhost:80')
2073
2971
        self.assertEqual(req.environ['PATH_INFO'], '/article')
2074
2972
        self.assertEqual(req.environ['QUERY_STRING'], 'id=1')
2077
2975
        self.assertEqual(req.environ['SERVER_NAME'], 'localhost')
2078
2976
        self.assertEqual(req.environ['SERVER_PORT'], '80')
2079
2977
        self.assertEqual(req.environ['SERVER_PROTOCOL'], 'HTTP/1.0')
2080
 
        self.assert_(hasattr(req.environ['wsgi.errors'], 'write') and
 
2978
        self.assertTrue(hasattr(req.environ['wsgi.errors'], 'write') and
2081
2979
                     hasattr(req.environ['wsgi.errors'], 'flush'))
2082
 
        self.assert_(hasattr(req.environ['wsgi.input'], 'next'))
 
2980
        self.assertTrue(hasattr(req.environ['wsgi.input'], 'next') or
 
2981
                     hasattr(req.environ['wsgi.input'], '__next__'))
2083
2982
        self.assertEqual(req.environ['wsgi.multiprocess'], False)
2084
2983
        self.assertEqual(req.environ['wsgi.multithread'], False)
2085
2984
        self.assertEqual(req.environ['wsgi.run_once'], False)
2087
2986
        self.assertEqual(req.environ['wsgi.version'], (1, 0))
2088
2987
 
2089
2988
        # Test body
2090
 
        self.assert_(hasattr(req.body_file, 'read'))
2091
 
        self.assertEqual(req.body, '')
 
2989
        self.assertTrue(hasattr(req.body_file, 'read'))
 
2990
        self.assertEqual(req.body, b'')
2092
2991
        req.method = 'PUT'
2093
 
        req.body = 'test'
2094
 
        self.assert_(hasattr(req.body_file, 'read'))
2095
 
        self.assertEqual(req.body, 'test')
 
2992
        req.body = b'test'
 
2993
        self.assertTrue(hasattr(req.body_file, 'read'))
 
2994
        self.assertEqual(req.body, b'test')
2096
2995
 
2097
2996
        # Test method & URL
2098
2997
        self.assertEqual(req.method, 'PUT')
2103
3002
        # Content-Type of the request body
2104
3003
        self.assertEqual(req.content_type, '')
2105
3004
        # The auth'ed user (there is none set)
2106
 
        self.assert_(req.remote_user is None)
2107
 
        self.assert_(req.remote_addr is None)
 
3005
        self.assertTrue(req.remote_user is None)
 
3006
        self.assertTrue(req.remote_addr is None)
2108
3007
        self.assertEqual(req.host, 'localhost:80')
2109
3008
        self.assertEqual(req.host_url, 'http://localhost')
2110
3009
        self.assertEqual(req.application_url, 'http://localhost/blog')
2139
3038
        from webob.multidict import MultiDict
2140
3039
        from webob.multidict import NestedMultiDict
2141
3040
        from webob.multidict import NoVars
2142
 
        from webob.multidict import TrackableMultiDict
2143
 
        req = Request.blank('/test?check=a&check=b&name=Bob')
2144
 
        GET = TrackableMultiDict([('check', 'a'),
2145
 
                                  ('check', 'b'),
2146
 
                                  ('name', 'Bob')])
2147
 
        self.assertEqual(req.str_GET, GET)
2148
 
        self.assertEqual(req.str_GET['check'], 'b')
2149
 
        self.assertEqual(req.str_GET.getall('check'), ['a', 'b'])
2150
 
        self.assertEqual(req.str_GET.items(),
 
3041
        from webob.multidict import GetDict
 
3042
        req = self._blankOne('/test?check=a&check=b&name=Bob')
 
3043
        GET = GetDict([('check', 'a'),
 
3044
                      ('check', 'b'),
 
3045
                      ('name', 'Bob')], {})
 
3046
        self.assertEqual(req.GET, GET)
 
3047
        self.assertEqual(req.GET['check'], 'b')
 
3048
        self.assertEqual(req.GET.getall('check'), ['a', 'b'])
 
3049
        self.assertEqual(list(req.GET.items()),
2151
3050
                         [('check', 'a'), ('check', 'b'), ('name', 'Bob')])
2152
3051
 
2153
 
        self.assert_(isinstance(req.str_POST, NoVars))
 
3052
        self.assertTrue(isinstance(req.POST, NoVars))
2154
3053
        # NoVars can be read like a dict, but not written
2155
 
        self.assertEqual(req.str_POST.items(), [])
 
3054
        self.assertEqual(list(req.POST.items()), [])
2156
3055
        req.method = 'POST'
2157
 
        req.body = 'name=Joe&email=joe@example.com'
2158
 
        self.assertEqual(req.str_POST,
 
3056
        req.body = b'name=Joe&email=joe@example.com'
 
3057
        self.assertEqual(req.POST,
2159
3058
                         MultiDict([('name', 'Joe'),
2160
3059
                                    ('email', 'joe@example.com')]))
2161
 
        self.assertEqual(req.str_POST['name'], 'Joe')
 
3060
        self.assertEqual(req.POST['name'], 'Joe')
2162
3061
 
2163
 
        self.assert_(isinstance(req.str_params, NestedMultiDict))
2164
 
        self.assertEqual(req.str_params.items(),
 
3062
        self.assertTrue(isinstance(req.params, NestedMultiDict))
 
3063
        self.assertEqual(list(req.params.items()),
2165
3064
                         [('check', 'a'),
2166
3065
                          ('check', 'b'),
2167
3066
                          ('name', 'Bob'),
2168
3067
                          ('name', 'Joe'),
2169
3068
                          ('email', 'joe@example.com')])
2170
 
        self.assertEqual(req.str_params['name'], 'Bob')
2171
 
        self.assertEqual(req.str_params.getall('name'), ['Bob', 'Joe'])
 
3069
        self.assertEqual(req.params['name'], 'Bob')
 
3070
        self.assertEqual(req.params.getall('name'), ['Bob', 'Joe'])
2172
3071
 
2173
3072
    def test_request_put(self):
2174
3073
        from datetime import datetime
2177
3076
        from webob.acceptparse import MIMEAccept
2178
3077
        from webob.byterange import Range
2179
3078
        from webob.etag import ETagMatcher
2180
 
        from webob.etag import _NoIfRange
2181
3079
        from webob.multidict import MultiDict
2182
 
        from webob.multidict import TrackableMultiDict
2183
 
        from webob.multidict import UnicodeMultiDict
2184
 
        req = Request.blank('/test?check=a&check=b&name=Bob')
 
3080
        from webob.multidict import GetDict
 
3081
        req = self._blankOne('/test?check=a&check=b&name=Bob')
2185
3082
        req.method = 'PUT'
2186
 
        req.body = 'var1=value1&var2=value2&rep=1&rep=2'
 
3083
        req.body = b'var1=value1&var2=value2&rep=1&rep=2'
2187
3084
        req.environ['CONTENT_LENGTH'] = str(len(req.body))
2188
3085
        req.environ['CONTENT_TYPE'] = 'application/x-www-form-urlencoded'
2189
 
        GET = TrackableMultiDict([('check', 'a'),
2190
 
                                  ('check', 'b'),
2191
 
                                  ('name', 'Bob')])
2192
 
        self.assertEqual(req.str_GET, GET)
2193
 
        self.assertEqual(req.str_POST, MultiDict(
 
3086
        GET = GetDict([('check', 'a'),
 
3087
                      ('check', 'b'),
 
3088
                      ('name', 'Bob')], {})
 
3089
        self.assertEqual(req.GET, GET)
 
3090
        self.assertEqual(req.POST, MultiDict(
2194
3091
                                [('var1', 'value1'),
2195
3092
                                 ('var2', 'value2'),
2196
3093
                                 ('rep', '1'),
2197
3094
                                 ('rep', '2')]))
 
3095
        self.assertEqual(
 
3096
            list(req.GET.items()),
 
3097
            [('check', 'a'), ('check', 'b'), ('name', 'Bob')])
2198
3098
 
2199
3099
        # Unicode
2200
3100
        req.charset = 'utf8'
2201
 
        self.assert_(isinstance(req.GET, UnicodeMultiDict))
2202
 
        self.assertEqual(req.GET.items(),
2203
 
                         [('check', u'a'), ('check', u'b'), ('name', u'Bob')])
 
3101
        self.assertEqual(list(req.GET.items()),
 
3102
                         [('check', 'a'), ('check', 'b'), ('name', 'Bob')])
2204
3103
 
2205
3104
        # Cookies
2206
3105
        req.headers['Cookie'] = 'test=value'
2207
 
        self.assert_(isinstance(req.cookies, UnicodeMultiDict))
2208
 
        self.assertEqual(req.cookies.items(), [('test', u'value')])
 
3106
        self.assertTrue(isinstance(req.cookies, collections.MutableMapping))
 
3107
        self.assertEqual(list(req.cookies.items()), [('test', 'value')])
2209
3108
        req.charset = None
2210
 
        self.assertEqual(req.str_cookies, {'test': 'value'})
 
3109
        self.assertEqual(req.cookies, {'test': 'value'})
2211
3110
 
2212
3111
        # Accept-* headers
2213
 
        self.assert_('text/html' in req.accept)
 
3112
        self.assertTrue('text/html' in req.accept)
2214
3113
        req.accept = 'text/html;q=0.5, application/xhtml+xml;q=1'
2215
 
        self.assert_(isinstance(req.accept, MIMEAccept))
2216
 
        self.assert_('text/html' in req.accept)
 
3114
        self.assertTrue(isinstance(req.accept, MIMEAccept))
 
3115
        self.assertTrue('text/html' in req.accept)
2217
3116
 
2218
 
        self.assertEqual(req.accept.first_match(['text/html',
2219
 
                                    'application/xhtml+xml']), 'text/html')
 
3117
        self.assertRaises(DeprecationWarning,
 
3118
                          req.accept.first_match, ['text/html'])
2220
3119
        self.assertEqual(req.accept.best_match(['text/html',
2221
3120
                                                'application/xhtml+xml']),
2222
3121
                         'application/xhtml+xml')
2223
 
        self.assertEqual(req.accept.best_matches(),
2224
 
                         ['application/xhtml+xml', 'text/html'])
2225
3122
 
2226
3123
        req.accept_language = 'es, pt-BR'
2227
 
        self.assertEqual(req.accept_language.best_matches('en-US'),
2228
 
                         ['es', 'pt-BR', 'en-US'])
2229
 
        self.assertEqual(req.accept_language.best_matches('es'), ['es'])
 
3124
        self.assertEqual(req.accept_language.best_match(['es']), 'es')
2230
3125
 
2231
3126
        # Conditional Requests
2232
3127
        server_token = 'opaque-token'
2233
3128
        # shouldn't return 304
2234
 
        self.assert_(not server_token in req.if_none_match)
 
3129
        self.assertTrue(not server_token in req.if_none_match)
2235
3130
        req.if_none_match = server_token
2236
 
        self.assert_(isinstance(req.if_none_match, ETagMatcher))
 
3131
        self.assertTrue(isinstance(req.if_none_match, ETagMatcher))
2237
3132
        # You *should* return 304
2238
 
        self.assert_(server_token in req.if_none_match)
 
3133
        self.assertTrue(server_token in req.if_none_match)
 
3134
        # if_none_match should use weak matching
 
3135
        weak_token = 'W/"%s"' % server_token
 
3136
        req.if_none_match = weak_token
 
3137
        assert req.headers['if-none-match'] == weak_token
 
3138
        self.assertTrue(server_token in req.if_none_match)
 
3139
 
2239
3140
 
2240
3141
        req.if_modified_since = datetime(2006, 1, 1, 12, 0, tzinfo=UTC)
2241
3142
        self.assertEqual(req.headers['If-Modified-Since'],
2242
3143
                         'Sun, 01 Jan 2006 12:00:00 GMT')
2243
3144
        server_modified = datetime(2005, 1, 1, 12, 0, tzinfo=UTC)
2244
 
        self.assert_(req.if_modified_since)
2245
 
        self.assert_(req.if_modified_since >= server_modified)
 
3145
        self.assertTrue(req.if_modified_since)
 
3146
        self.assertTrue(req.if_modified_since >= server_modified)
2246
3147
 
2247
 
        self.assert_(isinstance(req.if_range, _NoIfRange))
2248
 
        self.assert_(req.if_range.match(etag='some-etag',
2249
 
                     last_modified=datetime(2005, 1, 1, 12, 0)))
 
3148
        self.assertTrue(not req.if_range)
 
3149
        self.assertTrue(Response(etag='some-etag',
 
3150
                              last_modified=datetime(2005, 1, 1, 12, 0))
 
3151
            in req.if_range)
2250
3152
        req.if_range = 'opaque-etag'
2251
 
        self.assert_(not req.if_range.match(etag='other-etag'))
2252
 
        self.assert_(req.if_range.match(etag='opaque-etag'))
 
3153
        self.assertTrue(Response(etag='other-etag') not in req.if_range)
 
3154
        self.assertTrue(Response(etag='opaque-etag') in req.if_range)
2253
3155
 
2254
3156
        res = Response(etag='opaque-etag')
2255
 
        self.assert_(req.if_range.match_response(res))
 
3157
        self.assertTrue(res in req.if_range)
2256
3158
 
2257
3159
        req.range = 'bytes=0-100'
2258
 
        self.assert_(isinstance(req.range, Range))
2259
 
        self.assertEqual(req.range.ranges, [(0, 101)])
 
3160
        self.assertTrue(isinstance(req.range, Range))
 
3161
        self.assertEqual(tuple(req.range), (0, 101))
2260
3162
        cr = req.range.content_range(length=1000)
2261
 
        self.assertEqual((cr.start, cr.stop, cr.length), (0, 101, 1000))
 
3163
        self.assertEqual(tuple(cr), (0, 101, 1000))
2262
3164
 
2263
 
        self.assert_(server_token in req.if_match)
 
3165
        self.assertTrue(server_token in req.if_match)
2264
3166
        # No If-Match means everything is ok
2265
3167
        req.if_match = server_token
2266
 
        self.assert_(server_token in req.if_match)
 
3168
        self.assertTrue(server_token in req.if_match)
2267
3169
        # Still OK
2268
3170
        req.if_match = 'other-token'
2269
3171
        # Not OK, should return 412 Precondition Failed:
2270
 
        self.assert_(not server_token in req.if_match)
 
3172
        self.assertTrue(not server_token in req.if_match)
2271
3173
 
2272
3174
    def test_call_WSGI_app(self):
2273
 
        req = Request.blank('/')
 
3175
        req = self._blankOne('/')
2274
3176
        def wsgi_app(environ, start_response):
2275
3177
            start_response('200 OK', [('Content-type', 'text/plain')])
2276
 
            return ['Hi!']
 
3178
            return [b'Hi!']
2277
3179
        self.assertEqual(req.call_application(wsgi_app),
2278
 
                         ('200 OK', [('Content-type', 'text/plain')], ['Hi!']))
 
3180
                         ('200 OK', [('Content-type', 'text/plain')],
 
3181
                          [b'Hi!']))
2279
3182
 
2280
3183
        res = req.get_response(wsgi_app)
2281
3184
        from webob.response import Response
2282
 
        self.assert_(isinstance(res, Response))
2283
 
        self.assertEqual(res.status, '200 OK')
2284
 
        from webob.headers import ResponseHeaders
2285
 
        self.assert_(isinstance(res.headers, ResponseHeaders))
2286
 
        self.assertEqual(res.headers.items(), [('Content-type', 'text/plain')])
2287
 
        self.assertEqual(res.body, 'Hi!')
2288
 
 
2289
 
    def equal_req(self, req):
2290
 
        from cStringIO import StringIO
2291
 
        input = StringIO(str(req))
2292
 
        req2 = Request.from_file(input)
 
3185
        self.assertTrue(isinstance(res, Response))
 
3186
        self.assertEqual(res.status, '200 OK')
 
3187
        from webob.headers import ResponseHeaders
 
3188
        self.assertTrue(isinstance(res.headers, ResponseHeaders))
 
3189
        self.assertEqual(list(res.headers.items()),
 
3190
                         [('Content-type', 'text/plain')])
 
3191
        self.assertEqual(res.body, b'Hi!')
 
3192
 
 
3193
    def test_get_response_catch_exc_info_true(self):
 
3194
        req = self._blankOne('/')
 
3195
        def wsgi_app(environ, start_response):
 
3196
            start_response('200 OK', [('Content-type', 'text/plain')])
 
3197
            return [b'Hi!']
 
3198
        res = req.get_response(wsgi_app, catch_exc_info=True)
 
3199
        from webob.response import Response
 
3200
        self.assertTrue(isinstance(res, Response))
 
3201
        self.assertEqual(res.status, '200 OK')
 
3202
        from webob.headers import ResponseHeaders
 
3203
        self.assertTrue(isinstance(res.headers, ResponseHeaders))
 
3204
        self.assertEqual(list(res.headers.items()),
 
3205
                         [('Content-type', 'text/plain')])
 
3206
        self.assertEqual(res.body, b'Hi!')
 
3207
 
 
3208
    def equal_req(self, req, inp):
 
3209
        cls = self._getTargetClass()
 
3210
        req2 = cls.from_file(inp)
2293
3211
        self.assertEqual(req.url, req2.url)
2294
3212
        headers1 = dict(req.headers)
2295
3213
        headers2 = dict(req2.headers)
2300
3218
        if 'Content-Length' in headers2:
2301
3219
            del headers2['Content-Length']
2302
3220
        self.assertEqual(headers1, headers2)
2303
 
        self.assertEqual(req.body, req2.body)
2304
 
 
 
3221
        req_body = req.body
 
3222
        req2_body = req2.body
 
3223
        self.assertEqual(req_body, req2_body)
 
3224
 
 
3225
class FakeCGIBodyTests(unittest.TestCase):
 
3226
    def test_encode_multipart_value_type_options(self):
 
3227
        from cgi import FieldStorage
 
3228
        from webob.request import BaseRequest, FakeCGIBody
 
3229
        from webob.multidict import MultiDict
 
3230
        multipart_type = 'multipart/form-data; boundary=foobar'
 
3231
        from io import BytesIO
 
3232
        body = (
 
3233
            b'--foobar\r\n'
 
3234
            b'Content-Disposition: form-data; name="bananas"; filename="bananas.txt"\r\n'
 
3235
            b'Content-type: text/plain; charset="utf-7"\r\n'
 
3236
            b'\r\n'
 
3237
            b"these are the contents of the file 'bananas.txt'\r\n"
 
3238
            b'\r\n'
 
3239
            b'--foobar--')
 
3240
        multipart_body = BytesIO(body)
 
3241
        environ = BaseRequest.blank('/').environ
 
3242
        environ.update(CONTENT_TYPE=multipart_type)
 
3243
        environ.update(REQUEST_METHOD='POST')
 
3244
        environ.update(CONTENT_LENGTH=len(body))
 
3245
        fs = FieldStorage(multipart_body, environ=environ)
 
3246
        vars = MultiDict.from_fieldstorage(fs)
 
3247
        self.assertEqual(vars['bananas'].__class__, FieldStorage)
 
3248
        fake_body = FakeCGIBody(vars, multipart_type)
 
3249
        self.assertEqual(fake_body.read(), body)
 
3250
 
 
3251
    def test_encode_multipart_no_boundary(self):
 
3252
        from webob.request import FakeCGIBody
 
3253
        self.assertRaises(ValueError, FakeCGIBody, {}, 'multipart/form-data')
 
3254
 
 
3255
    def test_repr(self):
 
3256
        from webob.request import FakeCGIBody
 
3257
        body = FakeCGIBody({'bananas': 'bananas'},
 
3258
                           'multipart/form-data; boundary=foobar')
 
3259
        body.read(1)
 
3260
        import re
 
3261
        self.assertEqual(
 
3262
            re.sub(r'\b0x[0-9a-f]+\b', '<whereitsat>', repr(body)),
 
3263
            "<FakeCGIBody at <whereitsat> viewing {'bananas': 'ba...nas'}>",
 
3264
        )
 
3265
 
 
3266
    def test_fileno(self):
 
3267
        from webob.request import FakeCGIBody
 
3268
        body = FakeCGIBody({'bananas': 'bananas'},
 
3269
                           'multipart/form-data; boundary=foobar')
 
3270
        self.assertEqual(body.fileno(), None)
 
3271
 
 
3272
    def test_iter(self):
 
3273
        from webob.request import FakeCGIBody
 
3274
        body = FakeCGIBody({'bananas': 'bananas'},
 
3275
                           'multipart/form-data; boundary=foobar')
 
3276
        self.assertEqual(list(body), [
 
3277
            b'--foobar\r\n',
 
3278
            b'Content-Disposition: form-data; name="bananas"\r\n',
 
3279
            b'\r\n',
 
3280
            b'bananas\r\n',
 
3281
            b'--foobar--',
 
3282
         ])
 
3283
 
 
3284
    def test_readline(self):
 
3285
        from webob.request import FakeCGIBody
 
3286
        body = FakeCGIBody({'bananas': 'bananas'},
 
3287
                           'multipart/form-data; boundary=foobar')
 
3288
        self.assertEqual(body.readline(), b'--foobar\r\n')
 
3289
        self.assertEqual(
 
3290
            body.readline(),
 
3291
            b'Content-Disposition: form-data; name="bananas"\r\n')
 
3292
        self.assertEqual(body.readline(), b'\r\n')
 
3293
        self.assertEqual(body.readline(), b'bananas\r\n')
 
3294
        self.assertEqual(body.readline(), b'--foobar--')
 
3295
        # subsequent calls to readline will return ''
 
3296
 
 
3297
    def test_read_bad_content_type(self):
 
3298
        from webob.request import FakeCGIBody
 
3299
        body = FakeCGIBody({'bananas': 'bananas'}, 'application/jibberjabber')
 
3300
        self.assertRaises(AssertionError, body.read)
 
3301
 
 
3302
    def test_read_urlencoded(self):
 
3303
        from webob.request import FakeCGIBody
 
3304
        body = FakeCGIBody({'bananas': 'bananas'},
 
3305
                           'application/x-www-form-urlencoded')
 
3306
        self.assertEqual(body.read(), b'bananas=bananas')
 
3307
 
 
3308
 
 
3309
class Test_cgi_FieldStorage__repr__patch(unittest.TestCase):
 
3310
    def _callFUT(self, fake):
 
3311
        from webob.request import _cgi_FieldStorage__repr__patch
 
3312
        return _cgi_FieldStorage__repr__patch(fake)
 
3313
 
 
3314
    def test_with_file(self):
 
3315
        class Fake(object):
 
3316
            name = 'name'
 
3317
            file = 'file'
 
3318
            filename = 'filename'
 
3319
            value = 'value'
 
3320
        fake = Fake()
 
3321
        result = self._callFUT(fake)
 
3322
        self.assertEqual(result, "FieldStorage('name', 'filename')")
 
3323
 
 
3324
    def test_without_file(self):
 
3325
        class Fake(object):
 
3326
            name = 'name'
 
3327
            file = None
 
3328
            filename = 'filename'
 
3329
            value = 'value'
 
3330
        fake = Fake()
 
3331
        result = self._callFUT(fake)
 
3332
        self.assertEqual(result, "FieldStorage('name', 'filename', 'value')")
 
3333
 
 
3334
 
 
3335
class TestLimitedLengthFile(unittest.TestCase):
 
3336
    def _makeOne(self, file, maxlen):
 
3337
        from webob.request import LimitedLengthFile
 
3338
        return LimitedLengthFile(file, maxlen)
 
3339
 
 
3340
    def test_fileno(self):
 
3341
        class DummyFile(object):
 
3342
            def fileno(self):
 
3343
                return 1
 
3344
        dummyfile = DummyFile()
 
3345
        inst = self._makeOne(dummyfile, 0)
 
3346
        self.assertEqual(inst.fileno(), 1)
 
3347
 
 
3348
 
 
3349
class Test_environ_from_url(unittest.TestCase):
 
3350
    def _callFUT(self, *arg, **kw):
 
3351
        from webob.request import environ_from_url
 
3352
        return environ_from_url(*arg, **kw)
 
3353
 
 
3354
    def test_environ_from_url(self):
 
3355
        # Generating an environ just from an url plus testing environ_add_POST
 
3356
        self.assertRaises(TypeError, self._callFUT,
 
3357
                    'http://www.example.com/foo?bar=baz#qux')
 
3358
        self.assertRaises(TypeError, self._callFUT,
 
3359
                    'gopher://gopher.example.com')
 
3360
        req = self._callFUT('http://www.example.com/foo?bar=baz')
 
3361
        self.assertEqual(req.get('HTTP_HOST', None), 'www.example.com:80')
 
3362
        self.assertEqual(req.get('PATH_INFO', None), '/foo')
 
3363
        self.assertEqual(req.get('QUERY_STRING', None), 'bar=baz')
 
3364
        self.assertEqual(req.get('REQUEST_METHOD', None), 'GET')
 
3365
        self.assertEqual(req.get('SCRIPT_NAME', None), '')
 
3366
        self.assertEqual(req.get('SERVER_NAME', None), 'www.example.com')
 
3367
        self.assertEqual(req.get('SERVER_PORT', None), '80')
 
3368
        req = self._callFUT('https://www.example.com/foo?bar=baz')
 
3369
        self.assertEqual(req.get('HTTP_HOST', None), 'www.example.com:443')
 
3370
        self.assertEqual(req.get('PATH_INFO', None), '/foo')
 
3371
        self.assertEqual(req.get('QUERY_STRING', None), 'bar=baz')
 
3372
        self.assertEqual(req.get('REQUEST_METHOD', None), 'GET')
 
3373
        self.assertEqual(req.get('SCRIPT_NAME', None), '')
 
3374
        self.assertEqual(req.get('SERVER_NAME', None), 'www.example.com')
 
3375
        self.assertEqual(req.get('SERVER_PORT', None), '443')
 
3376
 
 
3377
 
 
3378
        from webob.request import environ_add_POST
 
3379
 
 
3380
        environ_add_POST(req, None)
 
3381
        self.assertTrue('CONTENT_TYPE' not in req)
 
3382
        self.assertTrue('CONTENT_LENGTH' not in req)
 
3383
        environ_add_POST(req, {'hello':'world'})
 
3384
        self.assertTrue(req.get('HTTP_HOST', None), 'www.example.com:443')
 
3385
        self.assertEqual(req.get('PATH_INFO', None), '/foo')
 
3386
        self.assertEqual(req.get('QUERY_STRING', None), 'bar=baz')
 
3387
        self.assertEqual(req.get('REQUEST_METHOD', None), 'POST')
 
3388
        self.assertEqual(req.get('SCRIPT_NAME', None), '')
 
3389
        self.assertEqual(req.get('SERVER_NAME', None), 'www.example.com')
 
3390
        self.assertEqual(req.get('SERVER_PORT', None), '443')
 
3391
        self.assertEqual(req.get('CONTENT_LENGTH', None),'11')
 
3392
        self.assertEqual(req.get('CONTENT_TYPE', None),
 
3393
                         'application/x-www-form-urlencoded')
 
3394
        self.assertEqual(req['wsgi.input'].read(), b'hello=world')
 
3395
 
 
3396
    def test_environ_from_url_highorder_path_info(self):
 
3397
        from webob.request import Request
 
3398
        env = self._callFUT('/%E6%B5%81')
 
3399
        self.assertEqual(env['PATH_INFO'], '/\xe6\xb5\x81')
 
3400
        request = Request(env)
 
3401
        expected = text_(b'/\xe6\xb5\x81', 'utf-8') # u'/\u6d41'
 
3402
        self.assertEqual(request.path_info, expected)
 
3403
        self.assertEqual(request.upath_info, expected)
 
3404
 
 
3405
    def test_fileupload_mime_type_detection(self):
 
3406
        from webob.request import Request
 
3407
        # sometimes on win the detected mime type for .jpg will be image/pjpeg for ex.
 
3408
        # so we use a non-standard extesion to avoid that
 
3409
        import mimetypes
 
3410
        mimetypes.add_type('application/x-foo', '.foo')
 
3411
        request = Request.blank("/", POST=dict(file1=("foo.foo", "xxx"),
 
3412
                                               file2=("bar.mp3", "xxx")))
 
3413
        self.assert_("audio/mpeg" in request.body.decode('ascii'), str(request))
 
3414
        self.assert_('application/x-foo' in request.body.decode('ascii'), str(request))
 
3415
 
 
3416
class TestRequestMultipart(unittest.TestCase):
 
3417
    def test_multipart_with_charset(self):
 
3418
        from webob.request import Request
 
3419
        req = Request.from_string(_test_req_multipart_charset)
 
3420
        self.assertEqual(req.POST['title'].encode('utf8'),
 
3421
                         text_('こんにちは', 'utf-8').encode('utf8'))
2305
3422
 
2306
3423
def simpleapp(environ, start_response):
 
3424
    from webob.request import Request
2307
3425
    status = '200 OK'
2308
3426
    response_headers = [('Content-type','text/plain')]
2309
3427
    start_response(status, response_headers)
2310
3428
    request = Request(environ)
2311
3429
    request.remote_user = 'bob'
2312
 
    return [
 
3430
    return [ bytes_(x) for x in [
2313
3431
        'Hello world!\n',
2314
 
        'The get is %r' % request.str_GET,
2315
 
        ' and Val is %s\n' % request.str_GET.get('name'),
2316
 
        'The languages are: %s\n' %
2317
 
            request.accept_language.best_matches('en-US'),
 
3432
        'The get is %r' % request.GET,
 
3433
        ' and Val is %s\n' % repr(request.GET.get('name')),
 
3434
        'The languages are: %s\n' % list(request.accept_language),
2318
3435
        'The accepttypes is: %s\n' %
2319
3436
            request.accept.best_match(['application/xml', 'text/html']),
2320
 
        'post is %r\n' % request.str_POST,
2321
 
        'params is %r\n' % request.str_params,
2322
 
        'cookies is %r\n' % request.str_cookies,
 
3437
        'post is %r\n' % request.POST,
 
3438
        'params is %r\n' % request.params,
 
3439
        'cookies is %r\n' % request.cookies,
2323
3440
        'body: %r\n' % request.body,
2324
3441
        'method: %s\n' % request.method,
2325
3442
        'remote_user: %r\n' % request.environ['REMOTE_USER'],
2334
3451
        'if_modified_since: %r\n' % request.if_modified_since,
2335
3452
        'user_agent: %r\n' % request.user_agent,
2336
3453
        'if_none_match: %r\n' % request.if_none_match,
2337
 
        ]
2338
 
 
2339
 
 
 
3454
        ]]
2340
3455
 
2341
3456
_cgi_escaping_body = '''--boundary
2342
3457
Content-Disposition: form-data; name="%20%22""
2345
3460
--boundary--'''
2346
3461
 
2347
3462
def _norm_req(s):
2348
 
    return '\r\n'.join(s.strip().replace('\r','').split('\n'))
 
3463
    return b'\r\n'.join(s.strip().replace(b'\r', b'').split(b'\n'))
2349
3464
 
2350
 
_test_req = """
 
3465
_test_req = b"""
2351
3466
POST /webob/ HTTP/1.0
2352
3467
Accept: */*
2353
3468
Cache-Control: max-age=0
2368
3483
------------------------------deb95b63e42a--
2369
3484
"""
2370
3485
 
2371
 
_test_req2 = """
 
3486
_test_req2 = b"""
2372
3487
POST / HTTP/1.0
2373
3488
Content-Length: 0
2374
3489
 
2375
3490
"""
2376
3491
 
 
3492
_test_req_multipart_charset = b"""
 
3493
POST /upload/ HTTP/1.1
 
3494
Host: foo.com
 
3495
User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.2.13) Gecko/20101206 Ubuntu/10.04 (lucid) Firefox/3.6.13
 
3496
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
 
3497
Accept-Language: en-US,en;q=0.8,ja;q=0.6
 
3498
Accept-Encoding: gzip,deflate
 
3499
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
 
3500
Content-Type: multipart/form-data; boundary=000e0ce0b196b4ee6804c6c8af94
 
3501
Content-Length: 926
 
3502
 
 
3503
--000e0ce0b196b4ee6804c6c8af94
 
3504
Content-Type: text/plain; charset=ISO-2022-JP
 
3505
Content-Disposition: form-data; name=title
 
3506
Content-Transfer-Encoding: 7bit
 
3507
 
 
3508
\x1b$B$3$s$K$A$O\x1b(B
 
3509
--000e0ce0b196b4ee6804c6c8af94
 
3510
Content-Type: text/plain; charset=ISO-8859-1
 
3511
Content-Disposition: form-data; name=submit
 
3512
 
 
3513
Submit
 
3514
--000e0ce0b196b4ee6804c6c8af94
 
3515
Content-Type: message/external-body; charset=ISO-8859-1; blob-key=AMIfv94TgpPBtKTL3a0U9Qh1QCX7OWSsmdkIoD2ws45kP9zQAGTOfGNz4U18j7CVXzODk85WtiL5gZUFklTGY3y4G0Jz3KTPtJBOFDvQHQew7YUymRIpgUXgENS_fSEmInAIQdpSc2E78MRBVEZY392uhph3r-In96t8Z58WIRc-Yikx1bnarWo
 
3516
Content-Disposition: form-data; name=file; filename="photo.jpg"
 
3517
 
 
3518
Content-Type: image/jpeg
 
3519
Content-Length: 38491
 
3520
X-AppEngine-Upload-Creation: 2012-08-08 15:32:29.035959
 
3521
Content-MD5: ZjRmNGRhYmNhZTkyNzcyOWQ5ZGUwNDgzOWFkNDAxN2Y=
 
3522
Content-Disposition: form-data; name=file; filename="photo.jpg"
 
3523
 
 
3524
 
 
3525
--000e0ce0b196b4ee6804c6c8af94--"""
 
3526
 
 
3527
 
2377
3528
_test_req = _norm_req(_test_req)
2378
 
_test_req2 = _norm_req(_test_req2) + '\r\n'
 
3529
_test_req2 = _norm_req(_test_req2) + b'\r\n'
 
3530
_test_req_multipart_charset = _norm_req(_test_req_multipart_charset)
2379
3531
 
2380
3532
class UnseekableInput(object):
2381
3533
    def __init__(self, data):
2395
3547
class UnseekableInputWithSeek(UnseekableInput):
2396
3548
    def seek(self, pos, rel=0):
2397
3549
        raise IOError("Invalid seek!")
2398
 
 
2399
 
 
2400
 
class FakeCGIBodyTests(unittest.TestCase):
2401
 
 
2402
 
    def test_encode_multipart_value_type_options(self):
2403
 
        from StringIO import StringIO
2404
 
        from cgi import FieldStorage
2405
 
        from webob.request import BaseRequest, FakeCGIBody
2406
 
        from webob.multidict import MultiDict
2407
 
        multipart_type = 'multipart/form-data; boundary=foobar'
2408
 
        multipart_body = StringIO(
2409
 
            '--foobar\r\n'
2410
 
            'Content-Disposition: form-data; name="bananas"; filename="bananas.txt"\r\n'
2411
 
            'Content-type: text/plain; charset="utf-9"\r\n'
2412
 
            '\r\n'
2413
 
            "these are the contents of the file 'bananas.txt'\r\n"
2414
 
            '\r\n'
2415
 
            '--foobar--'
2416
 
        )
2417
 
        environ = BaseRequest.blank('/').environ
2418
 
        environ.update(CONTENT_TYPE=multipart_type)
2419
 
        environ.update(REQUEST_METHOD='POST')
2420
 
        fs = FieldStorage(multipart_body, environ=environ)
2421
 
        vars = MultiDict.from_fieldstorage(fs)
2422
 
        self.assertEqual(vars['bananas'].__class__, FieldStorage)
2423
 
        body = FakeCGIBody(vars, multipart_type)
2424
 
        self.assertEqual(body.read(), multipart_body.getvalue())
2425
 
 
2426
 
    def test_encode_multipart_no_boundary(self):
2427
 
        from webob.request import FakeCGIBody
2428
 
        self.assertRaises(ValueError, FakeCGIBody, {}, 'multipart/form-data')
2429
 
 
2430
 
    def test_repr(self):
2431
 
        from webob.request import FakeCGIBody
2432
 
        body = FakeCGIBody({'bananas': 'bananas'}, 'multipart/form-data; boundary=foobar')
2433
 
        body.read(1)
2434
 
        import re
2435
 
        self.assertEqual(
2436
 
            re.sub(r'\b0x[0-9a-f]+\b', '<whereitsat>', repr(body)),
2437
 
            "<FakeCGIBody at <whereitsat> viewing {'bananas': 'ba...nas'} at position 1>",
2438
 
        )
2439
 
 
2440
 
    def test_iter(self):
2441
 
        from webob.request import FakeCGIBody
2442
 
        body = FakeCGIBody({'bananas': 'bananas'}, 'multipart/form-data; boundary=foobar')
2443
 
        self.assertEqual(list(body), [
2444
 
            '--foobar\r\n',
2445
 
             'Content-Disposition: form-data; name="bananas"\r\n',
2446
 
             '\r\n',
2447
 
             'bananas\r\n',
2448
 
             '--foobar--',
2449
 
         ])
2450
 
 
2451
 
    def test_readline(self):
2452
 
        from webob.request import FakeCGIBody
2453
 
        body = FakeCGIBody({'bananas': 'bananas'}, 'multipart/form-data; boundary=foobar')
2454
 
        self.assertEqual(body.readline(), '--foobar\r\n')
2455
 
        self.assertEqual(body.readline(), 'Content-Disposition: form-data; name="bananas"\r\n')
2456
 
        self.assertEqual(body.readline(), '\r\n')
2457
 
        self.assertEqual(body.readline(), 'bananas\r\n')
2458
 
        self.assertEqual(body.readline(), '--foobar--')
2459
 
        # subsequent calls to readline will return ''
2460
 
 
2461
 
    def test_read_bad_content_type(self):
2462
 
        from webob.request import FakeCGIBody
2463
 
        body = FakeCGIBody({'bananas': 'bananas'}, 'application/jibberjabber')
2464
 
        self.assertRaises(AssertionError, body.read)
2465
 
 
2466
 
    def test_read_urlencoded(self):
2467
 
        from webob.request import FakeCGIBody
2468
 
        body = FakeCGIBody({'bananas': 'bananas'}, 'application/x-www-form-urlencoded')
2469
 
        self.assertEqual(body.read(), 'bananas=bananas')
2470
 
 
2471
 
    def test_tell(self):
2472
 
        from webob.request import FakeCGIBody
2473
 
        body = FakeCGIBody({'bananas': 'bananas'},
2474
 
                           'application/x-www-form-urlencoded')
2475
 
        body.position = 1
2476
 
        self.assertEqual(body.tell(), 1)
2477
 
 
2478
 
class Test_cgi_FieldStorage__repr__patch(unittest.TestCase):
2479
 
    def _callFUT(self, fake):
2480
 
        from webob.request import _cgi_FieldStorage__repr__patch
2481
 
        return _cgi_FieldStorage__repr__patch(fake)
2482
 
 
2483
 
    def test_with_file(self):
2484
 
        class Fake(object):
2485
 
            name = 'name'
2486
 
            file = 'file'
2487
 
            filename = 'filename'
2488
 
            value = 'value'
2489
 
        fake = Fake()
2490
 
        result = self._callFUT(fake)
2491
 
        self.assertEqual(result, "FieldStorage('name', 'filename')")
2492
 
 
2493
 
    def test_without_file(self):
2494
 
        class Fake(object):
2495
 
            name = 'name'
2496
 
            file = None
2497
 
            filename = 'filename'
2498
 
            value = 'value'
2499
 
        fake = Fake()
2500
 
        result = self._callFUT(fake)
2501
 
        self.assertEqual(result, "FieldStorage('name', 'filename', 'value')")