Example #1
0
 def __init__(self):
     WSGIApplication.__init__(
         self,
         [
             ("/Environment", _EnvironmentApp._EnvironmentHandler),
             ("/environment", _EnvironmentApp._EnvironmentHandler),
         ],
         debug=False,
         config=None,
     )
Example #2
0
    def test_app_get_config(self):
        app = WSGIApplication()

        assert app.get_config('resources.i18n', 'locale') == 'en_US'
        assert app.get_config('resources.i18n', 'locale', 'foo') == 'en_US'
        assert app.get_config('resources.i18n') == {
            'locale': 'en_US',
            'timezone': 'America/Chicago',
            'required': REQUIRED_VALUE,
        }
Example #3
0
class TemplateRequestHandlerTest(BaseTestCase, unittest.TestCase):

    application = WSGIApplication([('/', TemplateHandler)],
                                  config=wsgi_config,
                                  debug=True)

    def setUp(self):
        super(TemplateRequestHandlerTest, self).setUp()
        self.request = Request.blank('/',
                                     environ={
                                         'CONTENT_TYPE':
                                         'text/html; charset=ISO-8859-4',
                                     })
        self.response = Response()
        self.testapp.app.set_globals(app=self.testapp.app,
                                     request=self.request)

    def test_get(self):
        handler = TemplateRequestHandler(self.request, self.response)
        handler.template_name = 'test_template.html'
        with self.assertRaises(TemplateNotFound):
            self.testapp.get('/')

    def test_get_template_name(self):
        handler = TemplateRequestHandler(self.request, self.response)
        with self.assertRaises(ImproperlyConfigured):
            handler.get_template_name()
        handler.template_name = 'test_template.html'
        self.assertEqual(handler.get_template_name(), 'test_template.html')

    def test_get_context_data(self):
        handler = TemplateRequestHandler(self.request, self.response)
        self.assertIn('view', handler.get_context_data())
        self.assertIn('test', handler.get_context_data(test=123))
Example #4
0
class BaseRequestHandlerTest(BaseTestCase, unittest.TestCase):

    application = WSGIApplication([('/', BaseHandler)],
                                  config=wsgi_config,
                                  debug=True)

    def setUp(self):
        super(BaseRequestHandlerTest, self).setUp()
        self.request = Request.blank('/',
                                     environ={
                                         'CONTENT_TYPE':
                                         'text/html; charset=ISO-8859-4',
                                     })
        self.response = Response()
        self.testapp.app.set_globals(app=self.testapp.app,
                                     request=self.request)

    def test_init(self):
        handler = BaseRequestHandler(self.request, self.response)
        self.assertEqual(handler.LANGUAGE, 'en')
        self.assertEqual(handler.request, self.request)
        self.assertEqual(handler.response, self.response)

    def test_auth(self):
        handler = BaseRequestHandler(self.request, self.response)
        # Ducktype auth object.
        self.assertEqual(handler.auth.request, self.request)
Example #5
0
 def setUp(self):
     from webapp2 import WSGIApplication
     super(AppEngineWebTest, self).setUp()
     app = WSGIApplication(debug=True, config={
         'webapp2_extras.sessions': {'secret_key': 'notasecret'}
     })
     self.testapp = webtest.TestApp(app)
Example #6
0
 def setUp(self):
     super(FerrisTestCase, self).setUp()
     app = WSGIApplication(
         debug=True,
         config={'webapp2_extras.sessions': {
             'secret_key': 'notasecret'
         }})
     self.testapp = webtest.TestApp(app)
Example #7
0
    def setUp(self):
        super(SimpleAuthHandlerTestCase, self).setUp()
        # set back to default value
        DummyAuthHandler.OAUTH2_CSRF_STATE = SimpleAuthHandler.OAUTH2_CSRF_STATE
        DummyAuthHandler.SESSION_MOCK = {
            'req_token': {
                'oauth_token': 'oauth1 token',
                'oauth_token_secret': 'a secret'
            }
        }

        # handler instance for some of the tests
        self.handler = DummyAuthHandler()

        # Dummy app to run the tests against
        routes = [
            Route('/auth/<provider>',
                  handler=DummyAuthHandler,
                  handler_method='_simple_auth'),
            Route('/auth/<provider>/callback',
                  handler=DummyAuthHandler,
                  handler_method='_auth_callback')
        ]
        self.app = WSGIApplication(routes, debug=True)
Example #8
0
def create_simple_test_app(routes):
  """Create a simple webtest.TestApp with the specified routes.

  Args:
    routes: list of webapp2.Routes

  Returns:
    webtest.TestApp wrapping a webapp2.WSGIApplication
  """
  return TestApp(
    WSGIApplication(
      routes=routes,
      debug=True,
    )
  )
Example #9
0
  def setUp(self):
    super(SimpleAuthHandlerTestCase, self).setUp()
    # set back to default value
    DummyAuthHandler.OAUTH2_CSRF_STATE = SimpleAuthHandler.OAUTH2_CSRF_STATE
    DummyAuthHandler.SESSION_MOCK = {
      'req_token': {
        'oauth_token':'oauth1 token', 
        'oauth_token_secret':'a secret' 
      }
    }

    # handler instance for some of the tests
    self.handler = DummyAuthHandler()

    # Dummy app to run the tests against
    routes = [
      Route('/auth/<provider>', handler=DummyAuthHandler, 
        handler_method='_simple_auth'),
      Route('/auth/<provider>/callback', handler=DummyAuthHandler, 
        handler_method='_auth_callback') ]
    self.app = WSGIApplication(routes, debug=True)
    def request_handler_wrapper(request, *args, **kwargs):
        from webapp2 import Request, Response, WSGIApplication
        from django.http import HttpResponse

        class Route:
            handler_method = request.method.lower()

        req = Request(request.environ)
        req.route = Route()
        req.route_args = args
        req.route_kwargs = kwargs
        req.app = WSGIApplication()
        response = Response()
        view_func = request_handler(req, response)
        view_func.dispatch()

        django_response = HttpResponse(response.body, status=int(str(response.status).split(" ")[0]))
        for header, value in response.headers.iteritems():
            django_response[header] = value

        return django_response
