The little ASGI framework that shines. ?

Overview

starlette

The little ASGI framework that shines.

Build Status Package version


Documentation: https://www.starlette.io/

Community: https://discuss.encode.io/c/starlette


Starlette

Starlette is a lightweight ASGI framework/toolkit, which is ideal for building high performance asyncio services.

It is production-ready, and gives you the following:

  • Seriously impressive performance.
  • WebSocket support.
  • GraphQL support.
  • In-process background tasks.
  • Startup and shutdown events.
  • Test client built on requests.
  • CORS, GZip, Static Files, Streaming responses.
  • Session and Cookie support.
  • 100% test coverage.
  • 100% type annotated codebase.
  • Zero hard dependencies.

Requirements

Python 3.6+

Installation

$ pip3 install starlette

You'll also want to install an ASGI server, such as uvicorn, daphne, or hypercorn.

$ pip3 install uvicorn

Example

example.py:

from starlette.applications import Starlette
from starlette.responses import JSONResponse
from starlette.routing import Route


async def homepage(request):
    return JSONResponse({'hello': 'world'})

routes = [
    Route("/", endpoint=homepage)
]

app = Starlette(debug=True, routes=routes)

Then run the application using Uvicorn:

$ uvicorn example:app

For a more complete example, see encode/starlette-example.

Dependencies

Starlette does not have any hard dependencies, but the following are optional:

  • requests - Required if you want to use the TestClient.
  • aiofiles - Required if you want to use FileResponse or StaticFiles.
  • jinja2 - Required if you want to use Jinja2Templates.
  • python-multipart - Required if you want to support form parsing, with request.form().
  • itsdangerous - Required for SessionMiddleware support.
  • pyyaml - Required for SchemaGenerator support.
  • graphene - Required for GraphQLApp support.

You can install all of these with pip3 install starlette[full].

Framework or Toolkit

Starlette is designed to be used either as a complete framework, or as an ASGI toolkit. You can use any of its components independently.

from starlette.responses import PlainTextResponse


async def app(scope, receive, send):
    assert scope['type'] == 'http'
    response = PlainTextResponse('Hello, world!')
    await response(scope, receive, send)

Run the app application in example.py:

$ uvicorn example:app
INFO: Started server process [11509]
INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)

Run uvicorn with --reload to enable auto-reloading on code changes.

Modularity

The modularity that Starlette is designed on promotes building re-usable components that can be shared between any ASGI framework. This should enable an ecosystem of shared middleware and mountable applications.

The clean API separation also means it's easier to understand each component in isolation.

Performance

Independent TechEmpower benchmarks show Starlette applications running under Uvicorn as one of the fastest Python frameworks available. (*)

For high throughput loads you should:

  • Run using gunicorn using the uvicorn worker class.
  • Use one or two workers per-CPU core. (You might need to experiment with this.)
  • Disable access logging.

Eg.

gunicorn -w 4 -k uvicorn.workers.UvicornWorker --log-level warning example:app

Several of the ASGI servers also have pure Python implementations available, so you can also run under PyPy if your application code has parts that are CPU constrained.

Either programatically:

uvicorn.run(..., http='h11', loop='asyncio')

Or using Gunicorn:

gunicorn -k uvicorn.workers.UvicornH11Worker ...

⭐️

Starlette is BSD licensed code. Designed & built in Brighton, England.

