def _precheck(self): if self.args.debug and self.main_process: error_logger.warning( "Starting in v22.3, --debug will no " "longer automatically run the auto-reloader.\n Switch to " "--dev to continue using that functionality." ) # # Custom TLS mismatch handling for better diagnostics if self.main_process and ( # one of cert/key missing bool(self.args.cert) != bool(self.args.key) # new and old style self.args used together or self.args.tls and self.args.cert # strict host checking without certs would always fail or self.args.tlshost and not self.args.tls and not self.args.cert ): self.parser.print_usage(sys.stderr) message = ( "TLS certificates must be specified by either of:\n" " --cert certdir/fullchain.pem --key certdir/privkey.pem\n" " --tls certdir (equivalent to the above)" ) error_logger.error(message) sys.exit(1)
async def connection_task(self): """ Run a HTTP connection. Timeouts and some additional error handling occur here, while most of everything else happens in class Http or in code called from there. """ try: self._setup_connection() await self._http.http1() except CancelledError: pass except Exception: error_logger.exception("protocol.connection_task uncaught") finally: if self.app.debug and self._http: ip = self.transport.get_extra_info("peername") error_logger.error("Connection lost before response written" f" @ {ip} {self._http.request}") self._http = None self._task = None try: self.close() except BaseException: error_logger.exception("Closing failed")
async def http1(self): """ HTTP 1.1 connection handler """ while True: # As long as connection stays keep-alive try: # Receive and handle a request self.stage = Stage.REQUEST self.response_func = self.http1_response_header await self.http1_request_header() self.request.conn_info = self.protocol.conn_info await self.protocol.request_handler(self.request) # Handler finished, response should've been sent if self.stage is Stage.HANDLER and not self.upgrade_websocket: raise ServerError("Handler produced no response") if self.stage is Stage.RESPONSE: await self.response.send(end_stream=True) except CancelledError: # Write an appropriate response before exiting e = self.exception or ServiceUnavailable("Cancelled") self.exception = None self.keep_alive = False await self.error_response(e) except Exception as e: # Write an error response await self.error_response(e) # Try to consume any remaining request body if self.request_body: if self.response and 200 <= self.response.status < 300: error_logger.error(f"{self.request} body not consumed.") try: async for _ in self: pass except PayloadTooLarge: # We won't read the body and that may cause httpx and # tests to fail. This little delay allows clients to push # a small request into network buffers before we close the # socket, so that they are then able to read the response. await sleep(0.001) self.keep_alive = False # Exit and disconnect if no more requests can be taken if self.stage is not Stage.IDLE or not self.keep_alive: break # Wait for next request if not self.recv_buffer: await self._receive_more()
def _get_app(self): try: module_path = os.path.abspath(os.getcwd()) if module_path not in sys.path: sys.path.append(module_path) if self.args.simple: path = Path(self.args.module) app = create_simple_server(path) else: delimiter = ":" if ":" in self.args.module else "." module_name, app_name = self.args.module.rsplit(delimiter, 1) if module_name == "" and os.path.isdir(self.args.module): raise ValueError( "App not found.\n" " Please use --simple if you are passing a " "directory to sanic.\n" f" eg. sanic {self.args.module} --simple") if app_name.endswith("()"): self.args.factory = True app_name = app_name[:-2] module = import_module(module_name) app = getattr(module, app_name, None) if self.args.factory: try: app = app(self.args) except TypeError: app = app() app_type_name = type(app).__name__ if not isinstance(app, Sanic): if callable(app): solution = f"sanic {self.args.module} --factory" raise ValueError("Module is not a Sanic app, it is a" f"{app_type_name}\n" " If this callable returns a" f"Sanic instance try: \n{solution}") raise ValueError( f"Module is not a Sanic app, it is a {app_type_name}\n" f" Perhaps you meant {self.args.module}:app?") except ImportError as e: if module_name.startswith(e.name): error_logger.error( f"No module named {e.name} found.\n" " Example File: project/sanic_server.py -> app\n" " Example Module: project.sanic_server.app") else: raise e return app
def validate(request: Request, header: Type[BaseModel] = None, query: Type[BaseModel] = None, path: Type[BaseModel] = None, body: Type[BaseModel] = None, form: Type[BaseModel] = None, error: Type[SanicException] = None) -> ParsedArgsObj: """ When there are the same parameter name in the model, the parameter in ParsedArgsObj will be overwritten, The priorities is: body = form > query > path > header """ try: parsed_args = ParsedArgsObj() if header: parsed_args.update(header(**request.headers).dict()) if path: parsed_args.update(path(**request.match_info).dict()) if query: params = { key: val[0] if len(val) == 1 else val for key, val in request.args.items() } parsed_args.update(query(**params).dict()) if form: form_data = { key: val[0] if len(val) == 1 else val for key, val in request.form.items() } parsed_args.update(form(**form_data).dict()) elif body: parsed_args.update(body(**request.json).dict()) except ValidationError as e: # error handler function of sanic_dantic > default InvalidUsage if error: error_msg = e.errors()[0] message = f'{error_msg.get("loc")[0]} {error_msg.get("msg")}' raise error(message) else: error_msg = e.errors()[0] message = f'{error_msg.get("loc")[0]} {error_msg.get("msg")}' error_logger.error(message) raise InvalidUsage(message) except Exception as e: raise e request.ctx.params = parsed_args return parsed_args
def _precheck(self): # # Custom TLS mismatch handling for better diagnostics if self.main_process and ( # one of cert/key missing bool(self.args.cert) != bool(self.args.key) # new and old style self.args used together or self.args.tls and self.args.cert # strict host checking without certs would always fail or self.args.tlshost and not self.args.tls and not self.args.cert): self.parser.print_usage(sys.stderr) message = ( "TLS certificates must be specified by either of:\n" " --cert certdir/fullchain.pem --key certdir/privkey.pem\n" " --tls certdir (equivalent to the above)") error_logger.error(message) sys.exit(1)
async def get_user_bed_info(username): """ Args: username: username Returns: dict { bed: string portal: string ip: string } """ async with SQLPool.acquire() as conn: async with conn.cursor(DictCursor) as cur: sql = ("SELECT i.description, ip_type_id " "FROM `user` AS u " "INNER JOIN `iptable` AS i ON i.uid = u.uid " "WHERE u.username = %s " "AND (i.ip_type_id = 2 OR i.ip_type_id = 1)") para_input = username await cur.execute(sql, para_input) data = await cur.fetchone() if data is None: return None if data["description"] == "": error_logger.error( "Dorm Ip found but description missing: {}".format( username)) return messages.INTERNAL_SERVER_ERROR bed = data["description"].split(".") dicts = { "portal": bed[0], "bed": bed[1], "ip_type": data["ip_type_id"] } return dicts
def __init__( self, header: Type[BaseModel] = None, query: Type[BaseModel] = None, path: Type[BaseModel] = None, body: Type[BaseModel] = None, form: Type[BaseModel] = None, error: Type[SanicException] = None, ) -> None: """ The param must be a BaseModel class or must inherit from BaseModel \n if listed, the same model name's model will use strict mode """ try: if body and form: raise AssertionError( "sanic-dantic: " + "body and form cannot be used at the same time.") self.items = { "header": header, "path": path, "query": query, "form": form, "body": body, "error": error } for model in [header, path, query, form, body]: if model and BaseModel not in getmro(model): raise AssertionError( "sanic-dantic: " + "model must inherited from Pydantic.BaseModel") if error and SanicException not in getmro(error): raise AssertionError( "sanic-dantic: " + "error must inherited from SanicException") except AssertionError as e: error_logger.error(e) raise ServerError(str(e))
def _get_app(self): try: module_path = os.path.abspath(os.getcwd()) if module_path not in sys.path: sys.path.append(module_path) if self.args.simple: path = Path(self.args.module) app = create_simple_server(path) else: delimiter = ":" if ":" in self.args.module else "." module_name, app_name = self.args.module.rsplit(delimiter, 1) if app_name.endswith("()"): self.args.factory = True app_name = app_name[:-2] module = import_module(module_name) app = getattr(module, app_name, None) if self.args.factory: app = app() app_type_name = type(app).__name__ if not isinstance(app, Sanic): raise ValueError( f"Module is not a Sanic app, it is a {app_type_name}\n" f" Perhaps you meant {self.args.module}.app?" ) except ImportError as e: if module_name.startswith(e.name): error_logger.error( f"No module named {e.name} found.\n" " Example File: project/sanic_server.py -> app\n" " Example Module: project.sanic_server.app" ) else: raise e return app
async def connection_task(self): # no cov """ Run a HTTP connection. Timeouts and some additional error handling occur here, while most of everything else happens in class Http or in code called from there. """ try: self._setup_connection() await self.app.dispatch( "http.lifecycle.begin", inline=True, context={"conn_info": self.conn_info}, ) await self._http.http1() except CancelledError: pass except Exception: error_logger.exception("protocol.connection_task uncaught") finally: if (self.app.debug and self._http and self.transport and not self._http.upgrade_websocket): ip = self.transport.get_extra_info("peername") error_logger.error("Connection lost before response written" f" @ {ip} {self._http.request}") self._http = None self._task = None try: self.close() except BaseException: error_logger.exception("Closing failed") finally: await self.app.dispatch( "http.lifecycle.complete", inline=True, context={"conn_info": self.conn_info}, ) # Important to keep this Ellipsis here for the TouchUp module ...
async def bp_ip_set_owned_ip_mac(request, username, ip): username = request["username"] mac = request.json["mac"] ips = await Ip.get_user_own_ip(username) target_ip = next((i for i in ips if i["ip"] == ip), None) if re.match("^([0-9A-Fa-f]{12})$", mac) is None: return messages.INVALID_MAC # cant edit not owned ip if target_ip is None: return messages.NO_PERMISSION if await MAC.set_mac(target_ip["ip"], mac): await log_mac_change(ip, username, target_ip["mac"], mac) return messages.OPERATION_SUCCESS else: error_logger.error("Operation failed") error_logger.error(request.url) error_logger.error(target_ip) error_logger.error(mac) return messages.INTERNAL_SERVER_ERROR
async def http1(self): """ HTTP 1.1 connection handler """ # Handle requests while the connection stays reusable while self.keep_alive and self.stage is Stage.IDLE: self.init_for_request() # Wait for incoming bytes (in IDLE stage) if not self.recv_buffer: await self._receive_more() self.stage = Stage.REQUEST try: # Receive and handle a request self.response_func = self.http1_response_header await self.http1_request_header() self.stage = Stage.HANDLER self.request.conn_info = self.protocol.conn_info await self.protocol.request_handler(self.request) # Handler finished, response should've been sent if self.stage is Stage.HANDLER and not self.upgrade_websocket: raise ServerError("Handler produced no response") if self.stage is Stage.RESPONSE: await self.response.send(end_stream=True) except CancelledError: # Write an appropriate response before exiting if not self.protocol.transport: logger.info( f"Request: {self.request.method} {self.request.url} " "stopped. Transport is closed.") return e = self.exception or ServiceUnavailable("Cancelled") self.exception = None self.keep_alive = False await self.error_response(e) except Exception as e: # Write an error response await self.error_response(e) # Try to consume any remaining request body if self.request_body: if self.response and 200 <= self.response.status < 300: error_logger.error(f"{self.request} body not consumed.") # Limit the size because the handler may have set it infinite self.request_max_size = min(self.request_max_size, self.protocol.request_max_size) try: async for _ in self: pass except PayloadTooLarge: # We won't read the body and that may cause httpx and # tests to fail. This little delay allows clients to push # a small request into network buffers before we close the # socket, so that they are then able to read the response. await sleep(0.001) self.keep_alive = False # Clean up to free memory and for the next request if self.request: self.request.stream = None if self.response: self.response.stream = None
def main(): parser = SanicArgumentParser( prog="sanic", description=BASE_LOGO, formatter_class=lambda prog: RawTextHelpFormatter( prog, max_help_position=33), ) parser.add_argument( "-v", "--version", action="version", version=f"Sanic {__version__}; Routing {__routing_version__}", ) parser.add_argument( "--factory", action="store_true", help=("Treat app as an application factory, " "i.e. a () -> <Sanic app> callable"), ) parser.add_argument( "-s", "--simple", dest="simple", action="store_true", help="Run Sanic as a Simple Server (module arg should be a path)\n ", ) parser.add_argument( "-H", "--host", dest="host", type=str, default="127.0.0.1", help="Host address [default 127.0.0.1]", ) parser.add_argument( "-p", "--port", dest="port", type=int, default=8000, help="Port to serve on [default 8000]", ) parser.add_argument( "-u", "--unix", dest="unix", type=str, default="", help="location of unix socket\n ", ) parser.add_argument("--cert", dest="cert", type=str, help="Location of certificate for SSL") parser.add_argument("--key", dest="key", type=str, help="location of keyfile for SSL\n ") parser.add_bool_arguments("--access-logs", dest="access_log", help="display access logs") parser.add_argument( "-w", "--workers", dest="workers", type=int, default=1, help="number of worker processes [default 1]\n ", ) parser.add_argument("-d", "--debug", dest="debug", action="store_true") parser.add_argument( "-r", "--reload", "--auto-reload", dest="auto_reload", action="store_true", help="Watch source directory for file changes and reload on changes", ) parser.add_argument( "-R", "--reload-dir", dest="path", action="append", help="Extra directories to watch and reload on changes\n ", ) parser.add_argument( "module", help=("Path to your Sanic app. Example: path.to.server:app\n" "If running a Simple Server, path to directory to serve. " "Example: ./\n"), ) args = parser.parse_args() try: module_path = os.path.abspath(os.getcwd()) if module_path not in sys.path: sys.path.append(module_path) if args.simple: path = Path(args.module) app = create_simple_server(path) else: delimiter = ":" if ":" in args.module else "." module_name, app_name = args.module.rsplit(delimiter, 1) if app_name.endswith("()"): args.factory = True app_name = app_name[:-2] module = import_module(module_name) app = getattr(module, app_name, None) if args.factory: app = app() app_type_name = type(app).__name__ if not isinstance(app, Sanic): raise ValueError( f"Module is not a Sanic app, it is a {app_type_name}. " f"Perhaps you meant {args.module}.app?") if args.cert is not None or args.key is not None: ssl: Optional[Dict[str, Any]] = { "cert": args.cert, "key": args.key, } else: ssl = None kwargs = { "host": args.host, "port": args.port, "unix": args.unix, "workers": args.workers, "debug": args.debug, "access_log": args.access_log, "ssl": ssl, } if args.auto_reload: kwargs["auto_reload"] = True if args.path: if args.auto_reload or args.debug: kwargs["reload_dir"] = args.path else: error_logger.warning( "Ignoring '--reload-dir' since auto reloading was not " "enabled. If you would like to watch directories for " "changes, consider using --debug or --auto-reload.") app.run(**kwargs) except ImportError as e: if module_name.startswith(e.name): error_logger.error( f"No module named {e.name} found.\n" " Example File: project/sanic_server.py -> app\n" " Example Module: project.sanic_server.app") else: raise e except ValueError: error_logger.exception("Failed to run app")
def main(): parser = SanicArgumentParser( prog="sanic", description=BASE_LOGO, formatter_class=RawDescriptionHelpFormatter, ) parser.add_argument( "-H", "--host", dest="host", type=str, default="127.0.0.1", help="host address [default 127.0.0.1]", ) parser.add_argument( "-p", "--port", dest="port", type=int, default=8000, help="port to serve on [default 8000]", ) parser.add_argument( "-u", "--unix", dest="unix", type=str, default="", help="location of unix socket", ) parser.add_argument("--cert", dest="cert", type=str, help="location of certificate for SSL") parser.add_argument("--key", dest="key", type=str, help="location of keyfile for SSL.") parser.add_argument( "-w", "--workers", dest="workers", type=int, default=1, help="number of worker processes [default 1]", ) parser.add_argument("-d", "--debug", dest="debug", action="store_true") parser.add_argument( "-r", "--auto-reload", dest="auto_reload", action="store_true", help="Watch source directory for file changes and reload on changes", ) parser.add_argument( "-v", "--version", action="version", version=f"Sanic {__version__}; Routing {__routing_version__}", ) parser.add_bool_arguments("--access-logs", dest="access_log", help="display access logs") parser.add_argument( "module", help="path to your Sanic app. Example: path.to.server:app") args = parser.parse_args() try: module_path = os.path.abspath(os.getcwd()) if module_path not in sys.path: sys.path.append(module_path) delimiter = ":" if ":" in args.module else "." module_name, app_name = args.module.rsplit(delimiter, 1) module = import_module(module_name) app = getattr(module, app_name, None) app_name = type(app).__name__ if not isinstance(app, Sanic): raise ValueError( f"Module is not a Sanic app, it is a {app_name}. " f"Perhaps you meant {args.module}.app?") if args.cert is not None or args.key is not None: ssl: Optional[Dict[str, Any]] = { "cert": args.cert, "key": args.key, } else: ssl = None kwargs = { "host": args.host, "port": args.port, "unix": args.unix, "workers": args.workers, "debug": args.debug, "access_log": args.access_log, "ssl": ssl, } if args.auto_reload: kwargs["auto_reload"] = True app.run(**kwargs) except ImportError as e: if module_name.startswith(e.name): error_logger.error( f"No module named {e.name} found.\n" " Example File: project/sanic_server.py -> app\n" " Example Module: project.sanic_server.app") else: raise e except ValueError: error_logger.exception("Failed to run app")
async def after_response(request, response): try: if not db.is_closed(): db.close() except: error_logger.error()
def main(): parser = SanicArgumentParser( prog="sanic", description=BASE_LOGO, formatter_class=lambda prog: RawTextHelpFormatter( prog, max_help_position=33), ) parser.add_argument( "-v", "--version", action="version", version=f"Sanic {__version__}; Routing {__routing_version__}", ) parser.add_argument( "--factory", action="store_true", help=("Treat app as an application factory, " "i.e. a () -> <Sanic app> callable"), ) parser.add_argument( "-s", "--simple", dest="simple", action="store_true", help="Run Sanic as a Simple Server (module arg should be a path)\n ", ) parser.add_argument( "-H", "--host", dest="host", type=str, default="127.0.0.1", help="Host address [default 127.0.0.1]", ) parser.add_argument( "-p", "--port", dest="port", type=int, default=8000, help="Port to serve on [default 8000]", ) parser.add_argument( "-u", "--unix", dest="unix", type=str, default="", help="location of unix socket\n ", ) parser.add_argument( "--cert", dest="cert", type=str, help="Location of fullchain.pem, bundle.crt or equivalent", ) parser.add_argument( "--key", dest="key", type=str, help="Location of privkey.pem or equivalent .key file", ) parser.add_argument( "--tls", metavar="DIR", type=str, action="append", help="TLS certificate folder with fullchain.pem and privkey.pem\n" "May be specified multiple times to choose of multiple certificates", ) parser.add_argument( "--tls-strict-host", dest="tlshost", action="store_true", help="Only allow clients that send an SNI matching server certs\n ", ) parser.add_bool_arguments("--access-logs", dest="access_log", help="display access logs") parser.add_argument( "-w", "--workers", dest="workers", type=int, default=1, help="number of worker processes [default 1]\n ", ) parser.add_argument("-d", "--debug", dest="debug", action="store_true") parser.add_bool_arguments( "--noisy-exceptions", dest="noisy_exceptions", help="print stack traces for all exceptions", ) parser.add_argument( "-r", "--reload", "--auto-reload", dest="auto_reload", action="store_true", help="Watch source directory for file changes and reload on changes", ) parser.add_argument( "-R", "--reload-dir", dest="path", action="append", help="Extra directories to watch and reload on changes\n ", ) parser.add_argument( "module", help=("Path to your Sanic app. Example: path.to.server:app\n" "If running a Simple Server, path to directory to serve. " "Example: ./\n"), ) args = parser.parse_args() # Custom TLS mismatch handling for better diagnostics if ( # one of cert/key missing bool(args.cert) != bool(args.key) # new and old style args used together or args.tls and args.cert # strict host checking without certs would always fail or args.tlshost and not args.tls and not args.cert): parser.print_usage(sys.stderr) error_logger.error( "sanic: error: TLS certificates must be specified by either of:\n" " --cert certdir/fullchain.pem --key certdir/privkey.pem\n" " --tls certdir (equivalent to the above)") sys.exit(1) try: module_path = os.path.abspath(os.getcwd()) if module_path not in sys.path: sys.path.append(module_path) if args.simple: path = Path(args.module) app = create_simple_server(path) else: delimiter = ":" if ":" in args.module else "." module_name, app_name = args.module.rsplit(delimiter, 1) if app_name.endswith("()"): args.factory = True app_name = app_name[:-2] module = import_module(module_name) app = getattr(module, app_name, None) if args.factory: app = app() app_type_name = type(app).__name__ if not isinstance(app, Sanic): raise ValueError( f"Module is not a Sanic app, it is a {app_type_name}. " f"Perhaps you meant {args.module}.app?") ssl: Union[None, dict, str, list] = [] if args.tlshost: ssl.append(None) if args.cert is not None or args.key is not None: ssl.append(dict(cert=args.cert, key=args.key)) if args.tls: ssl += args.tls if not ssl: ssl = None elif len(ssl) == 1 and ssl[0] is not None: # Use only one cert, no TLSSelector. ssl = ssl[0] kwargs = { "host": args.host, "port": args.port, "unix": args.unix, "workers": args.workers, "debug": args.debug, "access_log": args.access_log, "ssl": ssl, "noisy_exceptions": args.noisy_exceptions, } if args.auto_reload: kwargs["auto_reload"] = True if args.path: if args.auto_reload or args.debug: kwargs["reload_dir"] = args.path else: error_logger.warning( "Ignoring '--reload-dir' since auto reloading was not " "enabled. If you would like to watch directories for " "changes, consider using --debug or --auto-reload.") app.run(**kwargs) except ImportError as e: if module_name.startswith(e.name): error_logger.error( f"No module named {e.name} found.\n" " Example File: project/sanic_server.py -> app\n" " Example Module: project.sanic_server.app") else: raise e except ValueError: error_logger.exception("Failed to run app")
def unknown_error(req, err): error_logger.error(err) error_logger.error(traceback.format_exc()) return sanic.response.raw(b'', 500)
def main(): parser = SanicArgumentParser( prog="sanic", description=BASE_LOGO, formatter_class=RawDescriptionHelpFormatter, ) parser.add_argument( "-H", "--host", dest="host", type=str, default="127.0.0.1", help="host address [default 127.0.0.1]", ) parser.add_argument( "-p", "--port", dest="port", type=int, default=8000, help="port to serve on [default 8000]", ) parser.add_argument( "-u", "--unix", dest="unix", type=str, default="", help="location of unix socket", ) parser.add_argument("--cert", dest="cert", type=str, help="location of certificate for SSL") parser.add_argument("--key", dest="key", type=str, help="location of keyfile for SSL.") parser.add_argument( "-w", "--workers", dest="workers", type=int, default=1, help="number of worker processes [default 1]", ) parser.add_argument("--debug", dest="debug", action="store_true") parser.add_bool_arguments("--access-logs", dest="access_log", help="display access logs") parser.add_argument( "-v", "--version", action="version", version=f"Sanic {__version__}", ) parser.add_argument( "module", help="path to your Sanic app. Example: path.to.server:app") args = parser.parse_args() try: module_path = os.path.abspath(os.getcwd()) if module_path not in sys.path: sys.path.append(module_path) if ":" in args.module: module_name, app_name = args.module.rsplit(":", 1) else: module_parts = args.module.split(".") module_name = ".".join(module_parts[:-1]) app_name = module_parts[-1] module = import_module(module_name) app = getattr(module, app_name, None) app_name = type(app).__name__ if not isinstance(app, Sanic): raise ValueError( f"Module is not a Sanic app, it is a {app_name}. " f"Perhaps you meant {args.module}.app?") if args.cert is not None or args.key is not None: ssl = { "cert": args.cert, "key": args.key, } # type: Optional[Dict[str, Any]] else: ssl = None app.run( host=args.host, port=args.port, unix=args.unix, workers=args.workers, debug=args.debug, access_log=args.access_log, ssl=ssl, ) except ImportError as e: error_logger.error(f"No module named {e.name} found.\n" f" Example File: project/sanic_server.py -> app\n" f" Example Module: project.sanic_server.app") except ValueError: error_logger.exception("Failed to run app")