Home | History | Annotate | Download | only in tests
      1 # -*- coding: utf-8 -*-
      2 """
      3 Tests for webapp2 webapp2.RequestHandler
      4 """
      5 import os
      6 import StringIO
      7 import sys
      8 import urllib
      9 
     10 import webapp2
     11 
     12 import test_base
     13 
     14 
     15 class BareHandler(object):
     16     def __init__(self, request, response):
     17         self.response = response
     18         response.write('I am not a RequestHandler but I work.')
     19 
     20     def dispatch(self):
     21         return self.response
     22 
     23 
     24 class HomeHandler(webapp2.RequestHandler):
     25     def get(self, **kwargs):
     26         self.response.out.write('home sweet home')
     27 
     28     def post(self, **kwargs):
     29         self.response.out.write('home sweet home - POST')
     30 
     31 
     32 class MethodsHandler(HomeHandler):
     33     def put(self, **kwargs):
     34         self.response.out.write('home sweet home - PUT')
     35 
     36     def delete(self, **kwargs):
     37         self.response.out.write('home sweet home - DELETE')
     38 
     39     def head(self, **kwargs):
     40         self.response.out.write('home sweet home - HEAD')
     41 
     42     def trace(self, **kwargs):
     43         self.response.out.write('home sweet home - TRACE')
     44 
     45     def options(self, **kwargs):
     46         self.response.out.write('home sweet home - OPTIONS')
     47 
     48 
     49 class RedirectToHandler(webapp2.RequestHandler):
     50     def get(self, **kwargs):
     51         return self.redirect_to('route-test', _fragment='my-anchor', year='2010',
     52                                 month='07', name='test', foo='bar')
     53 
     54 
     55 class RedirectAbortHandler(webapp2.RequestHandler):
     56     def get(self, **kwargs):
     57         self.redirect('/somewhere', abort=True)
     58 
     59 
     60 class BrokenHandler(webapp2.RequestHandler):
     61     def get(self, **kwargs):
     62         raise ValueError('booo!')
     63 
     64 
     65 class BrokenButFixedHandler(BrokenHandler):
     66     def handle_exception(self, exception, debug_mode):
     67         # Let's fix it.
     68         self.response.set_status(200)
     69         self.response.out.write('that was close!')
     70 
     71 
     72 def handle_404(request, response, exception):
     73     response.out.write('404 custom handler')
     74     response.set_status(404)
     75 
     76 
     77 def handle_405(request, response, exception):
     78     response.out.write('405 custom handler')
     79     response.set_status(405, 'Custom Error Message')
     80     response.headers['Allow'] = 'GET'
     81 
     82 
     83 def handle_500(request, response, exception):
     84     response.out.write('500 custom handler')
     85     response.set_status(500)
     86 
     87 
     88 class PositionalHandler(webapp2.RequestHandler):
     89     def get(self, month, day, slug=None):
     90         self.response.out.write('%s:%s:%s' % (month, day, slug))
     91 
     92 
     93 class HandlerWithError(webapp2.RequestHandler):
     94     def get(self, **kwargs):
     95         self.response.out.write('bla bla bla bla bla bla')
     96         self.error(403)
     97 
     98 
     99 class InitializeHandler(webapp2.RequestHandler):
    100     def __init__(self):
    101         pass
    102 
    103     def get(self):
    104         self.response.out.write('Request method: %s' % self.request.method)
    105 
    106 
    107 class WebDavHandler(webapp2.RequestHandler):
    108     def version_control(self):
    109         self.response.out.write('Method: VERSION-CONTROL')
    110 
    111     def unlock(self):
    112         self.response.out.write('Method: UNLOCK')
    113 
    114     def propfind(self):
    115         self.response.out.write('Method: PROPFIND')
    116 
    117 
    118 class AuthorizationHandler(webapp2.RequestHandler):
    119     def get(self):
    120         self.response.out.write('nothing here')
    121 
    122 class HandlerWithEscapedArg(webapp2.RequestHandler):
    123     def get(self, name):
    124         self.response.out.write(urllib.unquote_plus(name))
    125 
    126 def get_redirect_url(handler, **kwargs):
    127     return handler.uri_for('methods')
    128 
    129 
    130 app = webapp2.WSGIApplication([
    131     ('/bare', BareHandler),
    132     webapp2.Route('/', HomeHandler, name='home'),
    133     webapp2.Route('/methods', MethodsHandler, name='methods'),
    134     webapp2.Route('/broken', BrokenHandler),
    135     webapp2.Route('/broken-but-fixed', BrokenButFixedHandler),
    136     webapp2.Route('/<year:\d{4}>/<month:\d{1,2}>/<name>', None, name='route-test'),
    137     webapp2.Route('/<:\d\d>/<:\d{2}>/<:\w+>', PositionalHandler, name='positional'),
    138     webapp2.Route('/redirect-me', webapp2.RedirectHandler, defaults={'_uri': '/broken'}),
    139     webapp2.Route('/redirect-me2', webapp2.RedirectHandler, defaults={'_uri': get_redirect_url}),
    140     webapp2.Route('/redirect-me3', webapp2.RedirectHandler, defaults={'_uri': '/broken', '_permanent': False}),
    141     webapp2.Route('/redirect-me4', webapp2.RedirectHandler, defaults={'_uri': get_redirect_url, '_permanent': False}),
    142     webapp2.Route('/redirect-me5', RedirectToHandler),
    143     webapp2.Route('/redirect-me6', RedirectAbortHandler),
    144     webapp2.Route('/lazy', 'resources.handlers.LazyHandler'),
    145     webapp2.Route('/error', HandlerWithError),
    146     webapp2.Route('/initialize', InitializeHandler),
    147     webapp2.Route('/webdav', WebDavHandler),
    148     webapp2.Route('/authorization', AuthorizationHandler),
    149     webapp2.Route('/escape/<name:.*>', HandlerWithEscapedArg, 'escape'),
    150 ], debug=False)
    151 
    152 DEFAULT_RESPONSE = """Status: 404 Not Found
    153 content-type: text/html; charset=utf8
    154 Content-Length: 52
    155 
    156 404 Not Found
    157 
    158 The resource could not be found.
    159 
    160    """
    161 
    162 class TestHandler(test_base.BaseTestCase):
    163     def tearDown(self):
    164         super(TestHandler, self).tearDown()
    165         app.error_handlers = {}
    166 
    167     def test_200(self):
    168         rsp = app.get_response('/')
    169         self.assertEqual(rsp.status_int, 200)
    170         self.assertEqual(rsp.body, 'home sweet home')
    171 
    172     def test_404(self):
    173         req = webapp2.Request.blank('/nowhere')
    174         rsp = req.get_response(app)
    175         self.assertEqual(rsp.status_int, 404)
    176 
    177     def test_405(self):
    178         req = webapp2.Request.blank('/')
    179         req.method = 'PUT'
    180         rsp = req.get_response(app)
    181         self.assertEqual(rsp.status_int, 405)
    182         self.assertEqual(rsp.headers.get('Allow'), 'GET, POST')
    183 
    184     def test_500(self):
    185         req = webapp2.Request.blank('/broken')
    186         rsp = req.get_response(app)
    187         self.assertEqual(rsp.status_int, 500)
    188 
    189     def test_500_but_fixed(self):
    190         req = webapp2.Request.blank('/broken-but-fixed')
    191         rsp = req.get_response(app)
    192         self.assertEqual(rsp.status_int, 200)
    193         self.assertEqual(rsp.body, 'that was close!')
    194 
    195     def test_501(self):
    196         # 501 Not Implemented
    197         req = webapp2.Request.blank('/methods')
    198         req.method = 'FOOBAR'
    199         rsp = req.get_response(app)
    200         self.assertEqual(rsp.status_int, 501)
    201 
    202     def test_lazy_handler(self):
    203         req = webapp2.Request.blank('/lazy')
    204         rsp = req.get_response(app)
    205         self.assertEqual(rsp.status_int, 200)
    206         self.assertEqual(rsp.body, 'I am a laaazy view.')
    207 
    208     def test_handler_with_error(self):
    209         req = webapp2.Request.blank('/error')
    210         rsp = req.get_response(app)
    211         self.assertEqual(rsp.status_int, 403)
    212         self.assertEqual(rsp.body, '')
    213 
    214     def test_debug_mode(self):
    215         app = webapp2.WSGIApplication([
    216             webapp2.Route('/broken', BrokenHandler),
    217         ], debug=True)
    218         req = webapp2.Request.blank('/broken')
    219         rsp = req.get_response(app)
    220         self.assertEqual(rsp.status_int, 500)
    221 
    222     def test_custom_error_handlers(self):
    223         app.error_handlers = {
    224             404: handle_404,
    225             405: handle_405,
    226             500: handle_500,
    227         }
    228         req = webapp2.Request.blank('/nowhere')
    229         rsp = req.get_response(app)
    230         self.assertEqual(rsp.status_int, 404)
    231         self.assertEqual(rsp.body, '404 custom handler')
    232 
    233         req = webapp2.Request.blank('/')
    234         req.method = 'PUT'
    235         rsp = req.get_response(app)
    236         self.assertEqual(rsp.status, '405 Custom Error Message')
    237         self.assertEqual(rsp.body, '405 custom handler')
    238         self.assertEqual(rsp.headers.get('Allow'), 'GET')
    239 
    240         req = webapp2.Request.blank('/broken')
    241         rsp = req.get_response(app)
    242         self.assertEqual(rsp.status_int, 500)
    243         self.assertEqual(rsp.body, '500 custom handler')
    244 
    245     def test_methods(self):
    246         app.debug = True
    247         req = webapp2.Request.blank('/methods')
    248         rsp = req.get_response(app)
    249         self.assertEqual(rsp.status_int, 200)
    250         self.assertEqual(rsp.body, 'home sweet home')
    251 
    252         req = webapp2.Request.blank('/methods')
    253         req.method = 'POST'
    254         rsp = req.get_response(app)
    255         self.assertEqual(rsp.status_int, 200)
    256         self.assertEqual(rsp.body, 'home sweet home - POST')
    257 
    258         req = webapp2.Request.blank('/methods')
    259         req.method = 'PUT'
    260         rsp = req.get_response(app)
    261         self.assertEqual(rsp.status_int, 200)
    262         self.assertEqual(rsp.body, 'home sweet home - PUT')
    263 
    264         req = webapp2.Request.blank('/methods')
    265         req.method = 'DELETE'
    266         rsp = req.get_response(app)
    267         self.assertEqual(rsp.status_int, 200)
    268         self.assertEqual(rsp.body, 'home sweet home - DELETE')
    269 
    270         req = webapp2.Request.blank('/methods')
    271         req.method = 'HEAD'
    272         rsp = req.get_response(app)
    273         self.assertEqual(rsp.status_int, 200)
    274         self.assertEqual(rsp.body, '')
    275 
    276         req = webapp2.Request.blank('/methods')
    277         req.method = 'OPTIONS'
    278         rsp = req.get_response(app)
    279         self.assertEqual(rsp.status_int, 200)
    280         self.assertEqual(rsp.body, 'home sweet home - OPTIONS')
    281 
    282         req = webapp2.Request.blank('/methods')
    283         req.method = 'TRACE'
    284         rsp = req.get_response(app)
    285         self.assertEqual(rsp.status_int, 200)
    286         self.assertEqual(rsp.body, 'home sweet home - TRACE')
    287         app.debug = False
    288 
    289     def test_positional(self):
    290         req = webapp2.Request.blank('/07/31/test')
    291         rsp = req.get_response(app)
    292         self.assertEqual(rsp.status_int, 200)
    293         self.assertEqual(rsp.body, '07:31:test')
    294 
    295         req = webapp2.Request.blank('/10/18/wooohooo')
    296         rsp = req.get_response(app)
    297         self.assertEqual(rsp.status_int, 200)
    298         self.assertEqual(rsp.body, '10:18:wooohooo')
    299 
    300     def test_redirect(self):
    301         req = webapp2.Request.blank('/redirect-me')
    302         rsp = req.get_response(app)
    303         self.assertEqual(rsp.status_int, 301)
    304         self.assertEqual(rsp.body, '')
    305         self.assertEqual(rsp.headers['Location'], 'http://localhost/broken')
    306 
    307     def test_redirect_with_callable(self):
    308         req = webapp2.Request.blank('/redirect-me2')
    309         rsp = req.get_response(app)
    310         self.assertEqual(rsp.status_int, 301)
    311         self.assertEqual(rsp.body, '')
    312         self.assertEqual(rsp.headers['Location'], 'http://localhost/methods')
    313 
    314     def test_redirect_not_permanent(self):
    315         req = webapp2.Request.blank('/redirect-me3')
    316         rsp = req.get_response(app)
    317         self.assertEqual(rsp.status_int, 302)
    318         self.assertEqual(rsp.body, '')
    319         self.assertEqual(rsp.headers['Location'], 'http://localhost/broken')
    320 
    321     def test_redirect_with_callable_not_permanent(self):
    322         req = webapp2.Request.blank('/redirect-me4')
    323         rsp = req.get_response(app)
    324         self.assertEqual(rsp.status_int, 302)
    325         self.assertEqual(rsp.body, '')
    326         self.assertEqual(rsp.headers['Location'], 'http://localhost/methods')
    327 
    328     def test_redirect_to(self):
    329         req = webapp2.Request.blank('/redirect-me5')
    330         rsp = req.get_response(app)
    331         self.assertEqual(rsp.status_int, 302)
    332         self.assertEqual(rsp.body, '')
    333         self.assertEqual(rsp.headers['Location'], 'http://localhost/2010/07/test?foo=bar#my-anchor')
    334 
    335     def test_redirect_abort(self):
    336         req = webapp2.Request.blank('/redirect-me6')
    337         rsp = req.get_response(app)
    338         self.assertEqual(rsp.status_int, 302)
    339         self.assertEqual(rsp.body, """302 Moved Temporarily
    340 
    341 The resource was found at http://localhost/somewhere; you should be redirected automatically.  """)
    342         self.assertEqual(rsp.headers['Location'], 'http://localhost/somewhere')
    343 
    344     def test_run(self):
    345         os.environ['REQUEST_METHOD'] = 'GET'
    346 
    347         app.run()
    348         #self.assertEqual(sys.stdout.read(), DEFAULT_RESPONSE)
    349 
    350     def test_run_bare(self):
    351         os.environ['REQUEST_METHOD'] = 'GET'
    352         app.run(bare=True)
    353 
    354         #self.assertEqual(sys.stdout.read(), DEFAULT_RESPONSE)
    355 
    356     def test_run_debug(self):
    357         debug = app.debug
    358         app.debug = True
    359         os.environ['REQUEST_METHOD'] = 'GET'
    360         os.environ['PATH_INFO'] = '/'
    361 
    362         res = app.run(bare=True)
    363         #self.assertEqual(sys.stdout.read(), DEFAULT_RESPONSE)
    364 
    365         app.debug = debug
    366 
    367     '''
    368     def test_get_valid_methods(self):
    369         req = webapp2.Request.blank('http://localhost:80/')
    370         req.app = app
    371         app.set_globals(app=app, request=req)
    372 
    373         handler = BrokenHandler(req, None)
    374         handler.app = app
    375         self.assertEqual(handler.get_valid_methods().sort(), ['GET'].sort())
    376 
    377         handler = HomeHandler(req, None)
    378         handler.app = app
    379         self.assertEqual(handler.get_valid_methods().sort(),
    380             ['GET', 'POST'].sort())
    381 
    382         handler = MethodsHandler(req, None)
    383         handler.app = app
    384         self.assertEqual(handler.get_valid_methods().sort(),
    385             ['GET', 'POST', 'HEAD', 'OPTIONS', 'PUT', 'DELETE', 'TRACE'].sort())
    386     '''
    387 
    388     def test_uri_for(self):
    389         class Handler(webapp2.RequestHandler):
    390             def get(self, *args, **kwargs):
    391                 pass
    392 
    393         req = webapp2.Request.blank('http://localhost:80/')
    394         req.route = webapp2.Route('')
    395         req.route_args = tuple()
    396         req.route_kwargs = {}
    397         req.app = app
    398         app.set_globals(app=app, request=req)
    399         handler = Handler(req, webapp2.Response())
    400         handler.app = app
    401 
    402         for func in (handler.uri_for,):
    403             self.assertEqual(func('home'), '/')
    404             self.assertEqual(func('home', foo='bar'), '/?foo=bar')
    405             self.assertEqual(func('home', _fragment='my-anchor', foo='bar'), '/?foo=bar#my-anchor')
    406             self.assertEqual(func('home', _fragment='my-anchor'), '/#my-anchor')
    407             self.assertEqual(func('home', _full=True), 'http://localhost:80/')
    408             self.assertEqual(func('home', _full=True, _fragment='my-anchor'), 'http://localhost:80/#my-anchor')
    409             self.assertEqual(func('home', _scheme='https'), 'https://localhost:80/')
    410             self.assertEqual(func('home', _scheme='https', _full=False), 'https://localhost:80/')
    411             self.assertEqual(func('home', _scheme='https', _fragment='my-anchor'), 'https://localhost:80/#my-anchor')
    412 
    413             self.assertEqual(func('methods'), '/methods')
    414             self.assertEqual(func('methods', foo='bar'), '/methods?foo=bar')
    415             self.assertEqual(func('methods', _fragment='my-anchor', foo='bar'), '/methods?foo=bar#my-anchor')
    416             self.assertEqual(func('methods', _fragment='my-anchor'), '/methods#my-anchor')
    417             self.assertEqual(func('methods', _full=True), 'http://localhost:80/methods')
    418             self.assertEqual(func('methods', _full=True, _fragment='my-anchor'), 'http://localhost:80/methods#my-anchor')
    419             self.assertEqual(func('methods', _scheme='https'), 'https://localhost:80/methods')
    420             self.assertEqual(func('methods', _scheme='https', _full=False), 'https://localhost:80/methods')
    421             self.assertEqual(func('methods', _scheme='https', _fragment='my-anchor'), 'https://localhost:80/methods#my-anchor')
    422 
    423             self.assertEqual(func('route-test', year='2010', month='0', name='test'), '/2010/0/test')
    424             self.assertEqual(func('route-test', year='2010', month='07', name='test'), '/2010/07/test')
    425             self.assertEqual(func('route-test', year='2010', month='07', name='test', foo='bar'), '/2010/07/test?foo=bar')
    426             self.assertEqual(func('route-test', _fragment='my-anchor', year='2010', month='07', name='test', foo='bar'), '/2010/07/test?foo=bar#my-anchor')
    427             self.assertEqual(func('route-test', _fragment='my-anchor', year='2010', month='07', name='test'), '/2010/07/test#my-anchor')
    428             self.assertEqual(func('route-test', _full=True, year='2010', month='07', name='test'), 'http://localhost:80/2010/07/test')
    429             self.assertEqual(func('route-test', _full=True, _fragment='my-anchor', year='2010', month='07', name='test'), 'http://localhost:80/2010/07/test#my-anchor')
    430             self.assertEqual(func('route-test', _scheme='https', year='2010', month='07', name='test'), 'https://localhost:80/2010/07/test')
    431             self.assertEqual(func('route-test', _scheme='https', _full=False, year='2010', month='07', name='test'), 'https://localhost:80/2010/07/test')
    432             self.assertEqual(func('route-test', _scheme='https', _fragment='my-anchor', year='2010', month='07', name='test'), 'https://localhost:80/2010/07/test#my-anchor')
    433 
    434     def test_extra_request_methods(self):
    435         allowed_methods_backup = app.allowed_methods
    436         webdav_methods = ('VERSION-CONTROL', 'UNLOCK', 'PROPFIND')
    437 
    438         for method in webdav_methods:
    439             # It is still not possible to use WebDav methods...
    440             req = webapp2.Request.blank('/webdav')
    441             req.method = method
    442             rsp = req.get_response(app)
    443             self.assertEqual(rsp.status_int, 501)
    444 
    445         # Let's extend ALLOWED_METHODS with some WebDav methods.
    446         app.allowed_methods = tuple(app.allowed_methods) + webdav_methods
    447 
    448         #self.assertEqual(sorted(webapp2.get_valid_methods(WebDavHandler)), sorted(list(webdav_methods)))
    449 
    450         # Now we can use WebDav methods...
    451         for method in webdav_methods:
    452             req = webapp2.Request.blank('/webdav')
    453             req.method = method
    454             rsp = req.get_response(app)
    455             self.assertEqual(rsp.status_int, 200)
    456             self.assertEqual(rsp.body, 'Method: %s' % method)
    457 
    458         # Restore initial values.
    459         app.allowed_methods = allowed_methods_backup
    460         self.assertEqual(len(app.allowed_methods), 7)
    461 
    462     def test_escaping(self):
    463         def get_req(uri):
    464             req = webapp2.Request.blank(uri)
    465             app.set_globals(app=app, request=req)
    466             handler = webapp2.RequestHandler(req, None)
    467             handler.app = req.app = app
    468             return req, handler
    469 
    470         req, handler = get_req('http://localhost:80/')
    471         uri = webapp2.uri_for('escape', name='with space')
    472         req, handler = get_req(uri)
    473         rsp = req.get_response(app)
    474         self.assertEqual(rsp.status_int, 200)
    475         self.assertEqual(rsp.body, 'with space')
    476 
    477         req, handler = get_req('http://localhost:80/')
    478         uri = webapp2.uri_for('escape', name='with+plus')
    479         req, handler = get_req(uri)
    480         rsp = req.get_response(app)
    481         self.assertEqual(rsp.status_int, 200)
    482         self.assertEqual(rsp.body, 'with plus')
    483 
    484         req, handler = get_req('http://localhost:80/')
    485         uri = webapp2.uri_for('escape', name='with/slash')
    486         req, handler = get_req(uri)
    487         rsp = req.get_response(app)
    488         self.assertEqual(rsp.status_int, 200)
    489         self.assertEqual(rsp.body, 'with/slash')
    490 
    491     def test_handle_exception_with_error(self):
    492         class HomeHandler(webapp2.RequestHandler):
    493             def get(self, **kwargs):
    494                 raise TypeError()
    495 
    496         def handle_exception(request, response, exception):
    497             raise ValueError()
    498 
    499         app = webapp2.WSGIApplication([
    500             webapp2.Route('/', HomeHandler, name='home'),
    501         ], debug=False)
    502         app.error_handlers[500] = handle_exception
    503 
    504         req = webapp2.Request.blank('/')
    505         rsp = req.get_response(app)
    506         self.assertEqual(rsp.status_int, 500)
    507 
    508     def test_handle_exception_with_error_debug(self):
    509         class HomeHandler(webapp2.RequestHandler):
    510             def get(self, **kwargs):
    511                 raise TypeError()
    512 
    513         def handle_exception(request, response, exception):
    514             raise ValueError()
    515 
    516         app = webapp2.WSGIApplication([
    517             webapp2.Route('/', HomeHandler, name='home'),
    518         ], debug=True)
    519         app.error_handlers[500] = handle_exception
    520 
    521         req = webapp2.Request.blank('/')
    522         rsp = req.get_response(app)
    523         self.assertEqual(rsp.status_int, 500)
    524 
    525     def test_function_handler(self):
    526         def my_view(request, *args, **kwargs):
    527             return webapp2.Response('Hello, function world!')
    528 
    529         def other_view(request, *args, **kwargs):
    530             return webapp2.Response('Hello again, function world!')
    531 
    532         '''
    533         def one_more_view(request, response):
    534             self.assertEqual(request.route_args, ())
    535             self.assertEqual(request.route_kwargs, {'foo': 'bar'})
    536             response.write('Hello you too, deprecated arguments world!')
    537         '''
    538         def one_more_view(request, *args, **kwargs):
    539             self.assertEqual(args, ())
    540             self.assertEqual(kwargs, {'foo': 'bar'})
    541             return webapp2.Response('Hello you too!')
    542 
    543         app = webapp2.WSGIApplication([
    544             webapp2.Route('/', my_view),
    545             webapp2.Route('/other', other_view),
    546             webapp2.Route('/one-more/<foo>', one_more_view),
    547             #webapp2.Route('/one-more/<foo>', one_more_view),
    548         ])
    549 
    550         req = webapp2.Request.blank('/')
    551         rsp = req.get_response(app)
    552         self.assertEqual(rsp.status_int, 200)
    553         self.assertEqual(rsp.body, 'Hello, function world!')
    554 
    555         # Twice to test factory.
    556         req = webapp2.Request.blank('/')
    557         rsp = req.get_response(app)
    558         self.assertEqual(rsp.status_int, 200)
    559         self.assertEqual(rsp.body, 'Hello, function world!')
    560 
    561         req = webapp2.Request.blank('/other')
    562         rsp = req.get_response(app)
    563         self.assertEqual(rsp.status_int, 200)
    564         self.assertEqual(rsp.body, 'Hello again, function world!')
    565 
    566         # Twice to test factory.
    567         req = webapp2.Request.blank('/other')
    568         rsp = req.get_response(app)
    569         self.assertEqual(rsp.status_int, 200)
    570         self.assertEqual(rsp.body, 'Hello again, function world!')
    571 
    572         req = webapp2.Request.blank('/one-more/bar')
    573         rsp = req.get_response(app)
    574         self.assertEqual(rsp.status_int, 200)
    575         self.assertEqual(rsp.body, 'Hello you too!')
    576 
    577     def test_custom_method(self):
    578         class MyHandler(webapp2.RequestHandler):
    579             def my_method(self):
    580                 self.response.out.write('Hello, custom method world!')
    581 
    582             def my_other_method(self):
    583                 self.response.out.write('Hello again, custom method world!')
    584 
    585         app = webapp2.WSGIApplication([
    586             webapp2.Route('/', MyHandler, handler_method='my_method'),
    587             webapp2.Route('/other', MyHandler, handler_method='my_other_method'),
    588         ])
    589 
    590         req = webapp2.Request.blank('/')
    591         rsp = req.get_response(app)
    592         self.assertEqual(rsp.status_int, 200)
    593         self.assertEqual(rsp.body, 'Hello, custom method world!')
    594 
    595         req = webapp2.Request.blank('/other')
    596         rsp = req.get_response(app)
    597         self.assertEqual(rsp.status_int, 200)
    598         self.assertEqual(rsp.body, 'Hello again, custom method world!')
    599 
    600     def test_custom_method_with_string(self):
    601         app = webapp2.WSGIApplication([
    602             webapp2.Route('/', handler='resources.handlers.CustomMethodHandler:custom_method'),
    603             webapp2.Route('/bleh', handler='resources.handlers.CustomMethodHandler:custom_method'),
    604         ])
    605 
    606         req = webapp2.Request.blank('/')
    607         rsp = req.get_response(app)
    608         self.assertEqual(rsp.status_int, 200)
    609         self.assertEqual(rsp.body, 'I am a custom method.')
    610 
    611         req = webapp2.Request.blank('/bleh')
    612         rsp = req.get_response(app)
    613         self.assertEqual(rsp.status_int, 200)
    614         self.assertEqual(rsp.body, 'I am a custom method.')
    615 
    616         self.assertRaises(ValueError, webapp2.Route, '/', handler='resources.handlers.CustomMethodHandler:custom_method', handler_method='custom_method')
    617 
    618     def test_factory_1(self):
    619         app.debug = True
    620         rsp = app.get_response('/bare')
    621         self.assertEqual(rsp.status_int, 200)
    622         self.assertEqual(rsp.body, 'I am not a RequestHandler but I work.')
    623         app.debug = False
    624 
    625     def test_factory_2(self):
    626         """Very crazy stuff. Please ignore it."""
    627         class MyHandler(object):
    628             def __init__(self, request, response):
    629                 self.request = request
    630                 self.response = response
    631 
    632             def __new__(cls, *args, **kwargs):
    633                 return cls.create_instance(*args, **kwargs)()
    634 
    635             @classmethod
    636             def create_instance(cls, *args, **kwargs):
    637                 obj = object.__new__(cls)
    638                 if isinstance(obj, cls):
    639                     obj.__init__(*args, **kwargs)
    640 
    641                 return obj
    642 
    643             def __call__(self):
    644                 return self
    645 
    646             def dispatch(self):
    647                 self.response.write('hello')
    648 
    649         app = webapp2.WSGIApplication([
    650             webapp2.Route('/', handler=MyHandler),
    651         ])
    652 
    653         req = webapp2.Request.blank('/')
    654         rsp = req.get_response(app)
    655         self.assertEqual(rsp.status_int, 200)
    656         self.assertEqual(rsp.body, 'hello')
    657 
    658     def test_encoding(self):
    659         class PostHandler(webapp2.RequestHandler):
    660             def post(self):
    661                 foo = self.request.POST['foo']
    662                 if not foo:
    663                     foo = 'empty'
    664 
    665                 self.response.write(foo)
    666 
    667         app = webapp2.WSGIApplication([
    668             webapp2.Route('/', PostHandler),
    669         ], debug=True)
    670 
    671         # foo with umlauts in the vowels.
    672         value = 'f\xc3\xb6\xc3\xb6'
    673 
    674         rsp = app.get_response('/', POST={'foo': value},
    675             headers=[('Content-Type', 'application/x-www-form-urlencoded; charset=utf-8')])
    676         self.assertEqual(rsp.body, 'f')
    677 
    678         rsp = app.get_response('/', POST={'foo': value},
    679             headers=[('Content-Type', 'application/x-www-form-urlencoded')])
    680         self.assertEqual(rsp.body, 'f')
    681 
    682 
    683 if __name__ == '__main__':
    684     test_base.main()
    685