Home | History | Annotate | Download | only in tests
      1 # -*- coding: utf-8 -*-
      2 import StringIO
      3 
      4 import webapp2
      5 
      6 import test_base
      7 
      8 
      9 def _norm_req(s):
     10     return '\r\n'.join(s.strip().replace('\r','').split('\n'))
     11 
     12 _test_req = """
     13 POST /webob/ HTTP/1.0
     14 Accept: */*
     15 Cache-Control: max-age=0
     16 Content-Type: multipart/form-data; boundary=----------------------------deb95b63e42a
     17 Host: pythonpaste.org
     18 User-Agent: UserAgent/1.0 (identifier-version) library/7.0 otherlibrary/0.8
     19 
     20 ------------------------------deb95b63e42a
     21 Content-Disposition: form-data; name="foo"
     22 
     23 foo
     24 ------------------------------deb95b63e42a
     25 Content-Disposition: form-data; name="bar"; filename="bar.txt"
     26 Content-type: application/octet-stream
     27 
     28 these are the contents of the file 'bar.txt'
     29 
     30 ------------------------------deb95b63e42a--
     31 """
     32 
     33 _test_req2 = """
     34 POST / HTTP/1.0
     35 Content-Length: 0
     36 
     37 """
     38 
     39 _test_req = _norm_req(_test_req)
     40 _test_req2 = _norm_req(_test_req2) + '\r\n'
     41 
     42 
     43 class TestRequest(test_base.BaseTestCase):
     44     def test_charset(self):
     45         req = webapp2.Request.blank('/', environ={
     46             'CONTENT_TYPE': 'text/html; charset=ISO-8859-4',
     47         })
     48         self.assertEqual(req.content_type, 'text/html')
     49         self.assertEqual(req.charset, 'iso-8859-4')
     50 
     51         req = webapp2.Request.blank('/', environ={
     52             'CONTENT_TYPE': 'application/json; charset="ISO-8859-1"',
     53         })
     54         self.assertEqual(req.content_type, 'application/json')
     55         self.assertEqual(req.charset, 'iso-8859-1')
     56 
     57         req = webapp2.Request.blank('/', environ={
     58             'CONTENT_TYPE': 'application/json',
     59         })
     60         self.assertEqual(req.content_type, 'application/json')
     61         self.assertEqual(req.charset.lower(), 'utf-8')
     62 
     63         match = webapp2._charset_re.search('text/html')
     64         if match:
     65             charset = match.group(1).lower().strip().strip('"').strip()
     66         else:
     67             charset = 'utf-8'
     68         self.assertEqual(charset, 'utf-8')
     69 
     70         match = webapp2._charset_re.search('text/html; charset=ISO-8859-4')
     71         if match:
     72             charset = match.group(1).lower().strip().strip('"').strip()
     73         else:
     74             charset = 'utf-8'
     75         self.assertEqual(charset, 'iso-8859-4')
     76 
     77         match = webapp2._charset_re.search('text/html; charset="ISO-8859-4"')
     78         if match:
     79             charset = match.group(1).lower().strip().strip('"').strip()
     80         else:
     81             charset = 'utf-8'
     82         self.assertEqual(charset, 'iso-8859-4')
     83 
     84         match = webapp2._charset_re.search('text/html; charset=  "  ISO-8859-4  "  ')
     85         if match:
     86             charset = match.group(1).lower().strip().strip('"').strip()
     87         else:
     88             charset = 'utf-8'
     89         self.assertEqual(charset, 'iso-8859-4')
     90 
     91     def test_unicode(self):
     92         req = webapp2.Request.blank('/?1=2', POST='3=4')
     93 
     94         res = req.GET.get('1')
     95         self.assertEqual(res, '2')
     96         self.assertTrue(isinstance(res, unicode))
     97 
     98         res = req.str_GET.get('1')
     99         self.assertEqual(res, '2')
    100         self.assertTrue(isinstance(res, str))
    101 
    102         res = req.POST.get('3')
    103         self.assertEqual(res, '4')
    104         self.assertTrue(isinstance(res, unicode))
    105 
    106         res = req.str_POST.get('3')
    107         self.assertEqual(res, '4')
    108         self.assertTrue(isinstance(res, str))
    109 
    110     def test_cookie_unicode(self):
    111         import urllib
    112         import base64
    113 
    114         # With base64 ---------------------------------------------------------
    115 
    116         value = base64.b64encode(u''.encode('utf-8'))
    117         rsp = webapp2.Response()
    118         rsp.set_cookie('foo', value)
    119 
    120         cookie = rsp.headers.get('Set-Cookie')
    121         req = webapp2.Request.blank('/', headers=[('Cookie', cookie)])
    122 
    123         self.assertEqual(req.cookies.get('foo'), value)
    124         self.assertEqual(base64.b64decode(req.cookies.get('foo')).decode('utf-8'), u'')
    125 
    126         # Without quote -------------------------------------------------------
    127 
    128         # Most recent WebOb versions take care of quoting.
    129         # (not the version available on App Engine though)
    130 
    131         value = u'f=br; fo, br, bz=dng;'
    132         rsp = webapp2.Response()
    133         rsp.set_cookie('foo', value)
    134 
    135         cookie = rsp.headers.get('Set-Cookie')
    136         req = webapp2.Request.blank('/', headers=[('Cookie', cookie)])
    137 
    138         self.assertEqual(req.cookies.get('foo'), value)
    139 
    140         # With quote, hard way ------------------------------------------------
    141 
    142         # Here is our test value.
    143         x = u'f'
    144         # We must store cookies quoted. To quote unicode, we need to encode it.
    145         y = urllib.quote(x.encode('utf8'))
    146         # The encoded, quoted string looks ugly.
    147         self.assertEqual(y, 'f%C3%B6%C3%B6')
    148         # But it is easy to get it back to our initial value.
    149         z = urllib.unquote(y).decode('utf8')
    150         # And it is indeed the same value.
    151         self.assertEqual(z, x)
    152 
    153         # Set a cookie using the encoded/quoted value.
    154         rsp = webapp2.Response()
    155         rsp.set_cookie('foo', y)
    156         cookie = rsp.headers.get('Set-Cookie')
    157         self.assertEqual(cookie, 'foo=f%C3%B6%C3%B6; Path=/')
    158 
    159         # Get the cookie back.
    160         req = webapp2.Request.blank('/', headers=[('Cookie', cookie)])
    161         self.assertEqual(req.cookies.get('foo'), y)
    162         # Here is our original value, again. Problem: the value is decoded
    163         # before we had a chance to unquote it.
    164         w = urllib.unquote(req.cookies.get('foo').encode('utf8')).decode('utf8')
    165         # And it is indeed the same value.
    166         self.assertEqual(w, x)
    167 
    168         # With quote, easy way ------------------------------------------------
    169 
    170         value = u'f=br; fo, br, bz=dng;'
    171         quoted_value = urllib.quote(value.encode('utf8'))
    172         rsp = webapp2.Response()
    173         rsp.set_cookie('foo', quoted_value)
    174 
    175         cookie = rsp.headers.get('Set-Cookie')
    176         req = webapp2.Request.blank('/', headers=[('Cookie', cookie)])
    177 
    178         cookie_value = req.str_cookies.get('foo')
    179         unquoted_cookie_value = urllib.unquote(cookie_value).decode('utf-8')
    180         self.assertEqual(cookie_value, quoted_value)
    181         self.assertEqual(unquoted_cookie_value, value)
    182 
    183     def test_get(self):
    184         req = webapp2.Request.blank('/?1=2&1=3&3=4', POST='5=6&7=8')
    185 
    186         res = req.get('1')
    187         self.assertEqual(res, '2')
    188 
    189         res = req.get('1', allow_multiple=True)
    190         self.assertEqual(res, ['2', '3'])
    191 
    192         res = req.get('8')
    193         self.assertEqual(res, '')
    194 
    195         res = req.get('8', allow_multiple=True)
    196         self.assertEqual(res, [])
    197 
    198         res = req.get('8', default_value='9')
    199         self.assertEqual(res, '9')
    200 
    201     def test_get_with_POST(self):
    202         req = webapp2.Request.blank('/?1=2&1=3&3=4', POST={5: 6, 7: 8},
    203                                     unicode_errors='ignore')
    204 
    205         res = req.get('1')
    206         self.assertEqual(res, '2')
    207 
    208         res = req.get('1', allow_multiple=True)
    209         self.assertEqual(res, ['2', '3'])
    210 
    211         res = req.get('8')
    212         self.assertEqual(res, '')
    213 
    214         res = req.get('8', allow_multiple=True)
    215         self.assertEqual(res, [])
    216 
    217         res = req.get('8', default_value='9')
    218         self.assertEqual(res, '9')
    219 
    220     def test_arguments(self):
    221         req = webapp2.Request.blank('/?1=2&3=4', POST='5=6&7=8')
    222 
    223         res = req.arguments()
    224         self.assertEqual(res, ['1', '3', '5', '7'])
    225 
    226     def test_get_range(self):
    227         req = webapp2.Request.blank('/')
    228         res = req.get_range('1', min_value=None, max_value=None, default=None)
    229         self.assertEqual(res, None)
    230 
    231         req = webapp2.Request.blank('/?1=2')
    232         res = req.get_range('1', min_value=None, max_value=None, default=0)
    233         self.assertEqual(res, 2)
    234 
    235         req = webapp2.Request.blank('/?1=foo')
    236         res = req.get_range('1', min_value=1, max_value=99, default=100)
    237         self.assertEqual(res, 99)
    238 
    239     def test_issue_3426(self):
    240         """When the content-type is 'application/x-www-form-urlencoded' and
    241         POST data is empty the content-type is dropped by Google appengine.
    242         """
    243         req = webapp2.Request.blank('/', environ={
    244             'REQUEST_METHOD': 'GET',
    245             'CONTENT_TYPE': 'application/x-www-form-urlencoded',
    246         })
    247         self.assertEqual(req.method, 'GET')
    248         self.assertEqual(req.content_type, 'application/x-www-form-urlencoded')
    249 
    250     # XXX: These tests fail when request charset is set to utf-8 by default.
    251     # Otherwise they pass.
    252     '''
    253     def test_get_with_FieldStorage(self):
    254         if not test_base.check_webob_version(1.0):
    255             return
    256         # A valid request without a Content-Length header should still read
    257         # the full body.
    258         # Also test parity between as_string and from_string / from_file.
    259         import cgi
    260         req = webapp2.Request.from_string(_test_req)
    261         self.assertTrue(isinstance(req, webapp2.Request))
    262         self.assertTrue(not repr(req).endswith('(invalid WSGI environ)>'))
    263         self.assertTrue('\n' not in req.http_version or '\r' in req.http_version)
    264         self.assertTrue(',' not in req.host)
    265         self.assertTrue(req.content_length is not None)
    266         self.assertEqual(req.content_length, 337)
    267         self.assertTrue('foo' in req.body)
    268         bar_contents = "these are the contents of the file 'bar.txt'\r\n"
    269         self.assertTrue(bar_contents in req.body)
    270         self.assertEqual(req.params['foo'], 'foo')
    271         bar = req.params['bar']
    272         self.assertTrue(isinstance(bar, cgi.FieldStorage))
    273         self.assertEqual(bar.type, 'application/octet-stream')
    274         bar.file.seek(0)
    275         self.assertEqual(bar.file.read(), bar_contents)
    276 
    277         bar = req.get_all('bar')
    278         self.assertEqual(bar[0], bar_contents)
    279 
    280         # out should equal contents, except for the Content-Length header,
    281         # so insert that.
    282         _test_req_copy = _test_req.replace('Content-Type',
    283                             'Content-Length: 337\r\nContent-Type')
    284         self.assertEqual(str(req), _test_req_copy)
    285 
    286         req2 = webapp2.Request.from_string(_test_req2)
    287         self.assertTrue('host' not in req2.headers)
    288         self.assertEqual(str(req2), _test_req2.rstrip())
    289         self.assertRaises(ValueError,
    290                           webapp2.Request.from_string, _test_req2 + 'xx')
    291 
    292     def test_issue_5118(self):
    293         """Unable to read POST variables ONCE self.request.body is read."""
    294         if not test_base.check_webob_version(1.0):
    295             return
    296         import cgi
    297         req = webapp2.Request.from_string(_test_req)
    298         fieldStorage = req.POST.get('bar')
    299         self.assertTrue(isinstance(fieldStorage, cgi.FieldStorage))
    300         self.assertEqual(fieldStorage.type, 'application/octet-stream')
    301         # Double read.
    302         fieldStorage = req.POST.get('bar')
    303         self.assertTrue(isinstance(fieldStorage, cgi.FieldStorage))
    304         self.assertEqual(fieldStorage.type, 'application/octet-stream')
    305         # Now read the body.
    306         x = req.body
    307         fieldStorage = req.POST.get('bar')
    308         self.assertTrue(isinstance(fieldStorage, cgi.FieldStorage))
    309         self.assertEqual(fieldStorage.type, 'application/octet-stream')
    310     '''
    311 
    312 if __name__ == '__main__':
    313     test_base.main()
    314