Example #11
0
          handler='handlers.piskel.PiskelHandler:updateinfo',
          name='piskel-update',
          methods=['POST']),
    Route('/p/<piskel_id>/sprite',
          handler='handlers.image.GetImageHandler:get_piskel_sprite',
          name='piskel-get-sprite'),
    # ############# #
    # IMAGE  ROUTES #
    # ############# #
    Route('/img/<image_name>',
          handler='handlers.image.GetImageHandler',
          name='image-get'),
    Route('/img/<framesheet_id>/preview',
          handler='handlers.image.GetImageHandler:get_framesheet_preview',
          name='image-get-preview'),
    Route('/img/<framesheet_id>/framesheet',
          handler='handlers.image.GetImageHandler:get_framesheet',
          name='image-get-framesheet')
]

app = WSGIApplication(routes, config=config, debug=True)


def error_handler(request, response, exception):
    h = error.ErrorHandler(request, response)
    h.handle_error(exception)


error_codes = [403, 404, 500]
for error_code in error_codes:
    app.error_handlers[error_code] = error_handler
Example #12
0
app = WSGIApplication(
    [
        RedirectRoute('/manage', redirect_to_name='manage-home'
                      ),  #fixes stupid trailing slash thing
        PathPrefixRoute('/manage', [
            Route('/', HomeHandler, 'manage-home'),
            Route('/profile/<term>', InstructorOfficeHandler,
                  'manage-profile-office'),
            Route('/profile', ProfileHandler, 'manage-profile'),
            Route('/syllabus/create', SyllabusCreateHandler,
                  'create-syllabus'),
            Route('/syllabus/<fterm>/<fname>/duplicate', SyllabusCreateHandler,
                  'duplicate-syllabus'),
            Route('/syllabus/<term>/<name>/delete', SyllabusDeleteHandler,
                  'delete-syllabus'),
            Route('/syllabus/<term>/<name>/<step>', SyllabusHandler,
                  'edit-syllabus'),
            Route('/instructor', InstructorViewHandler, 'manage-instructor'),
            Route('/instructor/<iid>/<term>', InstructorOfficeHandler,
                  'manage-instructor-office'),
        ]),
        RedirectRoute(
            '/admin',
            redirect_to_name='admin-home'),  #fixes stupid trailing slash thing
        PathPrefixRoute('/admin', [
            Route('/', AdminHandler, 'admin-home'),
            Route('/<uid>/delete', AdminDeleteHandler, 'admin-delete'),
        ]),
        Route('/', IndexHandler, 'index'),
        Route('/static/<path:.+>', None, 'static'),
        Route('/login', LoginHandler, 'login'),
        Route('/logout', LogoutHandler, 'logout'),
        Route('/<instructor>/<term>', TermHandler, 'public-term'),
        Route('/<instructor>/<term>/<name>', ViewHandler, 'public-view'),
    ],
    debug=True,
    config={
        'webapp2_extras.auth': {
            'user_model': '_datatypes.user.User',
            'user_attributes': ['auth_ids']
        },
        'webapp2_extras.sessions': {
            'secret_key': 'I_wanted2eatPotato1nce'
        }
    })
Example #13
0
 def __init__(self):
     WSGIApplication.__init__(self, [("/api/Record/?.*", _RecordHandler)])
Example #14
0
import os, logging
from webapp2 import Route, WSGIApplication
from .handlers import *

config = {
    'template_path': 'app/html',
    'webapp2_extras.sessions': {
        # webapp2 security token to hmac breaks when not converted
        'secret_key': os.environ['EMBAR_SESSION'].encode()
    }
}

wsgi = WSGIApplication(
    [
        # PublicRequestHandler
        Route('/', handler=PublicRequestHandler, handler_method='get_index'),

        # AuthRequestHandler
        Route('/auth/register',
              handler=AuthRequestHandler,
              handler_method='post_register'),
        Route('/auth/login',
              handler=AuthRequestHandler,
              handler_method='post_login'),
        Route('/auth/logout',
              handler=AuthRequestHandler,
              handler_method='get_logout')
    ],
    debug=True,
    config=config)
Example #15
0
 def __init__(self):
     WSGIApplication.__init__(self, [("/api/Crawl/?.*", _CrawlHandler)])
Example #16
0
  def _auth_error(self, provider, msg=None):
    raise DummyAuthError("Couldn't authenticate against %s: %s" % (provider, msg))

  # mocks

  def _oauth1_client(self, token=None, consumer_key=None, consumer_secret=None):
    """OAuth1 client mock"""
    return OAuth1ClientMock(content='{"oauth_token": "some oauth1 request token"}')
    
  def _get_dummy_oauth1_user_info(self, auth_info, key=None, secret=None):
    return 'an oauth1 user info'

# dummy app to test requests against 
app = WSGIApplication([
  Route('/auth/<provider>', handler=DummyAuthHandler, handler_method='_simple_auth'),
  Route('/auth/<provider>/callback', handler=DummyAuthHandler, handler_method='_auth_callback')  
], debug=True)

#
# test suite
#

class SimpleAuthHandlerTestCase(helpers.BaseTestMixin, unittest.TestCase):
  def setUp(self):
    super(SimpleAuthHandlerTestCase, self).setUp()
    self.handler = DummyAuthHandler()
    
  def test_providers_dict(self):
    for p in ('google', 'windows_live', 'facebook', 'linkedin', 'twitter', 'openid'):
      self.assertIn(self.handler.PROVIDERS[p][0], ['oauth2', 'oauth1', 'openid'])
    
Example #17
0
"""
The App module provides the main WSGI app for ferris.
See /settings.py to configure the app. See app/routes.py
to configure routing
"""

import os
from webapp2 import WSGIApplication
from ferris.core import settings

# Only enable debug mode locally.
debug = os.environ.get('SERVER_SOFTWARE', '').startswith('Dev')

# Here's the main application, loads the config from the Ferris
# Settings API.
app = WSGIApplication(
    debug=debug,
    config=settings.get('app_config'))

# Custom Error Handlers
from ferris.controllers import errors
app.error_handlers[400] = errors.handle_400
app.error_handlers[401] = errors.handle_401
app.error_handlers[403] = errors.handle_403
app.error_handlers[404] = errors.handle_404
app.error_handlers[500] = errors.handle_500
Example #18
0
            # Find any orders in the database with this transaction ID
            MAX_ORDERS_TO_FETCH = 5
            orders = Order.query().filter(
                Order.transaction_id == transaction_id).fetch(
                    MAX_ORDERS_TO_FETCH)
            if orders:
                self.render_page(orders=orders)
            else:
                self.render_page(
                    error_text='No orders found with that Transaction ID.')

        else:
            self.render_page(error_text='You must enter a Transaction ID.')


