def test_if_static_dir_is_none_then_no_assets_served(tmpdir_factory): static_dir = tmpdir_factory.mktemp("static") _create_asset(static_dir) api = API(static_dir=None) assert api.client.get(f"/static/{FILE_DIR}/{FILE_NAME}").status_code == 404
def test_static_root_defaults_to_static_dir(tmpdir_factory): static_dir = tmpdir_factory.mktemp("foo") _create_asset(static_dir) api = API(static_dir=str(static_dir), static_root=None) response = api.client.get(f"{static_dir}/{FILE_DIR}/{FILE_NAME}") assert response.status_code == 200
def test_if_host_not_allowed_then_400(): api = API(allowed_hosts=["example.com"]) @api.route("/") async def index(req, res): pass response = api.client.get("/") assert response.status_code == 400
def test_assets_are_served_at_static_by_default(tmpdir_factory): static_dir = tmpdir_factory.mktemp("static") _create_asset(static_dir) api = API(static_dir=str(static_dir)) response = api.client.get(f"/static/{FILE_DIR}/{FILE_NAME}") assert response.status_code == 200 assert response.text == FILE_CONTENTS
def test_customize_static_root(tmpdir_factory): static_dir = tmpdir_factory.mktemp("static") _create_asset(static_dir) api = API(static_dir=str(static_dir), static_root="assets") assert api.client.get(f"/static/{FILE_DIR}/{FILE_NAME}").status_code == 404 response = api.client.get(f"/assets/{FILE_DIR}/{FILE_NAME}") assert response.status_code == 200 assert response.text == FILE_CONTENTS
def test_if_gzip_enabled_then_response_is_compressed(): api = API(enable_gzip=True, gzip_min_size=0) @api.route("/") async def index(req, res): pass response = api.client.get("/", headers={"Accept-Encoding": "gzip"}) assert response.status_code == 200 assert response.headers["content-encoding"] == "gzip"
def test_mount_extra_static_files_dirs(tmpdir_factory): static_dir = tmpdir_factory.mktemp("staticfiles") _create_asset(static_dir) api = API(static_dir=None) api.mount("assets", static(str(static_dir))) response = api.client.get(f"/assets/{FILE_DIR}/{FILE_NAME}") assert response.status_code == 200 assert response.text == FILE_CONTENTS
def test_if_hsts_enabled_and_request_is_on_http_then_redirects_to_https(): api = API(enable_hsts=True) @api.route("/") async def index(req, res): pass response = api.client.get("/", allow_redirects=False) assert response.status_code == 301 assert response.headers["location"] == "https://testserver/"
def test_if_asgi_middleware_is_applied(): api = API(enable_gzip=False) api.add_asgi_middleware(GZipMiddleware, minimum_size=0) @api.route("/") async def index(req, res): pass response = api.client.get("/", headers={"Accept-Encoding": "gzip"}) assert response.status_code == 200 assert response.headers["content-encoding"] == "gzip"
def test_if_media_type_not_supported_then_setting_it_raises_error(api: API): foo_type = "application/foo" with pytest.raises(UnsupportedMediaType) as ctx: api.media_type = foo_type assert foo_type in str(ctx.value) with pytest.raises(UnsupportedMediaType) as ctx: API(media_type="application/foo") assert foo_type in str(ctx.value)
def test_no_allowed_origins_by_default(): api = API(enable_cors=True) @api.route("/") async def index(req, res): pass response = api.client.options( "/", headers={ "origin": "foobar.com", "access-control-request-method": "GET", }, ) assert response.status_code == 400
def test_if_method_not_in_allow_methods_then_400(): api = API( enable_cors=True, cors_config={ "allow_origins": ["foobar.com"], "allow_methods": ["POST"], }, ) @api.route("/") async def index(req, res): pass response = api.client.options( "/", headers={ "origin": "foobar.com", "access-control-request-method": "GET", }, ) assert response.status_code == 400
# api.py from bocadillo import API api = API() clients = set() history = [] @api.websocket_route("/chat", value_type="json") async def chat(ws): async with ws: # Register new client print("New client:", ws) clients.add(ws) # Send history of messages for message in history: await ws.send(message) try: # Broadcast new messages to all connected clients async for message in ws: print("Received:", message) history.append(message) if message["type"] == "message": for client in clients: await client.send(message) finally: # Make sure we unregister the client in case of unexpected errors. # For example, Safari seems to improperly close WebSockets when
def test_if_static_dir_does_not_exist_then_no_files_mounted(): with pytest.warns(None) as record: API(static_dir="foo") assert len(record) == 0
def api(): return API()
def test_can_specify_media_type_when_creating_the_api_object(): API(media_type=Media.PLAIN_TEXT)
def test_if_media_type_not_supported_then_passing_it_raises_error( api: API, foo_type): with pytest.raises(UnsupportedMediaType) as ctx: API(media_type=foo_type) assert foo_type in str(ctx.value)
# HTTP error responses! raise HTTPError(400, detail="Invalid JSON") # NOTE: you're free to integrate a third-party # validation library such as Marshmallow or jsonschema. for field in "name", "teacher": if field not in data: raise HTTPError(400, detail=f"{field} is a required field") # Now, let's assemble the actual application, shall we? api = API( # Built-in CORS, HSTS and GZip! enable_cors=True, enable_hsts=False, # the default enable_gzip=True, gzip_min_size=1024, # the default ) # Register the token middleware. api.add_middleware(TokenMiddleware) # Instanciate helper backends. storage = Storage() analytics = Analytics() # Routes! Views! Jinja templates! Static files! @api.route("/") async def index(req, res):
def test_can_specify_media_type_when_creating_the_api_object(): API(media_type=CONTENT_TYPE.JSON)