PageRenderTime 69ms CodeModel.GetById 47ms app.highlight 16ms RepoModel.GetById 1ms app.codeStats 0ms

/tests/regressiontests/requests/tests.py

https://code.google.com/p/mango-py/
Python | 355 lines | 317 code | 18 blank | 20 comment | 3 complexity | fa18324f1bb06f41b526de5fe218fd60 MD5 | raw file
  1import time
  2from datetime import datetime, timedelta
  3from StringIO import StringIO
  4
  5from django.conf import settings
  6from django.core.handlers.modpython import ModPythonRequest
  7from django.core.handlers.wsgi import WSGIRequest, LimitedStream
  8from django.http import HttpRequest, HttpResponse, parse_cookie
  9from django.utils import unittest
 10from django.utils.http import cookie_date
 11
 12
 13class RequestsTests(unittest.TestCase):
 14    def test_httprequest(self):
 15        request = HttpRequest()
 16        self.assertEqual(request.GET.keys(), [])
 17        self.assertEqual(request.POST.keys(), [])
 18        self.assertEqual(request.COOKIES.keys(), [])
 19        self.assertEqual(request.META.keys(), [])
 20
 21    def test_wsgirequest(self):
 22        request = WSGIRequest({'PATH_INFO': 'bogus', 'REQUEST_METHOD': 'bogus', 'wsgi.input': StringIO('')})
 23        self.assertEqual(request.GET.keys(), [])
 24        self.assertEqual(request.POST.keys(), [])
 25        self.assertEqual(request.COOKIES.keys(), [])
 26        self.assertEqual(set(request.META.keys()), set(['PATH_INFO', 'REQUEST_METHOD', 'SCRIPT_NAME', 'wsgi.input']))
 27        self.assertEqual(request.META['PATH_INFO'], 'bogus')
 28        self.assertEqual(request.META['REQUEST_METHOD'], 'bogus')
 29        self.assertEqual(request.META['SCRIPT_NAME'], '')
 30
 31    def test_modpythonrequest(self):
 32        class FakeModPythonRequest(ModPythonRequest):
 33           def __init__(self, *args, **kwargs):
 34               super(FakeModPythonRequest, self).__init__(*args, **kwargs)
 35               self._get = self._post = self._meta = self._cookies = {}
 36
 37        class Dummy:
 38            def get_options(self):
 39                return {}
 40
 41        req = Dummy()
 42        req.uri = 'bogus'
 43        request = FakeModPythonRequest(req)
 44        self.assertEqual(request.path, 'bogus')
 45        self.assertEqual(request.GET.keys(), [])
 46        self.assertEqual(request.POST.keys(), [])
 47        self.assertEqual(request.COOKIES.keys(), [])
 48        self.assertEqual(request.META.keys(), [])
 49
 50    def test_parse_cookie(self):
 51        self.assertEqual(parse_cookie('invalid:key=true'), {})
 52
 53    def test_httprequest_location(self):
 54        request = HttpRequest()
 55        self.assertEqual(request.build_absolute_uri(location="https://www.example.com/asdf"),
 56            'https://www.example.com/asdf')
 57
 58        request.get_host = lambda: 'www.example.com'
 59        request.path = ''
 60        self.assertEqual(request.build_absolute_uri(location="/path/with:colons"),
 61            'http://www.example.com/path/with:colons')
 62
 63    def test_http_get_host(self):
 64        old_USE_X_FORWARDED_HOST = settings.USE_X_FORWARDED_HOST
 65        try:
 66            settings.USE_X_FORWARDED_HOST = False
 67
 68            # Check if X_FORWARDED_HOST is provided.
 69            request = HttpRequest()
 70            request.META = {
 71                u'HTTP_X_FORWARDED_HOST': u'forward.com',
 72                u'HTTP_HOST': u'example.com',
 73                u'SERVER_NAME': u'internal.com',
 74                u'SERVER_PORT': 80,
 75            }
 76            # X_FORWARDED_HOST is ignored.
 77            self.assertEqual(request.get_host(), 'example.com')
 78
 79            # Check if X_FORWARDED_HOST isn't provided.
 80            request = HttpRequest()
 81            request.META = {
 82                u'HTTP_HOST': u'example.com',
 83                u'SERVER_NAME': u'internal.com',
 84                u'SERVER_PORT': 80,
 85            }
 86            self.assertEqual(request.get_host(), 'example.com')
 87
 88            # Check if HTTP_HOST isn't provided.
 89            request = HttpRequest()
 90            request.META = {
 91                u'SERVER_NAME': u'internal.com',
 92                u'SERVER_PORT': 80,
 93            }
 94            self.assertEqual(request.get_host(), 'internal.com')
 95
 96            # Check if HTTP_HOST isn't provided, and we're on a nonstandard port
 97            request = HttpRequest()
 98            request.META = {
 99                u'SERVER_NAME': u'internal.com',
100                u'SERVER_PORT': 8042,
101            }
102            self.assertEqual(request.get_host(), 'internal.com:8042')
103
104        finally:
105            settings.USE_X_FORWARDED_HOST = old_USE_X_FORWARDED_HOST
106
107    def test_http_get_host_with_x_forwarded_host(self):
108        old_USE_X_FORWARDED_HOST = settings.USE_X_FORWARDED_HOST
109        try:
110            settings.USE_X_FORWARDED_HOST = True
111
112            # Check if X_FORWARDED_HOST is provided.
113            request = HttpRequest()
114            request.META = {
115                u'HTTP_X_FORWARDED_HOST': u'forward.com',
116                u'HTTP_HOST': u'example.com',
117                u'SERVER_NAME': u'internal.com',
118                u'SERVER_PORT': 80,
119            }
120            # X_FORWARDED_HOST is obeyed.
121            self.assertEqual(request.get_host(), 'forward.com')
122
123            # Check if X_FORWARDED_HOST isn't provided.
124            request = HttpRequest()
125            request.META = {
126                u'HTTP_HOST': u'example.com',
127                u'SERVER_NAME': u'internal.com',
128                u'SERVER_PORT': 80,
129            }
130            self.assertEqual(request.get_host(), 'example.com')
131
132            # Check if HTTP_HOST isn't provided.
133            request = HttpRequest()
134            request.META = {
135                u'SERVER_NAME': u'internal.com',
136                u'SERVER_PORT': 80,
137            }
138            self.assertEqual(request.get_host(), 'internal.com')
139
140            # Check if HTTP_HOST isn't provided, and we're on a nonstandard port
141            request = HttpRequest()
142            request.META = {
143                u'SERVER_NAME': u'internal.com',
144                u'SERVER_PORT': 8042,
145            }
146            self.assertEqual(request.get_host(), 'internal.com:8042')
147
148        finally:
149            settings.USE_X_FORWARDED_HOST = old_USE_X_FORWARDED_HOST
150
151    def test_near_expiration(self):
152        "Cookie will expire when an near expiration time is provided"
153        response = HttpResponse()
154        # There is a timing weakness in this test; The
155        # expected result for max-age requires that there be
156        # a very slight difference between the evaluated expiration
157        # time, and the time evaluated in set_cookie(). If this
158        # difference doesn't exist, the cookie time will be
159        # 1 second larger. To avoid the problem, put in a quick sleep,
160        # which guarantees that there will be a time difference.
161        expires = datetime.utcnow() + timedelta(seconds=10)
162        time.sleep(0.001)
163        response.set_cookie('datetime', expires=expires)
164        datetime_cookie = response.cookies['datetime']
165        self.assertEqual(datetime_cookie['max-age'], 10)
166
167    def test_far_expiration(self):
168        "Cookie will expire when an distant expiration time is provided"
169        response = HttpResponse()
170        response.set_cookie('datetime', expires=datetime(2028, 1, 1, 4, 5, 6))
171        datetime_cookie = response.cookies['datetime']
172        self.assertEqual(datetime_cookie['expires'], 'Sat, 01-Jan-2028 04:05:06 GMT')
173
174    def test_max_age_expiration(self):
175        "Cookie will expire if max_age is provided"
176        response = HttpResponse()
177        response.set_cookie('max_age', max_age=10)
178        max_age_cookie = response.cookies['max_age']
179        self.assertEqual(max_age_cookie['max-age'], 10)
180        self.assertEqual(max_age_cookie['expires'], cookie_date(time.time()+10))
181
182    def test_httponly_cookie(self):
183        response = HttpResponse()
184        response.set_cookie('example', httponly=True)
185        example_cookie = response.cookies['example']
186        # A compat cookie may be in use -- check that it has worked
187        # both as an output string, and using the cookie attributes
188        self.assertTrue('; httponly' in str(example_cookie))
189        self.assertTrue(example_cookie['httponly'])
190
191    def test_limited_stream(self):
192        # Read all of a limited stream
193        stream = LimitedStream(StringIO('test'), 2)
194        self.assertEqual(stream.read(), 'te')
195        # Reading again returns nothing.
196        self.assertEqual(stream.read(), '')
197
198        # Read a number of characters greater than the stream has to offer
199        stream = LimitedStream(StringIO('test'), 2)
200        self.assertEqual(stream.read(5), 'te')
201        # Reading again returns nothing.
202        self.assertEqual(stream.readline(5), '')
203
204        # Read sequentially from a stream
205        stream = LimitedStream(StringIO('12345678'), 8)
206        self.assertEqual(stream.read(5), '12345')
207        self.assertEqual(stream.read(5), '678')
208        # Reading again returns nothing.
209        self.assertEqual(stream.readline(5), '')
210
211        # Read lines from a stream
212        stream = LimitedStream(StringIO('1234\n5678\nabcd\nefgh\nijkl'), 24)
213        # Read a full line, unconditionally
214        self.assertEqual(stream.readline(), '1234\n')
215        # Read a number of characters less than a line
216        self.assertEqual(stream.readline(2), '56')
217        # Read the rest of the partial line
218        self.assertEqual(stream.readline(), '78\n')
219        # Read a full line, with a character limit greater than the line length
220        self.assertEqual(stream.readline(6), 'abcd\n')
221        # Read the next line, deliberately terminated at the line end
222        self.assertEqual(stream.readline(4), 'efgh')
223        # Read the next line... just the line end
224        self.assertEqual(stream.readline(), '\n')
225        # Read everything else.
226        self.assertEqual(stream.readline(), 'ijkl')
227
228        # Regression for #15018
229        # If a stream contains a newline, but the provided length
230        # is less than the number of provided characters, the newline
231        # doesn't reset the available character count
232        stream = LimitedStream(StringIO('1234\nabcdef'), 9)
233        self.assertEqual(stream.readline(10), '1234\n')
234        self.assertEqual(stream.readline(3), 'abc')
235        # Now expire the available characters
236        self.assertEqual(stream.readline(3), 'd')
237        # Reading again returns nothing.
238        self.assertEqual(stream.readline(2), '')
239
240        # Same test, but with read, not readline.
241        stream = LimitedStream(StringIO('1234\nabcdef'), 9)
242        self.assertEqual(stream.read(6), '1234\na')
243        self.assertEqual(stream.read(2), 'bc')
244        self.assertEqual(stream.read(2), 'd')
245        self.assertEqual(stream.read(2), '')
246        self.assertEqual(stream.read(), '')
247
248    def test_stream(self):
249        request = WSGIRequest({'REQUEST_METHOD': 'POST', 'wsgi.input': StringIO('name=value')})
250        self.assertEqual(request.read(), 'name=value')
251
252    def test_read_after_value(self):
253        """
254        Reading from request is allowed after accessing request contents as
255        POST or raw_post_data.
256        """
257        request = WSGIRequest({'REQUEST_METHOD': 'POST', 'wsgi.input': StringIO('name=value')})
258        self.assertEqual(request.POST, {u'name': [u'value']})
259        self.assertEqual(request.raw_post_data, 'name=value')
260        self.assertEqual(request.read(), 'name=value')
261
262    def test_value_after_read(self):
263        """
264        Construction of POST or raw_post_data is not allowed after reading
265        from request.
266        """
267        request = WSGIRequest({'REQUEST_METHOD': 'POST', 'wsgi.input': StringIO('name=value')})
268        self.assertEqual(request.read(2), 'na')
269        self.assertRaises(Exception, lambda: request.raw_post_data)
270        self.assertEqual(request.POST, {})
271
272    def test_raw_post_data_after_POST_multipart(self):
273        """
274        Reading raw_post_data after parsing multipart is not allowed
275        """
276        # Because multipart is used for large amounts fo data i.e. file uploads,
277        # we don't want the data held in memory twice, and we don't want to
278        # silence the error by setting raw_post_data = '' either.
279        payload = "\r\n".join([
280                '--boundary',
281                'Content-Disposition: form-data; name="name"',
282                '',
283                'value',
284                '--boundary--'
285                ''])
286        request = WSGIRequest({'REQUEST_METHOD': 'POST',
287                               'CONTENT_TYPE': 'multipart/form-data; boundary=boundary',
288                               'CONTENT_LENGTH': len(payload),
289                               'wsgi.input': StringIO(payload)})
290        self.assertEqual(request.POST, {u'name': [u'value']})
291        self.assertRaises(Exception, lambda: request.raw_post_data)
292
293    def test_POST_multipart_with_content_length_zero(self):
294        """
295        Multipart POST requests with Content-Length >= 0 are valid and need to be handled.
296        """
297        # According to:
298        # http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.13
299        # Every request.POST with Content-Length >= 0 is a valid request,
300        # this test ensures that we handle Content-Length == 0.
301        payload = "\r\n".join([
302                '--boundary',
303                'Content-Disposition: form-data; name="name"',
304                '',
305                'value',
306                '--boundary--'
307                ''])
308        request = WSGIRequest({'REQUEST_METHOD': 'POST',
309                               'CONTENT_TYPE': 'multipart/form-data; boundary=boundary',
310                               'CONTENT_LENGTH': 0,
311                               'wsgi.input': StringIO(payload)})
312        self.assertEqual(request.POST, {})
313
314    def test_read_by_lines(self):
315        request = WSGIRequest({'REQUEST_METHOD': 'POST', 'wsgi.input': StringIO('name=value')})
316        self.assertEqual(list(request), ['name=value'])
317
318    def test_POST_after_raw_post_data_read(self):
319        """
320        POST should be populated even if raw_post_data is read first
321        """
322        request = WSGIRequest({'REQUEST_METHOD': 'POST', 'wsgi.input': StringIO('name=value')})
323        raw_data = request.raw_post_data
324        self.assertEqual(request.POST, {u'name': [u'value']})
325
326    def test_POST_after_raw_post_data_read_and_stream_read(self):
327        """
328        POST should be populated even if raw_post_data is read first, and then
329        the stream is read second.
330        """
331        request = WSGIRequest({'REQUEST_METHOD': 'POST', 'wsgi.input': StringIO('name=value')})
332        raw_data = request.raw_post_data
333        self.assertEqual(request.read(1), u'n')
334        self.assertEqual(request.POST, {u'name': [u'value']})
335
336    def test_POST_after_raw_post_data_read_and_stream_read_multipart(self):
337        """
338        POST should be populated even if raw_post_data is read first, and then
339        the stream is read second. Using multipart/form-data instead of urlencoded.
340        """
341        payload = "\r\n".join([
342                '--boundary',
343                'Content-Disposition: form-data; name="name"',
344                '',
345                'value',
346                '--boundary--'
347                ''])
348        request = WSGIRequest({'REQUEST_METHOD': 'POST',
349                               'CONTENT_TYPE': 'multipart/form-data; boundary=boundary',
350                               'CONTENT_LENGTH': len(payload),
351                               'wsgi.input': StringIO(payload)})
352        raw_data = request.raw_post_data
353        # Consume enough data to mess up the parsing:
354        self.assertEqual(request.read(13), u'--boundary\r\nC')
355        self.assertEqual(request.POST, {u'name': [u'value']})