# This is a list of "routes". This maps URLs from the browser to the handler
# classes defined above.
#
# Each route is a tuple with two values: a regular expression and a class.
# For each request from the browser, AppEngine will find the first regular
# expression in this list that matches the URL. It will then call either the
# get() or post() function on the class, depending on whether this is a GET or
# POST request.
#
# For more information, see: http://webapp2.readthedocs.io/en/latest/guide/routing.html
app = WSGIApplication(routes=[
    (r'/place-order', PlaceOrderHandler),
    (r'/order-lookup', OrderLookupHandler),
    (r'/', BundleHandler),
], )
Example #19
0
session_config = {
    'secret_key': 'ghostcatch00p3rsp00dfsdferwerwer43545lzxce',
    'cookie_name': 'ghost-name-picker',
    'session_max_age': 5 * 86400,
    'cookie_args': {
        'max_age': 5 * 86400,
    }
}

config = {'webapp2_extras.sessions': session_config}

# [START app]
app = WSGIApplication([
    PathPrefixRoute('/ghost_name_picker', [
        Route('/', Overview, name='home'),
        Route('/pick-name', NamePicker, name='name_picker'),
    ]),
],
                      config=config,
                      debug=True)
# [END app]

# Populates datastore with the default set of ghosts if none exists.
ghost_initial_set_up()


def main():
    app.RUN()


if __name__ == '__main__':
    main()
Example #20
0
import logging
from webapp2 import WSGIApplication
import web

logging.getLogger().setLevel(logging.DEBUG)

routes = [
    (r'/$|/map$', web.getMap),
    (r'/beers$', web.getBeers),
    (r'/preview$', web.postImagePreview),
    (r'/preview/.+$', web.getImagePreview),
    (r'/.+', web.MainHandler),
]
application = WSGIApplication(routes, debug=True)
Example #21
0
class LandingPage(RequestHandler):
    def get(self):
        user = users.get_current_user()
        if user:
            #User is authenticated
            if not Owner.exists(user):
                #User is not an Owner in DB, add them
                owner = Owner(id=user.user_id(),
                              email=user.email(),
                              nickname=user.nickname(),
                              )
                owner_key = owner.put()
            else:
                #User is an owner in DB, get their key
                owner_key = Owner.get_key(user)

            if Vessel.exists(owner_key):
                #Owner has a vessel, view it
                self.redirect('/myvessel')
            else:
                #Owner does not have a vessel, send to create form
                self.redirect('/newvessel')
        else:
            #redirect to splash
            template = JINJA_ENV.get_template('splash.html')
            self.response.write(template.render(
                loginurl=users.create_login_url('/')
            ))

application = WSGIApplication([('/', LandingPage)])
Example #22
0
 def __init__(self):
     WSGIApplication.__init__(self, [("/", MyHandler)])
Example #23
0
def create_app():
    return WSGIApplication(routes=routes, config=get_config(), debug=(get_app_env() == 'development'))
Example #24
0
    def remove_client_id(cls, client_id):
        server_key = cls.get_server_key(client_id)
        server_channels = cls.get_key(server_key).get()
        if server_channels is not None:
            try:
                server_channels.client_ids.remove(client_id)
                server_channels.put()
            except ValueError:
                pass


class ConnectedHandler(RequestHandler):
    def post(self):
        client_id = self.request.get('from')
        logging.info(u'channel client %s connected!' % client_id)
        ServerChannels.add_client_id(client_id)


class DisconnectedHandler(RequestHandler):
    def post(self):
        client_id = self.request.get('from')
        logging.info(u'channel client %s disconnected!' % client_id)
        ServerChannels.remove_client_id(client_id)


application = WSGIApplication([
    Route('/_ah/channel/connected/', ConnectedHandler),
    Route('/_ah/channel/disconnected/', DisconnectedHandler),
],
                              debug=False)
Example #25
0
#!/usr/bin/python
# -*- coding: utf-8 -*-

import logging
import os
import views

from webapp2 import WSGIApplication, Route
from webapp2_extras.routes import RedirectRoute

# Localhost timezone (datetime.now()) defaults to EAT (Computer Clocks timezone).
# This causes some issues since datastore auto_now is always on UTC
# E.g condition parser tests failing everyday between 0:00 and 3:00 EAT.
# The line below is a quick fix
os.environ['TZ'] = 'UTC'

logging.getLogger().setLevel(logging.DEBUG)

app = WSGIApplication([
    Route(r'/', handler=views.MainApp, name="MainApp"),
    RedirectRoute(r'/<:.*>', redirect_to="/")
],
                      debug=True)
Example #26
0
    (r'/api/0/google/sheets/([\w\-]+)/(\w+)/?', api.GoogleSheetsWorksheetRoute),
    (r'/api/0/user/?',                          api.UserRoute),
    (r'/api/0/data_source/?',                   api.DataSourceListRoute),
    (r'/api/0/data_source/(\d+)/?',             api.DataSourceItemRoute),
    (r'/api/0/data_source/(\d+)/view/?',        api.DataViewListRoute),
    (r'/api/0/data_source/(\d+)/view/(\d+)/?',  api.DataViewItemRoute),
    (r'/api/0/template/preview/?',              api.TemplatePreviewRoute),
    (r'/api/.*',                                api.Error404Route),
    (r'/api/?',                                 api.Error404Route),

    # Public Site
    # Last in list for profile pattern matching
    (r'/([\w\-]+)/?',                           public.ProfileRoute),
    (r'/([\w\-]+)/([\w\-]+)/?',                 public.DataSourceRoute),
    (r'/([\w\-]+)/([\w\-]+)\.([A-Za-z]+)?',     public.DataViewRoute),
]


# Load config
config = load_config()


# Create the application
app = WSGIApplication(routes=routes, debug=config['debug'], config=config)


# Define error page handlers for production only
# We want to see full error traces during development
if not config['debug']:
    app.error_handlers[404] = root.error_404
    app.error_handlers[500] = root.error_500
Example #27
0
from webapp2 import WSGIApplication, RequestHandler, Route


class WarmupHandler(RequestHandler):
    def get(self):
        self.response.out.write("Warmed Up")


application = WSGIApplication([
    Route('/_ah/warmup', WarmupHandler, name='warmup'),
],
                              debug=False)
