def _apply_route(self, route: FutureRoute) -> Route: params = route._asdict() websocket = params.pop("websocket", False) subprotocols = params.pop("subprotocols", None) if websocket: self.enable_websocket() websocket_handler = partial( self._websocket_handler, route.handler, subprotocols=subprotocols, ) websocket_handler.__name__ = route.handler.__name__ # type: ignore websocket_handler.is_websocket = True # type: ignore params["handler"] = websocket_handler return self.router.add(**params)
def _apply_route(self, route: FutureRoute) -> List[Route]: params = route._asdict() websocket = params.pop("websocket", False) subprotocols = params.pop("subprotocols", None) if websocket: self.enable_websocket() websocket_handler = partial( self._websocket_handler, route.handler, subprotocols=subprotocols, ) websocket_handler.__name__ = route.handler.__name__ # type: ignore websocket_handler.is_websocket = True # type: ignore params["handler"] = websocket_handler routes = self.router.add(**params) if isinstance(routes, Route): routes = [routes] for r in routes: r.ctx.websocket = websocket r.ctx.static = params.get("static", False) return routes
def register(self, app, options): """ Register the blueprint to the sanic app. :param app: Instance of :class:`sanic.app.Sanic` class :param options: Options to be used while registering the blueprint into the app. *url_prefix* - URL Prefix to override the blueprint prefix """ self._apps.add(app) url_prefix = options.get("url_prefix", self.url_prefix) routes = [] middleware = [] exception_handlers = [] listeners = defaultdict(list) # Routes for future in self._future_routes: # attach the blueprint name to the handler so that it can be # prefixed properly in the router future.handler.__blueprintname__ = self.name # Prepend the blueprint URI prefix if available uri = url_prefix + future.uri if url_prefix else future.uri strict_slashes = ( self.strict_slashes if future.strict_slashes is None and self.strict_slashes is not None else future.strict_slashes ) name = app._generate_name(future.name) apply_route = FutureRoute( future.handler, uri[1:] if uri.startswith("//") else uri, future.methods, future.host or self.host, strict_slashes, future.stream, future.version or self.version, name, future.ignore_body, future.websocket, future.subprotocols, future.unquote, future.static, ) route = app._apply_route(apply_route) operation = ( routes.extend if isinstance(route, list) else routes.append ) operation(route) # Static Files for future in self._future_statics: # Prepend the blueprint URI prefix if available uri = url_prefix + future.uri if url_prefix else future.uri apply_route = FutureStatic(uri, *future[1:]) route = app._apply_static(apply_route) routes.append(route) route_names = [route.name for route in routes if route] # Middleware if route_names: for future in self._future_middleware: middleware.append(app._apply_middleware(future, route_names)) # Exceptions for future in self._future_exceptions: exception_handlers.append(app._apply_exception_handler(future)) # Event listeners for listener in self._future_listeners: listeners[listener.event].append(app._apply_listener(listener)) for signal in self._future_signals: signal.condition.update({"blueprint": self.name}) app._apply_signal(signal) self.routes = [route for route in routes if isinstance(route, Route)] # Deprecate these in 21.6 self.websocket_routes = [ route for route in self.routes if route.ctx.websocket ] self.middlewares = middleware self.exceptions = exception_handlers self.listeners = dict(listeners)
def decorator(handler): nonlocal uri nonlocal methods nonlocal host nonlocal strict_slashes nonlocal stream nonlocal version nonlocal name nonlocal ignore_body nonlocal subprotocols nonlocal websocket nonlocal static if isinstance(handler, tuple): # if a handler fn is already wrapped in a route, the handler # variable will be a tuple of (existing routes, handler fn) _, handler = handler name = self._generate_name(name, handler) if isinstance(host, str): host = frozenset([host]) elif host and not isinstance(host, frozenset): try: host = frozenset(host) except TypeError: raise ValueError( "Expected either string or Iterable of host strings, " "not %s" % host) if isinstance(subprotocols, (list, tuple, set)): subprotocols = frozenset(subprotocols) route = FutureRoute( handler, uri, None if websocket else frozenset([x.upper() for x in methods]), host, strict_slashes, stream, version, name, ignore_body, websocket, subprotocols, unquote, static, ) self._future_routes.add(route) args = list(signature(handler).parameters.keys()) if websocket and len(args) < 2: handler_name = handler.__name__ raise ValueError( f"Required parameter `request` and/or `ws` missing " f"in the {handler_name}() route?") elif not args: handler_name = handler.__name__ raise ValueError(f"Required parameter `request` missing " f"in the {handler_name}() route?") if not websocket and stream: handler.is_stream = stream if apply: self._apply_route(route) return route, handler
def register(self, app, options): """ Register the blueprint to the sanic app. :param app: Instance of :class:`sanic.app.Sanic` class :param options: Options to be used while registering the blueprint into the app. *url_prefix* - URL Prefix to override the blueprint prefix """ self._apps.add(app) url_prefix = options.get("url_prefix", self.url_prefix) opt_version = options.get("version", None) opt_strict_slashes = options.get("strict_slashes", None) opt_version_prefix = options.get("version_prefix", self.version_prefix) error_format = options.get("error_format", app.config.FALLBACK_ERROR_FORMAT) routes = [] middleware = [] exception_handlers = [] listeners = defaultdict(list) registered = set() # Routes for future in self._future_routes: # attach the blueprint name to the handler so that it can be # prefixed properly in the router future.handler.__blueprintname__ = self.name # Prepend the blueprint URI prefix if available uri = url_prefix + future.uri if url_prefix else future.uri version_prefix = self.version_prefix for prefix in ( future.version_prefix, opt_version_prefix, ): if prefix and prefix != "/v": version_prefix = prefix break version = self._extract_value(future.version, opt_version, self.version) strict_slashes = self._extract_value(future.strict_slashes, opt_strict_slashes, self.strict_slashes) name = app._generate_name(future.name) host = future.host or self.host if isinstance(host, list): host = tuple(host) apply_route = FutureRoute( future.handler, uri[1:] if uri.startswith("//") else uri, future.methods, host, strict_slashes, future.stream, version, name, future.ignore_body, future.websocket, future.subprotocols, future.unquote, future.static, version_prefix, error_format, future.route_context, ) if (self, apply_route) in app._future_registry: continue registered.add(apply_route) route = app._apply_route(apply_route) operation = (routes.extend if isinstance(route, list) else routes.append) operation(route) # Static Files for future in self._future_statics: # Prepend the blueprint URI prefix if available uri = url_prefix + future.uri if url_prefix else future.uri apply_route = FutureStatic(uri, *future[1:]) if (self, apply_route) in app._future_registry: continue registered.add(apply_route) route = app._apply_static(apply_route) routes.append(route) route_names = [route.name for route in routes if route] if route_names: # Middleware for future in self._future_middleware: if (self, future) in app._future_registry: continue middleware.append(app._apply_middleware(future, route_names)) # Exceptions for future in self._future_exceptions: if (self, future) in app._future_registry: continue exception_handlers.append( app._apply_exception_handler(future, route_names)) # Event listeners for future in self._future_listeners: if (self, future) in app._future_registry: continue listeners[future.event].append(app._apply_listener(future)) # Signals for future in self._future_signals: if (self, future) in app._future_registry: continue future.condition.update({"__blueprint__": self.name}) # Force exclusive to be False app._apply_signal(tuple((*future[:-1], False))) self.routes += [route for route in routes if isinstance(route, Route)] self.websocket_routes += [ route for route in self.routes if route.ctx.websocket ] self.middlewares += middleware self.exceptions += exception_handlers self.listeners.update(dict(listeners)) if self.registered: self.register_futures( self.apps, self, chain( registered, self._future_middleware, self._future_exceptions, self._future_listeners, self._future_signals, ), )