Comments
  • Background tasks don't work with middleware that subclasses `BaseHTTPMiddleware`

    Background tasks don't work with middleware that subclasses `BaseHTTPMiddleware`

    When using background tasks with middleware, requests are not processed until the background task has finished.

    1. Use the example below
    2. Make several requests in a row - works as expected
    3. Uncomment app.add_middleware(TransparentMiddleware) and re-run
    4. Make several requests in a row - subsequent ones are not processed until the 10 second sleep has finished (the first request returns before then though).

    The same behaviour occurs with asyncio.sleep (async) and time.sleep (sync, run in threadpool)

    import asyncio
    import uvicorn
    from starlette.applications import Starlette
    from starlette.middleware.base import BaseHTTPMiddleware
    from starlette.background import BackgroundTask
    from starlette.responses import JSONResponse
    
    
    class TransparentMiddleware(BaseHTTPMiddleware):
        async def dispatch(self, request, call_next):
            # simple middleware that does absolutely nothing
            response = await call_next(request)
            return response
    
    
    app = Starlette(debug=True)
    # uncomment to break
    # app.add_middleware(TransparentMiddleware)
    
    
    @app.route("/")
    async def test(_):
        task = BackgroundTask(asyncio.sleep, 10)
        return JSONResponse("hello", background=task)
    
    
    if __name__ == '__main__':
        uvicorn.run(app)
    
    opened by retnikt 42
  • anyio integration

    anyio integration

    Fixes: #811

    This adds support for asyncio and trio by leveraging anyio and a little more structured concurrency in spots.

    Things to do yet:

    • [x] 100% tests passing (there's one failing test at the moment)
    • [x] TestClient rewritten for anyio, probably with portals.
    • [x] anyio 3.0 release

    This adds a hard dependency for starlette, which didn't exist before, and was a selling point. In my opinion, the benefit is worth it. It would be great to use starlette with either uvicorn or hypercorn using Trio.

    This also removes the need for aiofiles which is gained for free with anyio.

    Some drawbacks are that the other integrations such as graphql are only currently compatible with asyncio. But, this does not make those integrations incompatible. It does give users the ability to use trio without them, and maybe they can be ported in the future as well.

    I created a branch for framework benchmarks here: https://github.com/uSpike/FrameworkBenchmarks/tree/starlette-anyio

    See results: https://www.techempower.com/benchmarks/#section=test&shareid=c92a1338-0058-486c-9e47-c92ec4710b6a&hw=ph&test=query&a=2

    There is a performance penalty to using anyio. The weighted composite score is 173 vs 165, so a 4.5% drop in performance.

    opened by uSpike 39
  • Server Sent Events

    Server Sent Events

    Helpers for sending SSE event streams over HTTP connections.

    Related resources:

    • https://github.com/encode/uvicorn/commit/07c6c18945ab4f4167118e717e197adce3aee3da#r29630623
    • https://github.com/aio-libs/aiohttp-sse
    feature 
    opened by tomchristie 32
  • Fixes Request.json() Hangs Forever

    Fixes Request.json() Hangs Forever

    This fixes #847 by using the Request scope to store consumed stream data so that new instances of Request can access the Request stream content. Previously await Request(...).json() followed by another await Request(...).json() would hang forever because the receive stream was exhausted and await receive() doesn't timeout after message {"more_body": False} is received. This PR is focused only on enabling Request.body(), Request.form() and Request.json() to return the cached data as originally intended and does not address the issue of await receive() hanging forever inside of Request.stream()

    bug 
    opened by nikordaris 29
  • Caching backends

    Caching backends

    Hello! I think it would be interesting having a section in Starlette docs documenting how to use caching as this is something you end up doing typically for lots of services.

    I'm the maintainer of aiocache which is a caching framework agnostic to any http framework. I could write docs about things like:

    • how to use aiocache with starlette for caching endpoints
    • how to write configuration for caching and load it when starting a Starlette app

    Any other thing you could think of you usually do when setting caching for your app. Also happy to receive comments, issues and PRs if you think there is anything missing to integrate nicely with Starlette :).

    Would you be interested on me providing a PR documenting that? A new section called "Caching" in https://www.starlette.io/ maybe?

    feature 
    opened by argaen 28
  • Add pluggable session backends

    Add pluggable session backends

    This PR adds pluggable session backends and ships default InMemoryBackend, CookieBackend implementations.

    solves: #284

    The API of SessionMiddleware remains the same. It only receives new optional backend argument. The default value for this argument is CookieBackend so it has to be fully compatible with previous version.

    Here I also add a new test dependency pytest-asyncio.

    Usage example:

    from starlette.applications import Starlette
    from starlette.middleware.sessions import SessionMiddleware
    from starlette.sessions import CookieBackend
    
    backend = CookieBackend()
    
    app = Starlette()
    app.add_middleware(SessionMiddleware, backend=backend)
    

    API

    class MyCustomBackend(SessionBackend):
        async def read(self, session_id: str) -> Optional[str]: ...
    
        async def write(self, session_id: str, data: str) -> str: ...
    
        async def remove(self, session_id: str): ...
    

    write returns session_id to make it possible to use cookie backends as they don't persist data anywhere and their data is an ID.

    remove - currently unused but they may be used by logout handler.

    Do I need to add session_backend to scope? We need some API to invalidate session on logout.

    UPD: If you need this code please use this repository alex-oleshkevich/starsessions. There you will find a pip-installable package.

    feature 
    opened by alex-oleshkevich 26
  • feat: Add route-level middleware

    feat: Add route-level middleware

    In case you reconsider https://github.com/encode/starlette/issues/685#issuecomment-550240999 @tomchristie

    I think this would be a useful feature. I often see middleware parameters that are "a regex pattern to match routes" because the middleware has to determine what routes to interact with before routing is done. Here and here are two examples. This also closes https://github.com/tiangolo/fastapi/issues/1174

    Aside from being a pain to build some complex regex, there are performance implications: imagine (in the absurd scenario) that you have 100 endpoints and 100 middleware, but each middleware applies only to 1 endpoint. Now you have 99 middleware executing and doing regex matching when they could have just been bypassed to begin with if they executed after routing.

    That said, re-using the existing Middleware construct for this use has it's cons. For example, it is obvious that the middleware cannot modify the path. I can't think of any other major limitations, but I there may be others.

    feature 
    opened by adriangb 22
  • Serve Simple Page App (angular) on root alongside a backend on starlette

    Serve Simple Page App (angular) on root alongside a backend on starlette

    Hello, I'm developing an angular (7)+ starlette api backend and I would like to make starlette serve the angular app alongside with the api. I know that I could use ngnix to serve it but I would like to try to deploy just one server. Also I have found the https://github.com/tiangolo/uvicorn-gunicorn-starlette-docker and it would be amazing to be able to just use it with the whole app. As a normal angular app, it expects (by default) to be located to the "/" endpoint. As my angular prod files are in a folder ./angular relative to the starlette app.py file I have tried the following:

    _CURDIR = dirname(abspath(__file__))
    app = Starlette()
    app.mount('/', StaticFiles(directory=join(_CURDIR, 'angular' )))
    
    @app.exception_handler(404)
    async def not_found(request, exc):
        return FileResponse('./angular/index.html')
    
    if __name__ == '__main__':
        uvicorn.run(app, host='0.0.0.0', port=8090)
    
    

    The index.html is the usual on the angular apps:

    <!doctype html>
    <html lang="en">
    <head>
      <meta charset="utf-8">
      <title>ArcherytimerMatrix</title>
      <base href="/">
    
      <meta name="viewport" content="width=device-width, initial-scale=1">
      <link href="https://fonts.googleapis.com/css?family=Roboto:300,400,500" rel="stylesheet">
      <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
      <link rel="icon" type="image/x-icon" href="favicon.ico">
    <link rel="stylesheet" href="styles.54bd9f72bfb2c07e2a6b.css"></head>
    <body>
      <app-root></app-root>
    <script type="text/javascript" src="runtime.253d2798c34ad4bc8428.js"></script><script type="text/javascript" src="es2015-polyfills.4a4cfea0ce682043f4e9.js" nomodule>
    </script><script type="text/javascript" src="polyfills.407a467dedb63cfdd103.js"></script><script type="text/javascript" src="main.cfa2a2d950b21a173917.js"></script></body>
    </html>
    

    when I try to reach localhost:8090 the index.html is "shown" but it can't find the styles / runtime / polyfills and main

    INFO: Uvicorn running on http://0.0.0.0:8090 (Press CTRL+C to quit)
    INFO: ('127.0.0.1', 34138) - "GET / HTTP/1.1" 200
    INFO: ('127.0.0.1', 34138) - "GET /styles.54bd9f72bfb2c07e2a6b.css HTTP/1.1" 200
    INFO: ('127.0.0.1', 34140) - "GET /runtime.253d2798c34ad4bc8428.js HTTP/1.1" 200
    INFO: ('127.0.0.1', 34138) - "GET /polyfills.407a467dedb63cfdd103.js HTTP/1.1" 200
    INFO: ('127.0.0.1', 34140) - "GET /main.cfa2a2d950b21a173917.js HTTP/1.1" 200
    

    (the status is 200 as I'm catching the exception and redirecting...) If I try to access the static file directy: localhost:8090/styles.54bd9f72bfb2c07e2a6b.css Is not found either

    If I serve the statics files from an endpoint: app.mount('/angular', StaticFiles(directory=join(_CURDIR, 'angular' ))) and I try to access to the "angular" localhost:8090/angular/styles.54bd9f72bfb2c07e2a6b.css the file is served. So It seems that the "/" root can't be used for endopoint to static files (or there is a bug if this is not the intended behavior)

    Maybe I'm doing it wrong, is there another way to achieve this?

    Thank you in advance Regards

    opened by gpulido 22
  • Only stop receiving stream on `body_stream` if body is empty

    Only stop receiving stream on `body_stream` if body is empty

    • Closes #1977

    This solves the issue reported by @MrSalman333 on https://github.com/encode/starlette/pull/1609#issuecomment-1306742910.

    Test 1 (https://github.com/encode/starlette/pull/1609#issuecomment-1306786049)

    import logging
    
    import anyio
    from fastapi import Depends, FastAPI, Response
    from starlette.middleware.base import BaseHTTPMiddleware
    from starlette.middleware import Middleware
    
    
    class CustomMiddleware(BaseHTTPMiddleware):
        async def dispatch(self, request, call_next):
            return await call_next(request)
    
    
    app = FastAPI(middleware=[Middleware(CustomMiddleware)])
    
    
    def dependency_a(response: Response):
        try:
            yield "A"
        finally:
            logging.warning("A")
    
    
    def dependency_b(response: Response):
        try:
            yield "B"
        finally:
            logging.warning("B")
    
    
    def dependency_c(response: Response):
        try:
            yield "C"
        finally:
            logging.warning("C")
    
    
    @app.get(
        "/issue",
        dependencies=[
            Depends(dependency_a),
        ],
    )
    def show_dependencies_issue(
        b=Depends(dependency_b),
        c=Depends(dependency_c),
    ):
        print(b, c)
        return {"status": "ok"}
    

    Test 2 (https://github.com/encode/starlette/pull/1579#issuecomment-1097119520)

    from typing import Awaitable, Callable
    
    from starlette.middleware.base import BaseHTTPMiddleware
    from starlette.middleware.gzip import GZipMiddleware
    from starlette.routing import Route
    from starlette.middleware import Middleware
    from starlette.applications import Starlette
    from starlette.responses import Response
    from starlette.requests import Request
    
    class NoopMiddleware(BaseHTTPMiddleware):
        async def dispatch(self, request: Request, call_next: Callable[[Request], Awaitable]):
            return await call_next(request)
    
    def endpoint(request: Request):
        return Response(status_code=304)
    
    
    app2 = Starlette(
        routes=[Route("/", endpoint=endpoint)],
        middleware=[Middleware(GZipMiddleware), Middleware(NoopMiddleware)]
    )
    
    opened by Kludex 20
  • Version 0.13

    Version 0.13

    Documentation still in progress.

    This PR does not significantly remove any public API, but it does start to move us to a new prefered style of routing, moving away from the decorator style.

    I think using plain route lists is more clearly decoupled, and gives a clearer indication of what's going on under the hood.

    For example...

    routes = [
        Route('/', homepage),
        Mount('/users', routes=[
            Route('/', users, methods=['GET', 'POST']),
            Route('/{username}', user),
        ])
    ]
    
    app = Starlette(routes=routes)
    

    Similarly, middleware now has a prefered configure-on-init style...

    routes = ...
    
    middleware = [
        Middleware(SentryAsgiMiddleware) if settings.SENTRY_DSN else None,
        Middleware(HTTPSRedirectMiddleware) if settings.HTTPS_ONLY else None,
        Middleware(SessionMiddleware, secret_key=settings.SECRET, https_only=settings.HTTPS_ONLY)
    ]
    
    app = Starlette(routes=routes, middleware=middleware)
    

    Still to do here...

    • [ ] ~Review exception_handlers / server_error~. - We should defer this to a future release.
    • [ ] Update starlette-example.
    • [x] Update Routing docs.
    • [x] Update Middleware docs.
    • [x] Update routing examples in docs throughout.

    We may also want to reivew our url_for and url_path_for documentation and API as part of this release version. I'm somewhat keen for us to switch things around there, so that path-only URLs are the default style, and there's less surface area for folks to need to care about configuring Uvicorn's --allow-forward-ips. For example if we were using this:

    • app.url_for(), request.url_for(), url_for() in templates. Return a relative path-only URL.
    • request.absolute_url_for(), absolute_url_for() in templates. Return a fully qualified URL.

    I'm also pretty keen to switch things up here so that when debug=True we...

    • Display helpful routing table info if no route matches during routing.
    • Display helpful routing table info when url_for(...) fails.

    Something else that I think is interesting here is that we're more clearly exposing that alternative subclasses of BaseRoute can also be added to the routing table. For example, it'd be interesting to consider if there's any worthwhile documentation work to do in the ecosystem around eg. noting how you can use FastAPI's APIRoute inside a regular Starlette application, to point at a handler which gets their dependency injection treatments, alongside other regular Route cases, which just get the standard request argument.

    That line of thought is as much about demystifying how the different bits fit together, about making sure that we can display useful routing debug info for higher level frameworks as well as the plain starlette case, and also about enabling other framework authors to take the happy path when building on top of Starlette. (We kinda missed a trick with Responder here, which functions differently enough that it's working against the grain.)

    opened by tomchristie 20
  • Preserve changes to contexvars made in threadpools

    Preserve changes to contexvars made in threadpools

    I think this addresses https://github.com/tiangolo/fastapi/issues/953.

    Thank you @smagafurov for the link in https://github.com/tiangolo/fastapi/issues/953#issuecomment-730302314

    What does this do for users?

    This fixes a confusing behavior where their endpoint works differently depending on if it is sync or async. And in FastAPI (which for better or worse re-uses run_in_threadpool), it impacts dependencies as well.

    This is the current behavior:

    from typing import List
    from contextvars import ContextVar
    
    from starlette.applications import Starlette
    from starlette.routing import Route
    from starlette.requests import Request
    from starlette.responses import Response
    from starlette.middleware import Middleware
    from starlette.testclient import TestClient
    from starlette.types import ASGIApp, Scope, Receive, Send, Message
    
    user: ContextVar[str] = ContextVar("user")
    
    log: List[str] = []
    
    
    class LogUserMiddleware:
        def __init__(self, app: ASGIApp) -> None:
            self.app = app
        
        async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None:
            async def send_wrapper(message: Message) -> None:
                if message["type"] == "http.response.start":
                    log.append(user.get())
                await send(message)
            await self.app(scope, receive, send_wrapper)
    
    
    def endpoint_sync(request: Request) -> Response:
        user.set(request.query_params["user"])
        return Response()
    
    
    async def endpoint_async(request: Request) -> Response:
        return endpoint_sync(request)
    
    
    app = Starlette(
        routes=[
            Route("/sync", endpoint_sync),
            Route("/async", endpoint_async),
        ],
        middleware=[Middleware(LogUserMiddleware)]
    )
    
    
    client = TestClient(app, raise_server_exceptions=False)
    
    
    resp = client.get("/async", params={"user": "adrian"})
    assert resp.status_code == 200, resp.content
    assert log == ["adrian"]
    
    resp = client.get("/sync", params={"user": "adrian"})
    assert resp.status_code == 500, resp.content
    

    I wouldn't expect a user to write this themselves, but some library they are using very well could use contextvars to set something that then gets picked up by a middleware (for example, some sort of tracing library). Since this is an implementation detail, and the failure mode is pretty tricky, it would be difficult for a user to figure out what happened.

    feature refactor 
    opened by adriangb 19
  • Add support for range headers to `FileResponse`

    Add support for range headers to `FileResponse`

    • Closes #950.
    • Relates to https://github.com/encode/starlette/pull/1013/.
    • Inspired by https://github.com/abersheeran/baize/blob/23791841f30ca92775e50a544a8606d1d4deac93/baize/asgi/responses.py#L184

    The implementation differs from baize's FileResponse, since that one takes in consideration the "range" request header. This is because the Response classes in Starlette are naive in regard to the request.

    Alternative Solution

    Don't be naive in regard to the request, and send a Content-Range in case the client sent Range.

    I believe this alternative is cleaner than the implemented here.

    References

    • https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Range
    • https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/If-Range
    • https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Range
    • https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/206
    • https://developer.mozilla.org/en-US/docs/Web/HTTP/Range_requests
    opened by Kludex 0
  • Add Config.env_prefix option

    Add Config.env_prefix option

    This PR adds Config.env_prefix argument.

    import os
    from starlette.config import Config
    
    os.environ['APP_DEBUG'] = 'yes'
    os.environ['ENVIRONMENT'] = 'dev'
    
    config = Config(env_prefix='APP_')
    
    DEBUG = config('DEBUG') # lookups APP_DEBUG, returns "yes"
    ENVIRONMENT = config('ENVIRONMENT') # lookups APP_ENVIRONMENT, raises KeyError as variable is not defined
    
    opened by alex-oleshkevich 1
  • Version 0.24.0

    Version 0.24.0

    Checklist

    • [ ] https://github.com/encode/starlette/pull/1908
    • [ ] https://github.com/encode/starlette/pull/1701
    • [ ] https://github.com/encode/starlette/pull/1965
    • [ ] https://github.com/encode/starlette/pull/1922
    • [ ] https://github.com/encode/starlette/pull/1413
    opened by Kludex 0
  • #1931 Fix url parsing of ipv6 urls

    #1931 Fix url parsing of ipv6 urls

    The starting point for contributions should usually be a discussion

    Simple documentation typos may be raised as stand-alone pull requests, but otherwise please ensure you've discussed your proposal prior to issuing a pull request.

    This will help us direct work appropriately, and ensure that any suggested changes have been okayed by the maintainers.

    • [ ] Initially raised as discussion #...
    opened by kousikmitra 8
Releases(0.23.1)
  • 0.23.1(Dec 9, 2022)

  • 0.23.0(Dec 5, 2022)

  • 0.22.0(Nov 17, 2022)

    Changed

    • Bypass GZipMiddleware when response includes Content-Encoding #1901.

    Fixed

    • Remove unneeded unquote() from query parameters on the TestClient #1953.
    • Make sure MutableHeaders._list is actually a list #1917.
    • Import compatibility with the next version of AnyIO #1936.
    Source code(tar.gz)
    Source code(zip)
  • 0.21.0(Sep 26, 2022)

    This release replaces the underlying HTTP client used on the TestClient (requests :arrow_right: httpx), and as those clients differ a bit on their API, your test suite will likely break. To make the migration smoother, you can use the bump-testclient tool.

    Changed

    • Replace requests with httpx in TestClient #1376.

    Added

    • Add WebSocketException and support for WebSocket exception handlers #1263.
    • Add middleware parameter to Mount class #1649.
    • Officially support Python 3.11 #1863.
    • Implement __repr__ for route classes #1864.

    Fixed

    • Fix bug on which BackgroundTasks were cancelled when using BaseHTTPMiddleware and client disconnected #1715.
    Source code(tar.gz)
    Source code(zip)
  • 0.20.4(Jun 28, 2022)

  • 0.20.3(Jun 10, 2022)

  • 0.20.2(Jun 7, 2022)

  • 0.20.1(May 28, 2022)

    Fixed

    • Improve detection of async callables #1444.
    • Send 400 (Bad Request) when boundary is missing #1617.
    • Send 400 (Bad Request) when missing "name" field on Content-Disposition header #1643.
    • Do not send empty data to StreamingResponse on BaseHTTPMiddleware #1609.
    • Add __bool__ dunder for Secret #1625.
    Source code(tar.gz)
    Source code(zip)
  • 0.20.0(May 3, 2022)

  • 0.19.1(Apr 22, 2022)

    Fixed

    • Fix inference of Route.name when created from methods #1553.
    • Avoid TypeError on websocket.disconnect when code is None #1574.

    Deprecated

    • Deprecate WS_1004_NO_STATUS_RCVD and WS_1005_ABNORMAL_CLOSURE in favor of WS_1005_NO_STATUS_RCVD and WS_1006_ABNORMAL_CLOSURE, as the previous constants didn't match the WebSockets specs #1580.
    Source code(tar.gz)
    Source code(zip)
  • 0.19.0(Mar 9, 2022)

    Added

    • Error handler will always run, even if the error happens on a background task #761.
    • Add headers parameter to HTTPException #1435.
    • Internal responses with 405 status code insert an Allow header, as described by RFC 7231 #1436.
    • The content argument in JSONResponse is now required #1431.
    • Add custom URL convertor register #1437.
    • Add content disposition type parameter to FileResponse #1266.
    • Add next query param with original request URL in requires decorator #920.
    • Add raw_path to TestClient scope #1445.
    • Add union operators to MutableHeaders #1240.
    • Display missing route details on debug page #1363.
    • Change anyio required version range to >=3.4.0,<5.0 #1421 and #1460.
    • Add typing-extensions>=3.10 requirement - used only on lower versions than Python 3.10 #1475.

    Fixed

    • Prevent BaseHTTPMiddleware from hiding errors of StreamingResponse and mounted applications #1459.
    • SessionMiddleware uses an explicit path=..., instead of defaulting to the ASGI 'root_path' #1512.
    • Request.client is now compliant with the ASGI specifications #1462.
    • Raise KeyError at early stage for missing boundary #1349.

    Deprecated

    • Deprecate WSGIMiddleware in favor of a2wsgi #1504.
    • Deprecate run_until_first_complete #1443.
    Source code(tar.gz)
    Source code(zip)
  • 0.18.0(Jan 23, 2022)

    Added

    • Change default chunk size from 4Kb to 64Kb on FileResponse #1345.
    • Add support for functools.partial in WebSocketRoute #1356.
    • Add StaticFiles packages with directory #1350.
    • Allow environment options in Jinja2Templates #1401.
    • Allow HEAD method on HttpEndpoint #1346.
    • Accept additional headers on websocket.accept message #1361 and #1422.
    • Add reason to WebSocket close ASGI event #1417.
    • Add headers attribute to UploadFile #1382.
    • Don't omit Content-Length header for Content-Length: 0 cases #1395.
    • Don't set headers for responses with 1xx, 204 and 304 status code #1397.
    • SessionMiddleware.max_age now accepts None, so cookie can last as long as the browser session #1387.

    Fixed

    • Tweak hashlib.md5() function on FileResponses ETag generation. The parameter usedforsecurity flag is set to False, if the flag is available on the system. This fixes an error raised on systems with FIPS enabled #1366 and #1410.
    • Fix path_params type on url_path_for() method i.e. turn str into Any #1341.
    • Host now ignores port on routing #1322.
    Source code(tar.gz)
    Source code(zip)
  • 0.17.1(Nov 17, 2021)

  • 0.17.0(Nov 4, 2021)

    Added

    • Response.delete_cookie now accepts the same parameters as Response.set_cookie #1228.
    • Update the Jinja2Templates constructor to allow PathLike #1292.

    Fixed

    • Fix BadSignature exception handling in SessionMiddleware #1264.
    • Change HTTPConnection.__getitem__ return type from str to typing.Any #1118.
    • Change ImmutableMultiDict.getlist return type from typing.List[str] to typing.List[typing.Any] #1235.
    • Handle OSError exceptions on StaticFiles #1220.
    • Fix StaticFiles 404.html in HTML mode #1314.
    • Prevent anyio.ExceptionGroup in error views under a BaseHTTPMiddleware #1262.

    Removed

    • Remove GraphQL support #1198.
    Source code(tar.gz)
    Source code(zip)
  • 0.16.0(Jul 19, 2021)

    Added

    Fixed

    • starlette.websockets.WebSocket instances are now hashable and compare by identity #1039
    • A number of fixes related to running task groups in lifespan #1213, #1227

    Deprecated/removed

    • The method starlette.templates.Jinja2Templates.get_env was removed #1218
    • The ClassVar starlette.testclient.TestClient.async_backend was removed, the backend is now configured using constructor kwargs #1211
    • Passing an Async Generator Function or a Generator Function to starlette.router.Router(lifespan_context=) is deprecated. You should wrap your lifespan in @contextlib.asynccontextmanager. #1227 #1110
    Source code(tar.gz)
    Source code(zip)
  • 0.15.0(Jun 23, 2021)

    0.15.0

    This release includes major changes to the low-level asynchronous parts of Starlette. As a result, Starlette now depends on AnyIO and some minor API changes have occurred. Another significant change with this release is the deprecation of built-in GraphQL support.

    Added

    • Starlette now supports Trio as an async runtime via AnyIO - #1157.
    • TestClient.websocket_connect() now must be used as a context manager.
    • Initial support for Python 3.10 - #1201.
    • The compression level used in GZipMiddleware is now adjustable - #1128.

    Fixed

    • Several fixes to CORSMiddleware. See #1111, #1112, #1113, #1199.
    • Improved exception messages in the case of duplicated path parameter names - #1177.
    • RedirectResponse now uses quote instead of quote_plus encoding for the Location header to better match the behaviour in other frameworks such as Django - #1164.
    • Exception causes are now preserved in more cases - #1158.
    • Session cookies now use the ASGI root path in the case of mounted applications - #1147.
    • Fixed a cache invalidation bug when static files were deleted in certain circumstances - #1023.
    • Improved memory usage of BaseHTTPMiddleware when handling large responses - #1012 fixed via #1157

    Deprecated/removed

    • Built-in GraphQL support via the GraphQLApp class has been deprecated and will be removed in a future release. Please see #619. GraphQL is not supported on Python 3.10.
    • The executor parameter to GraphQLApp was removed. Use executor_class instead.
    • The workers parameter to WSGIMiddleware was removed. This hasn't had any effect since Starlette v0.6.3.
    Source code(tar.gz)
    Source code(zip)
  • 0.14.2(Feb 2, 2021)

    Fixed

    • Fixed ServerErrorMiddleware compatibility with Python 3.9.1/3.8.7 when debug mode is enabled - #1132.
    • Fixed unclosed socket ResourceWarnings when using the TestClient with WebSocket endpoints - #1132.
    • Improved detection of async endpoints wrapped in functools.partial on Python 3.8+ - #1106.
    Source code(tar.gz)
    Source code(zip)
  • 0.14.1(Nov 9, 2020)

  • 0.14.0(Nov 8, 2020)

    Added

    • Starlette now officially supports Python3.9.
    • In StreamingResponse, allow custom async iterator such as objects from classes implementing __aiter__.
    • Allow usage of functools.partial async handlers in Python versions 3.6 and 3.7.
    • Add 418 I'm A Teapot status code.

    Changed

    • Create tasks from handler coroutines before sending them to asyncio.wait.
    • Use format_exception instead of format_tb in ServerErrorMiddleware's debug responses.
    • Be more lenient with handler arguments when using the requires decorator.
    Source code(tar.gz)
    Source code(zip)
  • 0.13.8(Aug 14, 2020)

    • Revert Queue(maxsize=1) fix for BaseHTTPMiddleware middleware classes and streaming responses.

    • The StaticFiles constructor now allows pathlib.Path in addition to strings for its directory argument.

    Source code(tar.gz)
    Source code(zip)
  • 0.13.7(Aug 5, 2020)

  • 0.13.6(Jul 20, 2020)

  • 0.13.5(Jul 17, 2020)

    0.13.5

    • Add support for Starlette(lifespan=...) functions.
    • More robust path-traversal check in StaticFiles app.
    • Fix WSGI PATH_INFO encoding.
    • RedirectResponse now accepts optional background parameter
    • Allow path routes to contain regex meta characters
    • Treat ASGI HTTP 'body' as an optional key.
    • Don't use thread pooling for writing to in-memory upload files.
    Source code(tar.gz)
    Source code(zip)
  • 0.13.4(Apr 30, 2020)

Owner
Encode
Collaboratively funded software development.
Encode
Bablyon 🐍 A small ASGI web framework

A small ASGI web framework that you can make asynchronous web applications using uvicorn with using few lines of code

xArty 8 Dec 7, 2021
The lightning-fast ASGI server. ?

The lightning-fast ASGI server. Documentation: https://www.uvicorn.org Community: https://discuss.encode.io/c/uvicorn Requirements: Python 3.6+ (For P

Encode 6k Jan 3, 2023
Pyrin is an application framework built on top of Flask micro-framework to make life easier for developers who want to develop an enterprise application using Flask

Pyrin A rich, fast, performant and easy to use application framework to build apps using Flask on top of it. Pyrin is an application framework built o

Mohamad Nobakht 10 Jan 25, 2022
Asita is a web application framework for python based on express-js framework.

Asita is a web application framework for python. It is designed to be easy to use and be more easy for javascript users to use python frameworks because it is based on express-js framework.

Mattéo 4 Nov 16, 2021
Asynchronous HTTP client/server framework for asyncio and Python

Async http client/server framework Key Features Supports both client and server side of HTTP protocol. Supports both client and server Web-Sockets out

aio-libs 13.2k Jan 5, 2023
Async Python 3.6+ web server/framework | Build fast. Run fast.

Sanic | Build fast. Run fast. Build Docs Package Support Stats Sanic is a Python 3.6+ web server and web framework that's written to go fast. It allow

Sanic Community Organization 16.7k Jan 8, 2023
Fast, asynchronous and elegant Python web framework.

Warning: This project is being completely re-written. If you're curious about the progress, reach me on Slack. Vibora is a fast, asynchronous and eleg

vibora.io 5.7k Jan 8, 2023
cirrina is an opinionated asynchronous web framework based on aiohttp

cirrina cirrina is an opinionated asynchronous web framework based on aiohttp. Features: HTTP Server Websocket Server JSON RPC Server Shared sessions

André Roth 32 Mar 5, 2022
FastAPI framework, high performance, easy to learn, fast to code, ready for production

FastAPI framework, high performance, easy to learn, fast to code, ready for production Documentation: https://fastapi.tiangolo.com Source Code: https:

Sebastián Ramírez 53k Jan 2, 2023
The Web framework for perfectionists with deadlines.

Django Django is a high-level Python Web framework that encourages rapid development and clean, pragmatic design. Thanks for checking it out. All docu

Django 67.9k Dec 29, 2022
The Python micro framework for building web applications.

Flask Flask is a lightweight WSGI web application framework. It is designed to make getting started quick and easy, with the ability to scale up to co

The Pallets Projects 61.5k Jan 6, 2023
Tornado is a Python web framework and asynchronous networking library, originally developed at FriendFeed.

Tornado Web Server Tornado is a Python web framework and asynchronous networking library, originally developed at FriendFeed. By using non-blocking ne

null 20.9k Jan 1, 2023
Async Python 3.6+ web server/framework | Build fast. Run fast.

Sanic | Build fast. Run fast. Build Docs Package Support Stats Sanic is a Python 3.6+ web server and web framework that's written to go fast. It allow

Sanic Community Organization 16.7k Dec 28, 2022
bottle.py is a fast and simple micro-framework for python web-applications.

Bottle: Python Web Framework Bottle is a fast, simple and lightweight WSGI micro web-framework for Python. It is distributed as a single file module a

Bottle Micro Web Framework 7.8k Dec 31, 2022
Pyramid - A Python web framework

Pyramid Pyramid is a small, fast, down-to-earth, open source Python web framework. It makes real-world web application development and deployment more

Pylons Project 3.7k Dec 30, 2022
The no-nonsense, minimalist REST and app backend framework for Python developers, with a focus on reliability, correctness, and performance at scale.

The Falcon Web Framework Falcon is a reliable, high-performance Python web framework for building large-scale app backends and microservices. It encou

Falconry 9k Jan 1, 2023
Daniel Vaz Gaspar 4k Jan 8, 2023
CherryPy is a pythonic, object-oriented HTTP framework. https://docs.cherrypy.org/

Welcome to the GitHub repository of CherryPy! CherryPy is a pythonic, object-oriented HTTP framework. It allows building web applications in much the

CherryPy 1.6k Dec 29, 2022
REST API framework designed for human beings

Eve Eve is an open source Python REST API framework designed for human beings. It allows to effortlessly build and deploy highly customizable, fully f

eve 6.6k Jan 7, 2023