Example #28
0
app = WSGIApplication(
    [
        Route('/', web.LandingHandler),
        PathPrefixRoute(
            '/api',
            [
                PathPrefixRoute('/alfa', [
                    Route('/registration', alfa_bank.PreCheckHandler),
                    Route('/check', alfa_bank.CheckStatusHandler),
                    Route('/create', alfa_bank.CreateByCardHandler),
                    Route('/reset', alfa_bank.ResetBlockedSumHandler),
                    Route('/pay', alfa_bank.PayByCardHandler),
                    Route('/unbind', alfa_bank.UnbindCardHandler),
                ]),
                PathPrefixRoute('/company', [
                    PathPrefixRoute('/<company_id:\d+>', [
                        Route('/info', api.NewsHandler),
                        Route('/menu', company.CompanyMenuHandler),
                        Route('/get_remainders', company.RemaindersHandler),
                        Route('/payment_types',
                              company.CompanyPaymentTypesHandler),
                        Route('/promos', promos.CompanyPromosHandler),
                        Route('/user_data', customer.SaveClientInfoHandler),
                        Route('/enter_card', customer.SaveBonusCardHandler),
                    ]),
                    Route('/get_company', company.CompanyInfoHandler),
                ]),
                Route('/delivery_types', company.CompanyDeliveryTypesHandler
                      ),  # it relates to company
                Route('/venues/<company_id:\d+>',
                      company.CompanyVenuesHandler),  # it relates to company
                PathPrefixRoute('/venue/<delivery_terminal_id:.*>', [
                    Route('/menu', venue.VenueMenuHandler),
                    Route('/order/new', order.PlaceOrderHandler),
                ]),
                Route('/payment_types/<delivery_terminal_id:.*>',
                      venue.VenuePaymentTypesHandler),  # it relates to venue
                Route('/iiko_promos',
                      promos.VenuePromosHandler),  # it relates to venue
                PathPrefixRoute('/order/<order_id:.*>', [
                    Route('/request_cancel', order.CancelOrderHandler),
                    Route('/review', order.OrderReviewHandler),
                    Route('', order.OrderInfoHandler),
                ]),
                Route('/status',
                      order.OrdersStatusHandler),  # it relates to order
                Route('/history', order.HistoryHandler),  # it relates to order
                Route('/get_order_promo',
                      order.CheckOrderHandler),  # it relates to order
                PathPrefixRoute('/customer', [
                    Route('/register', api.RegisterHandler),
                ]),
                PathPrefixRoute('/admin', [
                    Route('/login', admin.LoginHandler),
                    Route('/logout', admin.LogoutHandler),
                    PathPrefixRoute('/orders', [
                        Route('/current', admin.CurrentOrdersHandler),
                        Route('/updates', admin.OrderUpdatesHandler),
                        Route('/cancels', admin.CancelsHandler),
                        Route('/closed', admin.ClosedOrdersHandler),
                    ]),
                    Route('/menu', admin.MenuHandler),
                    Route('/dynamic_info', admin.DynamicInfoHandler),
                    Route('/stop_list/items', admin.ItemStopListHandler),
                    Route('/customer_history', admin.ClientHistoryHandler),
                ]),
                PathPrefixRoute('/push_admin', [
                    Route('/login', api_push_admin.LoginHandler,
                          'push_admin_login'),
                    Route('/logout', api_push_admin.LogoutHandler),
                    Route('/pushes', api_push_admin.PushSendingHandler,
                          'pushes'),
                    Route('/history', api_push_admin.PushHistoryHandler,
                          'admin_push_history'),
                    Route('/menu_reload', api_push_admin.ReloadMenuHandler),
                ]),
                PathPrefixRoute('/specials', [
                    PathPrefixRoute('/mivako_gift', [
                        Route('/info', specials.MivakoPromoInfoHandler),
                        Route('/send', specials.MivakoPromoSendGiftHandler),
                    ]),
                    Route('/cat_add_social', specials.CATAddSocialHandler),
                    Route('/cat_places', specials.CATFetchCoffeeShopsHandler),
                    Route('/cat_company_id', specials.CATGetCompanyIdHandler),
                    Route('/cat_company_id_2',
                          specials.CATGetCompanyIdHandler2),
                ]),
                PathPrefixRoute('/shared', [
                    PathPrefixRoute('/invitation', [
                        Route('/info', specials.InvitationInfoHandler),
                        Route('/get_url', specials.InvitationUrlsHandler),
                    ]),
                    PathPrefixRoute('/gift', [
                        Route('/get_url', specials.GiftUrlHandler),
                    ]),
                ]),
                PathPrefixRoute('/recommendation', [
                    Route('/by_item', specials.ItemRecommendationHandler),
                ]),
                Route('/address', address.AddressByStreetHandler),
                Route('/get_info', trash.GetAddressByKeyHandler),
            ]),
        PathPrefixRoute('/mt', [
            PathPrefixRoute('/report', [
                Route('', report.ReportHandler),
                Route('/venues', report.VenueReportHandler),
                Route('/orders', report.OrdersReportHandler),
                Route('/orders_lite', report.OrdersLiteReportHandler),
                Route('/reviews', report.ReviewsReportHandler),
                Route('/clients', report.ClientsReportHandler),
                Route('/repeated_orders', report.RepeatedOrdersReportHandler),
                Route('/square_table', report.SquareTableHandler),
                Route('/sum_changes', report.OrderSumChangesReport),
            ]),
            PathPrefixRoute('/company', [
                Route('/list', mt_company.CompanyListHandler),
                Route('/create', mt_company.CompanyCreateHandler),
                Route('/<company_id:\d+>', mt_company.CompanyEditHandler),
                PathPrefixRoute('/<company_id:\d+>', [
                    Route('/terminals', mt_company.TerminalListHandler),
                    Route('/terminals/<terminal_id>',
                          mt_company.TerminalEditHandler),
                ]),
            ]),
            PathPrefixRoute('/push', [
                Route('/send', push.PushSendingHandler),
                Route('/history', push.PushHistoryHandler, 'mt_push_history'),
            ]),
            PathPrefixRoute('/push_admin', [
                Route('/create_admins', push_admins.AutoCreatePushAdmins),
                Route('/list', push_admins.ListPushAdmins, 'push_admin_main'),
                PathPrefixRoute('/<admin_id:\d+>', [
                    Route('', push_admins.ChangeLoginPushAdmin),
                    Route('/change_password',
                          push_admins.ChangePasswordPushAdmin),
                ]),
            ]),
            PathPrefixRoute('/qr', [
                Route('', qr.AnalyticsLinkListHandler),
                Route('/<code:\w{,3}>', qr.AnalyticsLinkEditHandler),
            ]),
            PathPrefixRoute('/changelogs', [
                Route('', changes.ChangeLogFindOrderHandler),
                Route('/<order_id:.*>', changes.ViewChangeLogsHandler,
                      "view_changelog"),
            ]),
            Route('/migrate', migration.CreateNewCompaniesHandler),
        ]),
        PathPrefixRoute('/single_task', [
            PathPrefixRoute('/push', [
                Route('/review', task.PushReviewHandler),
            ]),
            PathPrefixRoute('/bonus', [
                Route('/activate', task.SharedBonusActivateHandler),
            ]),
        ]),
        PathPrefixRoute('/ext', [
            Route('/export_legals', ext_api.ExportLegalsHandler),
        ]),
        Route(
            '/very_long_secret_private_url/company/<company_id:\d+>/view_menu',
            web.ViewMenuHandler),
        Route('/get/<app:\w{,3}>', share.GATrackDownloadHandler),
        Route('/img/<:.*>', image_proxy.ImageProxyHandler),
        Route('/iiko_biz_app', iikobiz.IikoBizAppHandler),
        Route('/iiko_biz_submit', iikobiz.IikoBizSubmitHandler),
    ],
    debug=config.DEBUG,
    config=webapp2_config)
