Exemplo n.º 1
0
    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)
Exemplo n.º 2
0
    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")
Exemplo n.º 3
0
    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()
Exemplo n.º 4
0
    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
Exemplo n.º 5
0
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
Exemplo n.º 6
0
 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)
Exemplo n.º 7
0
    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
Exemplo n.º 8
0
    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))
Exemplo n.º 9
0
    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
Exemplo n.º 10
0
    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
                ...
Exemplo n.º 11
0
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
Exemplo n.º 12
0
    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
Exemplo n.º 13
0
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")
Exemplo n.º 14
0
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")
Exemplo n.º 15
0
async def after_response(request, response):
    try:
        if not db.is_closed():
            db.close()
    except:
        error_logger.error()
Exemplo n.º 16
0
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")
Exemplo n.º 17
0
 def unknown_error(req, err):
     error_logger.error(err)
     error_logger.error(traceback.format_exc())
     return sanic.response.raw(b'', 500)
Exemplo n.º 18
0
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")