"""Proxy handlers""" # Copyright (c) Jupyter Development Team. # Distributed under the terms of the Modified BSD License. import json from tornado import web from ..scopes import needs_scope from .base import APIHandler class ProxyAPIHandler(APIHandler): @needs_scope('proxy') async def get(self): """GET /api/proxy fetches the routing table This is the same as fetching the routing table directly from the proxy, but without clients needing to maintain separate """ offset, limit = self.get_api_pagination() all_routes = await self.proxy.get_all_routes() if offset == 0 and len(all_routes) < limit: routes = all_routes else: routes = {} end = offset + limit for i, key in enumerate(sorted(all_routes.keys())): if i < offset: continue elif i >= end: break routes[key] = all_routes[key] if self.accepts_pagination: data = self.paginated_model(routes, offset, limit, len(all_routes)) else: data = routes self.write(json.dumps(data)) @needs_scope('proxy') async def post(self): """POST checks the proxy to ensure that it's up to date. Can be used to jumpstart a newly launched proxy without waiting for the check_routes interval. """ await self.proxy.check_routes(self.users, self.services) @needs_scope('proxy') async def patch(self): """PATCH updates the location of the proxy Can be used to notify the Hub that a new proxy is in charge """ if not self.request.body: raise web.HTTPError(400, "need JSON body") try: model = json.loads(self.request.body.decode('utf8', 'replace')) except ValueError: raise web.HTTPError(400, "Request body must be JSON dict") if not isinstance(model, dict): raise web.HTTPError(400, "Request body must be JSON dict") if 'api_url' in model: self.proxy.api_url = model['api_url'] if 'auth_token' in model: self.proxy.auth_token = model['auth_token'] self.log.info("Updated proxy at %s", self.proxy) await self.proxy.check_routes(self.users, self.services) default_handlers = [(r"/api/proxy", ProxyAPIHandler)]