Example #29
0
from google.appengine.ext import testbed
from webapp2 import WSGIApplication

from webtest import TestApp

from ndb import model

from .. import migrate

from ..migrate import read_migrations, register_migrations, get_migration_dirs

from ..routes import routes

register_migrations("zojax.gae.migration", "migrations")

app = WSGIApplication()

for r in routes:
    app.router.add(r)


def rand_text(size=500):
    words = []
    for i in range(1, 50):
        words.append(''.join([
            random.choice(string.ascii_letters + '. ')
            for s in range(1, random.randrange(1, 10))
        ]))
    return " ".join(words)

Example #30
0
class SimpleAuthHandlerTestCase(TestMixin, unittest.TestCase):
  def setUp(self):
    super(SimpleAuthHandlerTestCase, self).setUp()
    # set back to default value
    DummyAuthHandler.OAUTH2_CSRF_STATE = SimpleAuthHandler.OAUTH2_CSRF_STATE
    DummyAuthHandler.SESSION_MOCK = {
      'req_token': {
        'oauth_token':'oauth1 token', 
        'oauth_token_secret':'a secret' 
      }
    }

    # handler instance for some of the tests
    self.handler = DummyAuthHandler()

    # Dummy app to run the tests against
    routes = [
      Route('/auth/<provider>', handler=DummyAuthHandler, 
        handler_method='_simple_auth'),
      Route('/auth/<provider>/callback', handler=DummyAuthHandler, 
        handler_method='_auth_callback') ]
    self.app = WSGIApplication(routes, debug=True)
    
  def test_providers_dict(self):
    for p in ('google', 'twitter', 'linkedin', 'linkedin2', 'openid', 
              'facebook', 'windows_live'):
      self.assertIn(self.handler.PROVIDERS[p][0], 
                   ['oauth2', 'oauth1', 'openid'])
    
  def test_token_parsers_dict(self):
    for p in ('google', 'windows_live', 'facebook', 'linkedin', 'linkedin2',
              'twitter'):
      parser = self.handler.TOKEN_RESPONSE_PARSERS[p]
      self.assertIsNotNone(parser)
      self.assertTrue(hasattr(self.handler, parser))

  def test_not_supported_provider(self):
    self.expectErrors()
    with self.assertRaises(sa.UnknownAuthMethodError):
      self.handler._simple_auth()
      
    with self.assertRaises(sa.UnknownAuthMethodError):
      self.handler._simple_auth('whatever')

    resp = self.app.get_response('/auth/xxx')
    self.assertEqual(resp.status_int, 500)
    self.assertRegexpMatches(resp.body, 'UnknownAuthMethodError')

  def test_openid_init(self):
    resp = self.app.get_response('/auth/openid?identity_url=some.oid.provider.com')
    self.assertEqual(resp.status_int, 302)
    self.assertEqual(resp.headers['Location'], 
      'https://www.google.com/accounts/Login?'
      'continue=http%3A//testbed.example.com/auth/openid/callback')
        
  def test_openid_callback_success(self):
    self.login_user('*****@*****.**', 123, 
      federated_identity='http://dude.example.org', 
      federated_provider='example.org')

    resp = self.app.get_response('/auth/openid/callback')
    self.assertEqual(resp.status_int, 302)
    self.assertEqual(resp.headers['Location'], 
      'http://localhost/logged_in?provider=openid')
    
    uinfo, auth = self.handler._openid_callback()
    self.assertEqual(auth, {'provider': 'example.org'})
    self.assertEqual(uinfo, {
      'id': 'http://dude.example.org', 
      'nickname': 'http://dude.example.org',
      'email': '*****@*****.**'
    })
  
  def test_openid_callback_failure(self):
    self.expectErrors()
    resp = self.app.get_response('/auth/openid/callback')
    self.assertEqual(resp.status_int, 500)
    self.assertRegexpMatches(resp.body, 'InvalidOpenIDUserError')

  def test_oauth1_init(self):
    resp = self.app.get_response('/auth/dummy_oauth1')
    
    self.assertEqual(resp.status_int, 302)
    self.assertEqual(resp.headers['Location'], 
      'https://dummy/oauth1_auth?'
      'oauth_token=some+oauth1+request+token&'
      'oauth_callback=%2Fauth%2Fdummy_oauth1%2Fcallback')

  def test_oauth1_callback_success(self):
    url = '/auth/dummy_oauth1/callback?oauth_verifier=a-verifier-token'
    resp = self.app.get_response(url)
    self.assertEqual(resp.status_int, 302)
    self.assertEqual(resp.headers['Location'], 
      'http://localhost/logged_in?provider=dummy_oauth1')
        
  def test_oauth1_callback_failure(self):
    self.expectErrors()
    resp = self.app.get_response('/auth/dummy_oauth1/callback')
    self.assertEqual(resp.status_int, 500)
    self.assertRegexpMatches(resp.body, 'No OAuth verifier was provided')
      
  def test_query_string_parser(self):
    parsed = self.handler._query_string_parser('param1=val1&param2=val2')
    self.assertEqual(parsed, {'param1':'val1', 'param2':'val2'})

  #
  # CSRF tests
  # 
  
  def test_csrf_default(self):
    # Backward compatibility with older versions
    self.assertFalse(SimpleAuthHandler.OAUTH2_CSRF_STATE)

  def test_csrf_oauth2_init(self):
    DummyAuthHandler.OAUTH2_CSRF_STATE = True
    resp = self.app.get_response('/auth/dummy_oauth2')

    self.assertEqual(resp.status_int, 302)
    self.assertEqual(resp.headers['Location'], 'https://dummy/oauth2?'
      'scope=a_scope&'
      'state=valid-csrf-token&'
      'redirect_uri=%2Fauth%2Fdummy_oauth2%2Fcallback&'
      'response_type=code&'
      'client_id=cl_id')

    session = json.loads(resp.headers['SessionMock'])
    session_token = session.get(DummyAuthHandler.OAUTH2_CSRF_SESSION_PARAM, '')
    self.assertEqual(session_token, 'valid-csrf-token')

  def test_csrf_oauth2_callback_success(self):
    # need a real token here to have a valid timestamp
    csrf_token = SimpleAuthHandler()._generate_csrf_token()
    DummyAuthHandler.OAUTH2_CSRF_STATE = True
    DummyAuthHandler.SESSION_MOCK = {
      DummyAuthHandler.OAUTH2_CSRF_SESSION_PARAM: csrf_token
    }

    fetch_resp = json.dumps({
      "access_token":"1/fFAGRNJru1FTz70BzhT3Zg",
      "expires_in": 3600,
      "token_type":"Bearer"
      })
    self.set_urlfetch_response('https://dummy/oauth2_token', 
      content=fetch_resp)

    resp = self.app.get_response('/auth/dummy_oauth2/callback?'
      'code=auth-code&state=%s' % csrf_token)

    self.assertEqual(resp.status_int, 302)
    self.assertEqual(resp.headers['Location'], 
      'http://localhost/logged_in?provider=dummy_oauth2')

    # token should be removed after during the authorization step
    session = json.loads(resp.headers['SessionMock'])
    self.assertFalse(DummyAuthHandler.OAUTH2_CSRF_SESSION_PARAM in session)

  def test_csrf_oauth2_failure(self):
    self.expectErrors()
    DummyAuthHandler.OAUTH2_CSRF_STATE = True
    DummyAuthHandler.SESSION_MOCK = {}

    token = SimpleAuthHandler()._generate_csrf_token()
    resp = self.app.get_response('/auth/dummy_oauth2/callback?'
      'code=auth-code&state=%s' % token)

    self.assertEqual(resp.status_int, 500)
    self.assertRegexpMatches(resp.body, 'InvalidCSRFTokenError')

  def test_csrf_oauth2_tokens_dont_match(self):
    self.expectErrors()

    token1 = SimpleAuthHandler()._generate_csrf_token()
    token2 = SimpleAuthHandler()._generate_csrf_token()
    
    DummyAuthHandler.OAUTH2_CSRF_STATE = True
    DummyAuthHandler.SESSION_MOCK = {
      DummyAuthHandler.OAUTH2_CSRF_SESSION_PARAM: token1
    }

    resp = self.app.get_response('/auth/dummy_oauth2/callback?'
      'code=auth-code&state=%s' % token2)

    self.assertEqual(resp.status_int, 500)
    self.assertRegexpMatches(resp.body, 'InvalidCSRFTokenError')

  def test_csrf_token_generation(self):
    h = SimpleAuthHandler()
    token = h._generate_csrf_token()
    token2 = h._generate_csrf_token()
    self.assertNotEqual(token, token2)

    decoded = base64.urlsafe_b64decode(token)
    tok, ts = decoded.rsplit(h.OAUTH2_CSRF_DELIMITER, 1)
    # > 10 so that I won't have to modify this test if the length changes
    # in the future
    self.assertTrue(len(tok) > 10)
    # token generation can't really take more than 1 sec here
    self.assertFalse(long(time.time()) - long(ts) > 1)

  def test_csrf_validation(self):
    self.expectErrors()
    h = SimpleAuthHandler()

    token = h._generate_csrf_token()
    token2 = h._generate_csrf_token()
    self.assertTrue(h._validate_csrf_token(token, token))
    self.assertFalse(h._validate_csrf_token(token, token2))
    self.assertFalse(h._validate_csrf_token('', token))
    self.assertFalse(h._validate_csrf_token(token, ''))
    self.assertFalse(h._validate_csrf_token('', ''))
    self.assertFalse(h._validate_csrf_token('invalid b64', 'invalid b64'))

    # no timestamp
    token = base64.urlsafe_b64encode('random')
    self.assertFalse(h._validate_csrf_token(token, token))
    token = base64.urlsafe_b64encode('random%s' % h.OAUTH2_CSRF_DELIMITER)
    self.assertFalse(h._validate_csrf_token(token, token))

    # no token key
    token = '%s%d' % (h.OAUTH2_CSRF_DELIMITER, long(time.time()))
    encoded = base64.urlsafe_b64encode(token)
    self.assertFalse(h._validate_csrf_token(encoded, encoded))

    # token timeout
    timeout = long(time.time()) - h.OAUTH2_CSRF_TOKEN_TIMEOUT - 1
    token = h._generate_csrf_token(_time=timeout)
    self.assertFalse(h._validate_csrf_token(token, token))
            return self.html_view('template.html', test=test)
        if test == 'session-start':
            self.session['test'] = self.request.get('key')
            return
        if test == 'session-read':
            return self.json_view(session=self.session.get('test'))
        if test == 'session-end':
            del self.session['test']
            return


