# Request Methods Received JSON {Body} # Follow Thread https://github.com/encode/starlette/issues/493 async def firerecv(request): if request.method == 'GET': return PlainTextResponse("Received GET Method") if request.method == 'POST': body_bytes = await request.body() if body_bytes: json = await request.json() return JSONResponse(json) # print(json.dumps(data)) return PlainTextResponse("Received POST Method") routes = [ Route("/", endpoint=homepage), Route("/about", endpoint=about), Route("/fire", endpoint=firerecv, methods=['GET', 'POST']), Route("/users", endpoint=user), # Main Route Route("/users/{user_id:int}", endpoint=user), # Sub Route to Main Route Mount("/submex", routes=[ Route('/{username:str}', endpoint=submountex), Route('/', endpoint=submountex) ]) # Mounting Multiple SubRoutes after Main Route. ] app = Starlette(routes=routes)
from starlette.routing import Route, Mount from starlette.responses import JSONResponse from models import Tournament async def homepage(request): if request.method == 'POST': form = await request.form() await Tournament.create(name=form['name']) data = await Tournament.all() return JSONResponse([d.name for d in data]) routes = [Route('/', homepage, methods=['GET', 'POST'])]
from starlette.routing import Route, Router from ads.views import (ads_all, ad, ad_create, ad_edit, ad_delete, ad_images, upload, image_edit, image_delete, edit_upload, review_create, review_edit, review_delete, search, filter_search, maps) ads_routes = Router([ Route("/", endpoint=ads_all, methods=["GET", "POST"], name="ads_all"), Route("/create", endpoint=ad_create, methods=["GET", "POST"], name="ad_create"), Route("/edit/{id:int}", endpoint=ad_edit, methods=["GET", "POST"], name="ad_edit"), Route("/delete/{id:int}", endpoint=ad_delete, methods=["GET", "POST"], name="ad_delete"), Route("/image-edit/{id:int}", endpoint=image_edit, methods=["GET", "POST"], name="image_edit"), Route("/image-delete/{id:int}", endpoint=image_delete, methods=["POST"], name="image_delete"), Route("/edit-upload/{aid:int}", endpoint=edit_upload, methods=["POST"],
await ws.send_json({"msgtype": "pong"}) async def on_quit(self, ws, msg): await ws.send_json({"msgtype": "goodbye"}) await ws.close() async def on_exec(self, ws, msg): runtime = msg['runtime'] code = msg['code'] env = msg.get('env') or {} k = Kernel(ws, runtime) await k.execute(code, env) await ws.close() async def on_unknown_message(self, ws, msg): msgtype = msg.get("msgtype") await ws.send_json({ "msgtype": "error", "error": f"Unknown message type: {msgtype}", "msg": msg }) app = Starlette(routes=[ Route('/', home), WebSocketRoute("/livecode", LiveCode), Mount('/static', app=StaticFiles(directory=static_dir), name="static"), ])
await websocket.close() async def call_webhook(body: Dict, id: str, url: str): # background job to execute a webhook signature = make_signature(SECRET, json.dumps(body).encode()) headers = { "WebHook-ID": id, "WebHook-Signature": signature, "WebHook-Timestamp": f"{datetime.now(tz=timezone.utc).timestamp()}", } async with httpx.AsyncClient() as client: r = await client.post(url, json=body, headers=headers) try: body = r.json() except ValueError: body = r.text log.info(body) if (r.status_code // 100) > 3: raise HTTPException("Error, request failed") routes = [ Route("/healthz", health, methods=["GET"]), Route("/trigger", trigger, methods=["GET"]), Route("/webhook", incoming_webhook, methods=["GET", "POST"]), WebSocketRoute("/ws", websocket_endpoint), ] app = Starlette(debug=True, routes=routes)
template_dir = Path(__file__).parent.joinpath("static").resolve() TEMPLATES = Jinja2Templates(directory=[template_dir]) async def landing(request): """ Show a human-readable landing page when the base URL is accessed. """ meta = meta_values(str(request.url), 1, 1, more_data_available=False) major_version = __api_version__.split(".")[0] versioned_url = (f"{request.url}" if f"v{major_version}" in f"{request.url.path}" else f"{request.url}v{major_version}/") context = { "request": request, "request_url": request.url, "api_version": __api_version__, "implementation": meta.implementation, "versioned_url": versioned_url, "provider": meta.provider, "index_base_url": CONFIG.index_base_url, "endpoints": list(ENTRY_COLLECTIONS.keys()) + ["info"], } return TEMPLATES.TemplateResponse("landing_page.html", context) router = Router(routes=[Route("/", endpoint=landing)])
from typing import List, Optional from starlette.requests import Request from starlette.routing import Route, Mount from starlette.endpoints import HTTPEndpoint from starlette.responses import UJSONResponse from api.validators.members import MemberLoginValidator from infrastructures.logging import meteor_logman from packages.webargs import parse_requests class MemberLoginAPIResource(HTTPEndpoint): async def get(self, request: Request) -> UJSONResponse: return UJSONResponse({"path": "Members"}) @parse_requests(MemberLoginValidator()) async def post(self, request: Request, reqargs: dict) -> UJSONResponse: return UJSONResponse({"member_id": "MEM2019112613551501"}) member_auth_routes = Mount("/auth", routes=[Route("/login", MemberLoginAPIResource)])
body = await fetch(session, url) return UJSONResponse([body] + parse_chinese_name()) async def multiple_database_queries(request): seconds = 1.5 body_list = [] url = f'http://{GO_SLEEP_ADDRESS}/?seconds={seconds}' async with aiohttp.ClientSession(connector=_connector, connector_owner=False) as session: body = await fetch(session, url) body_list.append(body) url = f'http://{GO_SLEEP_ADDRESS}/?seconds={seconds}' async with aiohttp.ClientSession(connector=_connector, connector_owner=False) as session: body = await fetch(session, url) body_list.append(body) return UJSONResponse('\n'.join(body_list)) routes = [ Route('/single', single_database_query), Route('/multiple', multiple_database_queries), ] app = Starlette(routes=routes)
async def stream(scope, receive, send): message = await receive() camera = Camera() if message["type"] == "http.request": await send({ "type": "http.response.start", "status": 200, "headers": [[b"Content-Type", b"multipart/x-mixed-replace; boundary=frame"]], }) while True: async for frame in camera.frames(): data = b"".join([ b"--frame\r\n", b"Content-Type: image/jpeg\r\n\r\n", frame, b"\r\n", ]) await send({ "type": "http.response.body", "body": data, "more_body": True }) routes = [Route("/", endpoint=homepage), Mount("/stream/", stream)] app = Starlette(debug=True, routes=routes)
# can enhance the security of your web application # by enabling browser security policies. # more on https://secure.readthedocs.io/en/latest/headers.html secure_headers = SecureHeaders() async def index(request): results = "Home page" return templates.TemplateResponse("index.html", { "request": request, "results": results }) routes = [ Route("/", index), ] app = Starlette(debug=True, routes=routes) app.mount("/static", StaticFiles(directory="static"), name="static") app.mount("/accounts", accounts_routes) app.mount("/questions", questions_routes) app.add_middleware(AuthenticationMiddleware, backend=UserAuthentication()) app.add_middleware(SessionMiddleware, secret_key=SECRET_KEY) # middleware for secure headers @app.middleware("http") async def set_secure_headers(request, call_next): response = await call_next(request) secure_headers.starlette(response)
from fastapi import Depends, FastAPI from fastapi.middleware.cors import CORSMiddleware from piccolo.engine import engine_finder from piccolo_admin.endpoints import create_admin from piccolo_api.crud.endpoints import PiccoloCRUD from piccolo_api.fastapi.endpoints import FastAPIKwargs, FastAPIWrapper from starlette.routing import Mount, Route from accounts.endpoints import oauth2_scheme, router from forum.tables import Category, Reply, Topic from home.endpoints import HomeEndpoint app = FastAPI( title="Simple headless forum", routes=[ Route("/", HomeEndpoint), Mount( "/admin/", create_admin( tables=[Category, Reply, Topic], # Required when running under HTTPS: # allowed_hosts=['my_site.com'] ), ), ], ) origins = [ "http://localhost:8080", ]
async def delete_version(request: Request, *args, **kwargs): form_data = await request.form() logger.info(f'Processing form data {form_data}') if not form_data: return RedirectResponse('/') documentation_version = schemas.BasePackageVersion( name=form_data['packageName'], version=form_data['version']) methods.delete_version(documentation_version, provided_permissions=request.auth.scopes) return RedirectResponse(url='/', status_code=303) @authenticator.auth_required() async def delete_package(request: Request, *args, **kwargs): form_data = await request.form() logger.info(f'Processing form data {form_data}') if not form_data: return RedirectResponse('/') package = schemas.BasePackage(name=form_data['packageName']) methods.delete_package(package, provided_permissions=request.auth.scopes) return RedirectResponse(url='/', status_code=303) routes = [ Route("/", endpoint=index, methods=['GET', 'POST']), Route("/packages/", endpoint=index, methods=['GET']), Route("/_upload", endpoint=upload, methods=['POST']), Route("/_delete/package", endpoint=delete_package, methods=['POST']), Route("/_delete/version", endpoint=delete_version, methods=['POST']) ]
model = query_params["model"] models = { "sample": search_sample, "project": search_project, "session": search_session, } if model == "all": sql_fn = search_total query_res = db.exec_sql_query(fn=sql_fn, params=params) json_res = [dict(model=x, data=y) for x, y in query_res] json_res.reverse() return JSONResponse(json_res) else: for key, value in models.items(): if model == key: sql_fn = value schema = getattr(db.interface, key)(many=True) query_res = db.exec_sql_query(fn=sql_fn, params=params) json_res = [dict(r) for r in query_res] return APIResponse(json_res, total_count=len(json_res), schema=schema) OpenSearchAPI = Router( [Route("/query", endpoint=OpenSearchEndpoint, methods=["GET"])])
def test_read_only(self): app = Router(routes=[Route("/", register(read_only=True))]) client = TestClient(app) response = client.post("/") self.assertTrue(response.status_code, 405) self.assertTrue(response.content, "Running in read only mode.")
"""Generate text and return the parsed result as a dict.""" if request.method == 'GET': params = request.query_params elif request.method == 'POST': params = await request.json() elif request.method == 'HEAD': return JSONResponse({'text': ''}, headers=response_header) logging.info(params) return JSONResponse(parse_text(generate_text(params)), headers=response_header) async def homepage(request): """Return HTML homepage.""" return templates.TemplateResponse('index.html', {'request': request}) routes = [ Route("/", endpoint=homepage), Route("/generate", endpoint=generate, methods=["GET", "POST"]), ] app = Starlette(routes=routes, debug=True) app.mount('/static', StaticFiles(directory='app/static')) templates = Jinja2Templates(directory='app/templates') if __name__ == "__main__": uvicorn.run(app, host='0.0.0.0', port=int(os.environ.get('PORT', 5000)), log_level="info")
url = request.url_for("redirect2") return RedirectResponse(url) async def redirect2(request): url = request.url_for("redirect3") return RedirectResponse(url) async def redirect3(request): return JSONResponse({"hello": "world"}) routes = [ Route("/", echo_request, methods=["GET", "DELETE", "OPTIONS", "POST", "PUT", "PATCH"]), Route("/echo_form_data", echo_form_data, methods=["POST", "PUT", "PATCH"]), Route("/echo_json", echo_json, methods=["POST", "PUT", "PATCH"]), Route("/echo_headers", echo_headers), Route("/redirect1", redirect1, name="redirect1"), Route("/redirect2", redirect2, name="redirect2"), Route("/redirect3", redirect3, name="redirect3"), ] app = Starlette(routes=routes) @pytest.fixture async def server(): config = Config(app=app, lifespan="off")
@dataclasses.dataclass class RegisterUserInput: service_name: str user: t.Dict @classmethod async def parse(cls, a: Accessor) -> RegisterUserInput: # check header # check queries name = a.paths["name"] payload = t.cast(t.Mapping[str, t.Any], await a.jsondata()) user = UserSchema().load(payload) return RegisterUserInput( service_name=name, user=user, ) async def register(request: Request): input: RegisterUserInput = await parse(RegisterUserInput.parse, request) return JSONResponse(UserSchema().dump(input.user)) app = Starlette( debug=True, routes=[ Route("/services/{name}/users", register, methods=["POST"]), ], )
def users(request): return Response("All users", media_type="text/plain") def user(request): content = "User " + request.path_params["username"] return Response(content, media_type="text/plain") def staticfiles(request): return Response("xxxxx", media_type="image/png") app = Router( [ Route("/", endpoint=homepage, methods=["GET"]), Mount( "/users", app=Router( [Route("", endpoint=users), Route("/{username}", endpoint=user)] ), ), Mount("/static", app=staticfiles), ] ) @app.route("/func") def func_homepage(request): return Response("Hello, world!", media_type="text/plain")
from app.endpoints.home import Home from starlette.routing import Route routes = [Route("/", endpoint=Home, methods=["GET"])]
def test_cors_allow_origin_regex(test_client_factory): def homepage(request): return PlainTextResponse("Homepage", status_code=200) app = Starlette( routes=[Route("/", endpoint=homepage)], middleware=[ Middleware( CORSMiddleware, allow_headers=["X-Example", "Content-Type"], allow_origin_regex="https://.*", allow_credentials=True, ) ], ) client = test_client_factory(app) # Test standard response headers = {"Origin": "https://example.org"} response = client.get("/", headers=headers) assert response.status_code == 200 assert response.text == "Homepage" assert response.headers["access-control-allow-origin"] == "https://example.org" assert response.headers["access-control-allow-credentials"] == "true" # Test standard credentialed response headers = {"Origin": "https://example.org", "Cookie": "star_cookie=sugar"} response = client.get("/", headers=headers) assert response.status_code == 200 assert response.text == "Homepage" assert response.headers["access-control-allow-origin"] == "https://example.org" assert response.headers["access-control-allow-credentials"] == "true" # Test disallowed standard response # Note that enforcement is a browser concern. The disallowed-ness is reflected # in the lack of an "access-control-allow-origin" header in the response. headers = {"Origin": "http://example.org"} response = client.get("/", headers=headers) assert response.status_code == 200 assert response.text == "Homepage" assert "access-control-allow-origin" not in response.headers # Test pre-flight response headers = { "Origin": "https://another.com", "Access-Control-Request-Method": "GET", "Access-Control-Request-Headers": "X-Example, content-type", } response = client.options("/", headers=headers) assert response.status_code == 200 assert response.text == "OK" assert response.headers["access-control-allow-origin"] == "https://another.com" assert response.headers["access-control-allow-headers"] == ( "Accept, Accept-Language, Content-Language, Content-Type, X-Example" ) assert response.headers["access-control-allow-credentials"] == "true" # Test disallowed pre-flight response headers = { "Origin": "http://another.com", "Access-Control-Request-Method": "GET", "Access-Control-Request-Headers": "X-Example", } response = client.options("/", headers=headers) assert response.status_code == 400 assert response.text == "Disallowed CORS origin" assert "access-control-allow-origin" not in response.headers
async def kek(req): return JSONResponse(f"kek") async def horde(req): return PlainTextResponse(f"ты прав!") async def aliance(req): username = req.path_params['username'] return JSONResponse(f"Сам ты, {username}, сосед!") routes = [ Route("/", endpoint=homepage), Route("/about", endpoint=about), Route('/users/{username}', user), Route('/kek', kek, methods=["POST"]), Mount('/lol', routes=[ Route('/ordasosed', horde), Route('/alyanssosed/{username}', aliance) ]) ] HTML_404_PAGE = "not found" HTML_500_PAGE = "server error" async def not_found(request, exc):
def add_doc_route( app: Starlette, prefix: str = "/", pin_code: str = "", title: str = "Pait Doc", open_api_tag_list: Optional[List[Dict[str, Any]]] = None, ) -> None: if pin_code: logging.info(f"doc route start pin code:{pin_code}") def _get_request_pin_code(request: Request) -> Optional[str]: r_pin_code: Optional[str] = request.query_params.get("pin_code", None) if pin_code: if r_pin_code != pin_code: raise HTTPException( status_code=404, detail= ("The requested URL was not found on the server. If you entered" " the URL manually please check your spelling and try again." ), ) return r_pin_code def _get_open_json_url(request: Request) -> str: r_pin_code: Optional[str] = _get_request_pin_code(request) openapi_json_url: str = ( f"http://{request.url.hostname}:{request.url.port}{'/'.join(request.url.path.split('/')[:-1])}/openapi.json" ) if r_pin_code: openapi_json_url += f"?pin_code={r_pin_code}" return openapi_json_url def get_redoc_html(request: Request) -> HTMLResponse: return HTMLResponse(_get_redoc_html(_get_open_json_url(request), title)) def get_swagger_ui_html(request: Request) -> HTMLResponse: return HTMLResponse( _get_swagger_ui_html(_get_open_json_url(request), title)) def openapi_route(request: Request) -> JSONResponse: _get_request_pin_code(request) pait_dict: Dict[str, PaitCoreModel] = load_app(request.app) pait_openapi: PaitOpenApi = PaitOpenApi( pait_dict, title=title, open_api_server_list=[{ "url": f"http://{request.url.hostname}:{request.url.port}", "description": "" }], open_api_tag_list=open_api_tag_list, ) return JSONResponse(pait_openapi.open_api_dict) route: Mount = Mount( prefix, name="api doc", routes=[ Route("/redoc", get_redoc_html, methods=["GET"]), Route("/swagger", get_swagger_ui_html, methods=["GET"]), Route("/openapi.json", openapi_route, methods=["GET"]), ], ) app.routes.append(route)
def __init__(self, enablePiCamera=False, stabilize=False, source=None, camera_num=0, stream_mode=False, backend=0, colorspace=None, resolution=(640, 480), framerate=25, logging=False, time_delay=0, **options): """ This constructor method initializes the object state and attributes of the WebGear_RTC class. Parameters: enablePiCamera (bool): provide access to PiGear(if True) or CamGear(if False) APIs respectively. stabilize (bool): enable access to Stabilizer Class for stabilizing frames. camera_num (int): selects the camera module index which will be used as Rpi source. resolution (tuple): sets the resolution (i.e. `(width,height)`) of the Rpi source. framerate (int/float): sets the framerate of the Rpi source. source (based on input): defines the source for the input stream. stream_mode (bool): controls the exclusive YouTube Mode. backend (int): selects the backend for OpenCV's VideoCapture class. colorspace (str): selects the colorspace of the input stream. logging (bool): enables/disables logging. time_delay (int): time delay (in sec) before start reading the frames. options (dict): provides ability to alter Tweak Parameters of WebGear_RTC, CamGear, PiGear & Stabilizer. """ # raise error(s) for critical Class imports import_dependency_safe("starlette" if starlette is None else "") import_dependency_safe("aiortc" if aiortc is None else "") # initialize global params self.__logging = logging custom_data_location = "" # path to save data-files to custom location data_path = "" # path to WebGear_RTC data-files overwrite_default = False self.__relay = None # act as broadcaster # reformat dictionary options = {str(k).strip(): v for k, v in options.items()} # assign values to global variables if specified and valid if options: if "custom_data_location" in options: value = options["custom_data_location"] if isinstance(value, str): assert os.access( value, os.W_OK ), "[WebGear_RTC:ERROR] :: Permission Denied!, cannot write WebGear_RTC data-files to '{}' directory!".format( value) assert os.path.isdir( os.path.abspath(value) ), "[WebGear_RTC:ERROR] :: `custom_data_location` value must be the path to a directory and not to a file!" custom_data_location = os.path.abspath(value) else: logger.warning( "Skipped invalid `custom_data_location` value!") del options["custom_data_location"] # clean if "overwrite_default_files" in options: value = options["overwrite_default_files"] if isinstance(value, bool): overwrite_default = value else: logger.warning( "Skipped invalid `overwrite_default_files` value!") del options["overwrite_default_files"] # clean if "enable_live_broadcast" in options: value = options["enable_live_broadcast"] if isinstance(value, bool): if value: self.__relay = MediaRelay() options[ "enable_infinite_frames"] = True # enforce infinite frames logger.critical( "Enabled live broadcasting for Peer connection(s)." ) else: None else: logger.warning( "Skipped invalid `enable_live_broadcast` value!") del options["enable_live_broadcast"] # clean # check if custom certificates path is specified if custom_data_location: data_path = generate_webdata( custom_data_location, c_name="webgear_rtc", overwrite_default=overwrite_default, logging=logging, ) else: # otherwise generate suitable path data_path = generate_webdata( os.path.join(expanduser("~"), ".vidgear"), c_name="webgear_rtc", overwrite_default=overwrite_default, logging=logging, ) # log it self.__logging and logger.debug( "`{}` is the default location for saving WebGear_RTC data-files.". format(data_path)) # define Jinja2 templates handler self.__templates = Jinja2Templates( directory="{}/templates".format(data_path)) # define custom exception handlers self.__exception_handlers = { 404: self.__not_found, 500: self.__server_error } # define routing tables self.routes = [ Route("/", endpoint=self.__homepage), Route("/offer", self.__offer, methods=["GET", "POST"]), Mount( "/static", app=StaticFiles(directory="{}/static".format(data_path)), name="static", ), ] # define middleware support self.middleware = [] # Handle RTC video server if source is None: self.config = {"server": None} self.__default_rtc_server = None self.__logging and logger.warning("Given source is of NoneType!") else: # Handle video source self.__default_rtc_server = RTC_VideoServer( enablePiCamera=enablePiCamera, stabilize=stabilize, source=source, camera_num=camera_num, stream_mode=stream_mode, backend=backend, colorspace=colorspace, resolution=resolution, framerate=framerate, logging=logging, time_delay=time_delay, **options) # define default frame generator in configuration self.config = {"server": self.__default_rtc_server} # add exclusive reset connection node self.routes.append( Route("/close_connection", self.__reset_connections, methods=["POST"])) # copying original routing tables for further validation self.__rt_org_copy = self.routes[:] # collects peer RTC connections self.__pcs = set()
from starlette.routing import Route, Mount from source import views from source.staticfiles import statics from source.auth.routes import routes as auth_routes from source.users.routes import routes as users_routes from source.resources.routes import routes as resources_routes routes = [ Route("/", views.index, name="home"), Route("/about", views.about, name="about"), Route("/search", views.search, name="search"), Route("/welcome", views.welcome, name="welcome"), Route("/video", views.video, name="video"), Route("/image", views.image, name="image"), Route("/clear-session", views.clear, name="clear-session"), Mount("/resources", routes=resources_routes), Mount("/users", routes=users_routes), Mount("/auth", routes=auth_routes), Mount("/static", statics, name="static"), ]
with instrument('awaiting_task'): await asyncio.sleep(0.1) return "done" task = asyncio.create_task(awaiting_task()) await task return PlainTextResponse("Awaited task.") async def error(request, exc): # Always raise exceptions, rather than convert them into pages raise exc app = Starlette(routes=[ Route("/", home), Route("/hello/", HelloEndpoint), Route("/crash/", crash), Route("/background-jobs/", background_jobs), Route("/await-task/", await_task), ], exception_handlers={ 500: error, }) # Installation instructions Config.set( key=os.environ["SCOUT_KEY"], name="Test Starlette App", monitor=True, )
media_type=media_type, ) else: ctx = {"request": request, "form": form} return templates.TemplateResponse("index.html", ctx) async def http_exception( request: Request, e: HTTPException ) -> Jinja2Templates.TemplateResponse: ctx = { "request": request, "title": e.status_code, "status_code": e.status_code, "message": e.detail, } return templates.TemplateResponse("exceptions.html", ctx) routes = [ Route("/", Index, name="index"), Mount("/static", app=StaticFiles(directory="static"), name="static"), ] exception_handlers = {HTTPException: http_exception} app = Starlette(routes=routes, exception_handlers=exception_handlers)
from starlette.routing import Route from views import homepage, about routes = [ Route("/", endpoint=homepage), Route("/home", endpoint=homepage), Route("/about", endpoint=about), ]
from starlette.applications import Starlette from starlette.responses import JSONResponse, Response from starlette.routing import Route from datetime import datetime async def homepage(request): now = datetime.now() ts = now.isoformat() return JSONResponse({'hello': 'world', 'ts': ts}) app = Starlette(debug=True, routes=[ Route('/', homepage), ]) # async def app(scope, receive, send): # #assert scope['type'] == 'http' # response = Response('Hello, world!', media_type='text/plain') # await response(scope, receive, send)
raise HTTPException(status_code=406) def not_modified(request): raise HTTPException(status_code=304) class HandledExcAfterResponse: async def __call__(self, scope, receive, send): response = PlainTextResponse("OK", status_code=200) await response(scope, receive, send) raise HTTPException(status_code=406) router = Router(routes=[ Route("/runtime_error", endpoint=raise_runtime_error), Route("/not_acceptable", endpoint=not_acceptable), Route("/not_modified", endpoint=not_modified), Route("/handled_exc_after_response", endpoint=HandledExcAfterResponse()), WebSocketRoute("/runtime_error", endpoint=raise_runtime_error), ]) app = ExceptionMiddleware(router) @pytest.fixture def client(test_client_factory): with test_client_factory(app) as client: yield client
def startup(): print("Ready to go") # add tasks on startup scheduled_tasks.start_jobs() def shutdown(): # remove scheduled tasks on shutdown scheduled_tasks.shut_down_schedule() print("and we are done") routes = [ Route("/", homepage), Route("/math", math_page), # WebSocketRoute("/ws", websocket_endpoint), # Mount("/static", StaticFiles(directory="static")), ] app = Starlette(debug=True, routes=routes, on_startup=[startup], on_shutdown=[shutdown]) if __name__ == "__main__": import uvicorn # APScheduler is limited to running on a single worker at this this time (v3.6.3) # see https://github.com/agronholm/apscheduler/issues/218#issuecomment-559951948 for more information