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