app = WebTest(
    WSGIApplication(
        [(r'/(.+)', ExampleRequestHandler)],
        config={
            'webapp2_extras.sessions': {
                'secret_key': 'test-secret-session-key'
            },
            'template_path': 'test/html'
        }))


def test_get_json_view_test_object():
    response = app.get('/json-object')

    expect(response.status).to.eq('200 OK')
    expect(response.status_int).to.eq(200)
    expect(response.content_type).to.eq('application/json')
    expect(response.content_length).to.be.above(0)
    expect(response.json).to.eq({u'test': u'json-object'})

Example #32
0
import os
from webapp2 import WSGIApplication, Route

# Make sure external paths are correctly set
import ext

# webapp2 config
config = {'webapp2_extras.auth': {'user_model': 'auth.models.User'}}

debug = os.environ.get('SERVER_SOFTWARE', '').startswith('Dev')

routes = [
    Route('/oauth2/access_token',
          handler='auth.handlers.AuthHandler',
          name='auth_access_token'),
]

app = WSGIApplication(routes, config=config, debug=debug)
Example #33
0
  # PISKEL ROUTES #
  # ############# #
  Route('/p/<piskel_id>/history', handler='handlers.piskel.PiskelHandler:get_history', name='piskel-view-history'),
  Route('/p/<piskel_id>/view', handler='handlers.piskel.PiskelHandler:view', name='piskel-view'),
  Route('/p/<piskel_id>/delete', handler='handlers.piskel.PiskelHandler:delete', name='piskel-delete'),
  Route('/p/<piskel_id>/perm_delete', handler='handlers.piskel.PiskelHandler:permanently_delete', name='piskel-permanent-delete'),
  Route('/p/<piskel_id>/clone', handler='handlers.piskel.PiskelHandler:clone', name='piskel-clone'),
  Route('/p/<piskel_id>/clone/<action>', handler='handlers.piskel.PiskelHandler:clone', name='piskel-clone-action'),
  Route('/p/<piskel_id>/rollback/<framesheet_id>', handler='handlers.piskel.PiskelHandler:rollback_piskel_to_framesheet', name='piskel-rollback'),
  Route('/p/<piskel_id>/restore', handler='handlers.piskel.PiskelHandler:restore', name='piskel-restore'),
  Route('/p/<piskel_id>/edit', handler='handlers.piskel.PiskelHandler:edit', name='piskel-edit'),
  Route('/p/<piskel_id>/save', handler='handlers.piskel.PiskelHandler:save', name='piskel-save', methods=['POST']),
  Route('/p/<piskel_id>/updateinfo', handler='handlers.piskel.PiskelHandler:updateinfo', name='piskel-update', methods=['POST']),
  Route('/p/<piskel_id>/sprite', handler='handlers.image.GetImageHandler:get_piskel_sprite', name='piskel-get-sprite'),
  # ############# #
  # IMAGE  ROUTES #
  # ############# #
  Route('/img/<image_name>', handler='handlers.image.GetImageHandler', name='image-get'),
  Route('/img/<framesheet_id>/preview', handler='handlers.image.GetImageHandler:get_framesheet_preview', name='image-get-preview'),
  Route('/img/<framesheet_id>/framesheet', handler='handlers.image.GetImageHandler:get_framesheet', name='image-get-framesheet')
]

app = WSGIApplication(routes, config=config, debug=True)

def error_handler(request, response, exception):
    h = error.ErrorHandler(request, response)
    h.handle_error(exception)

error_codes = [403, 404, 500]
for error_code in error_codes:
    app.error_handlers[error_code] = error_handler
Example #34
0
 def __call__(self, environ, start_response):
     path_info_pop(environ)
     path_info_pop(environ)
     #info("PATH_INFO = " + environ["PATH_INFO"]) 
     return WSGIApplication.__call__(self, environ, start_response)
Example #35
0
    Route('/<projectid:[0-9]+>/datasets/<datasetid:[0-9]+>/<datacid:[0-9]+>/new', 'src.datasets.NewDataRevisionPage'),
    Route('/<projectid:[0-9]+>/datasets/<datasetid:[0-9]+>/<datacid:[0-9]+>/edit', 'src.datasets.EditConceptPage'),
    Route('/<projectid:[0-9]+>/datasets/<datasetid:[0-9]+>/<datacid:[0-9]+>/upload', 'src.datasets.UploadDataRevisionHandler'),
    Route('/<projectid:[0-9]+>/datasets/<datasetid:[0-9]+>/<datacid:[0-9]+>/edit/<revid:[0-9]+>', 'src.datasets.EditRevisionPage'),
    Route('/<projectid:[0-9]+>/datasets/<datasetid:[0-9]+>/<datacid:[0-9]+>/update/<revid:[0-9]+>', 'src.datasets.UpdateDataRevisionHandler'),
    # Code
    Route('/<projectid:[0-9]+>/code', 'src.code.CodesListPage'),
    Route('/<projectid:[0-9]+>/code/new', 'src.code.NewCodePage'),
    Route('/<projectid:[0-9]+>/code/<codeid:[0-9]+>/edit', 'src.code.EditCodePage'),
    Route('/<projectid:[0-9]+>/code/<codeid:[0-9]+>', 'src.code.ViewCodePage'),
    # Bibliography
    Route('/<projectid:[0-9]+>/bibliography', 'src.bibliography.MainPage'),
    Route('/<projectid:[0-9]+>/bibliography/new_item', 'src.bibliography.NewItemPage'),
    Route('/<projectid:[0-9]+>/bibliography/<itemid:[0-9]+>/<commentid:[0-9]+>', 'src.bibliography.CommentPage'),
    Route('/<projectid:[0-9]+>/bibliography/<itemid:[0-9]+>', 'src.bibliography.ItemPage'),
    # Admin projects
    Route('/<projectid:[0-9]+>/admin', 'src.projects.AdminPage'),
    Route('/<projectid:[0-9]+>/invite', 'src.projects.InvitePage'),
    Route('/file/<blobkey:.+>', 'src.datasets.DownloadDataRevisionHandler'),
    
    Route('/<projectid:[0-9]+>', 'src.frontend.OverviewPage'),
    Route('/<username:.+>/outreach', 'src.outreach.MainPage'),
    Route('/<username:.+>/outreach/new_post', 'src.outreach.NewPostPage'),
    Route('/<username:.+>/outreach/<postid:[0-9]+>/edit', 'src.outreach.EditPostPage'),
    Route('/<username:.+>/outreach/<postid:[0-9]+>', 'src.outreach.ViewPostPage'),
    Route('/<username:.+>', 'src.users.UserPage')]


app = WSGIApplication(routes, config = app_config, debug = True)

#!/usr/bin/env python

import sys
import os

sys.path.append(os.path.join(os.path.abspath('.'), 'venv/Lib/site-packages'))

from credentials import TOKEN
from webapp2 import WSGIApplication, Route

routes = [
    # Route for handle webhook (change it using admin rights, maybe..
    Route('/set_webhook',
          handler='handlers.hook_handler.WebHookHandler:set_webhook'),

    # Route for Telegram updates
    Route('/' + TOKEN,
          handler='handlers.hook_handler.WebHookHandler:webhook_handler')
]
app = WSGIApplication(routes, debug=False)
Example #37
0
            )
        ]
    ),
]

# APP ROUTES GOES HERE
app_routes = [
    Route(r'/', home_handler.HomeHandler, 'home'),
]

if app_config.enable_admin:
    app_routes.extend(ah_routes)

app = WSGIApplication(
    app_routes,
    debug = app_config.debug,
    config = app_config.config
)

if not app_config.debug:
    # bad request
    app.error_handlers[400] = error_handlers.HTTP_400
    # unauthorized 
    app.error_handlers[401] = error_handlers.HTTP_401
    # forbidden
    app.error_handlers[403] = error_handlers.HTTP_403
    # not found
    app.error_handlers[404] = error_handlers.HTTP_404
    # not allowed
    app.error_handlers[405] = error_handlers.HTTP_405
    # internal server error
Example #38
0
        return jinja2.get_jinja2(app=self.app)

    def cnr(self, view, **context):
        self.response.write(self.jinja2.render_template(view, **context))


class Index(TemplateHandler):
    """
    Welcome page listing katas and allowing login
    """
    get = loggedin()


# Build the app
kmodules = {k[0]: __import__(k[0]) for k in katas}
kroutes = [
    Route(('/katas/%s/%s' % (kata, route)).rstrip('/'),
          Class,
          name=Class.__name__) for kata, module in kmodules.items()
    for route, Class in module.routes
]
routes = [
    Route('/', Index),
    Route('/login/CAS<path:/.*>', CASLogin, name='cas'),
    Route('/login/google<path:/.*>', GoogleLogin, name='google'),
    Route('/logout', Logout, name='logout'),
]
app = WSGIApplication(routes + kroutes,
                      debug=environ.get('SERVER_SOFTWARE').startswith('Dev'),
                      config=config)
Example #39
0
import os

sys.path.append(os.path.join(os.path.abspath('.'), 'venv/Lib/site-packages'))

from credentials import TOKEN
from webapp2 import WSGIApplication, Route

from handlers.main_handlers import *

webapp2_config = {}
webapp2_config['webapp2_extras.sessions'] = {
    'secret_key': 'Im_an_alien',
}

routes = [
    ('/', IndexHandler),

    # Route for handle webhook (change it using admin rights, maybe..
    Route('/set_webhook/<token>',
          handler='handlers.hook_handler.WebHookHandler:set_webhook'),
    Route('/unset_webhook/<token>',
          handler='handlers.hook_handler.WebHookHandler:unset_webhook'),

    # Route for Telegram updates
    Route('/bot_handler/<token>',
          handler='handlers.hook_handler.WebHookHandler:webhook_handler'),
    ('/addbot', AddBotHandler),
    ('/deletebot', DeleteBotHandler),
]
app = WSGIApplication(routes, config=webapp2_config, debug=False)
Example #40
0
    def post(self):
        main_template = JINJA_ENVIRONMENT.get_template('share-target-destination.template.html')


        main_template_values = {
          'generation_location': 'server-side',
          'received_title': escape(self.request.POST.get('received_title', '')),
          'received_text': escape(self.request.POST.get('received_text', '')),
          'received_url': escape(self.request.POST.get('received_url', ''))
        }

        def process_attachments(field):
          received_file = self.request.POST.getall(field)
          attachments = [{'content': f.file.read(),
                           'filename': f.filename} for f in received_file if f != '']

          if len(attachments) > 0:
            file_contents = ", ".join([attachment['content'] for attachment in attachments])
            main_template_values[field] = file_contents

        process_attachments('received_html_files')
        process_attachments('received_css_files')

        print(main_template_values)
        self.response.write(main_template.render(main_template_values))


app = WSGIApplication([
    ('/share-target-destination.html', MainPage),
])
Example #41
0
            return

        num_stored = 0
        for n in news_list:
            try:
                n['text'] = get_news_text(n['link'])
            except ConnectionError:
                logging.exception("Error fetching news link")
                continue
            except ParseError:
                logging.exception("Error parsing news text.")
                continue
            except InputError:
                logging.exception("Input Error")
                continue

            news = News()
            try:
                if news.add_db_unique(n):
                    num_stored += 1
            except InputError:
                logging.exception("Input Error")
                continue

        self.response.write("Number of editorials stored = " + str(num_stored))


app = WSGIApplication([
    ('/feeds', Feeds),
], debug=True)
Example #42
0
    ('/api/disconnect', DisconnectHandler),
    ('/api/sync', SynchronizationHandler),
    ('/api/user', UserHandler),
    Route(
        '/auth/<provider>',
        handler='spidernotes.handlers.authentication.AuthHandler:_simple_auth',
        name='auth_login'),
    Route(
        '/auth/<provider>/callback',
        handler='spidernotes.handlers.authentication.AuthHandler:_auth_callback',
        name='auth_callback'),
    Route(
        '/logout',
        handler='spidernotes.handlers.authentication.AuthHandler:logout',
        name='logout'),
    (r'/.*', DefaultHandler)
]

config = {
    'webapp2_extras.auth': {
        'session_backend': 'memcache',
    },
    'webapp2_extras.sessions': {
        'cookie_name': '_simpleauth_sess',
        'secret_key': str(SESSION_KEY)
    }
}

app = WSGIApplication(routes=routes, config=config)
app.error_handlers[404] = handle_404
app.error_handlers[500] = handle_500
Example #43
0
from handlers import web, api
import secrets
from webapp2 import uri_for, Route, WSGIApplication
from webapp2_extras import jinja2
from utils import md5

config = {'webapp2_extras.sessions': {'secret_key': secrets.SESSION_KEY}}

application = WSGIApplication(
    [
        Route('/', web.MainPageHandler, 'main'),
        Route('/signup', web.SignUpHandler, 'signup'),
        Route('/signin', web.SignInHandler, 'signin'),
        Route('/signout', web.SignOutHandler, 'signout'),
        Route('/dashboard', web.DashboardHandler, 'dashboard'),
        Route('/upload_avatar', web.UploadAvatarHandler, 'upload_avatar'),

        #Route(r'/a/([^/]+)?', api.AvatarDownloadHandler, 'avatar')
        Route(r'/a/<email_hash>', api.DownloadAvatarHandler, 'avatar')
    ],
    debug=True,
    config=config)

jinja2.set_jinja2(jinja2.Jinja2(
    application,
    {'globals': {
        'uri_for': uri_for,
        'md5': md5,
        'site_name': 'My Gravatar'
    }}),
                  app=application)