From 6ef0a4cb911c5bc098ce56b1729c9f308e19a856 Mon Sep 17 00:00:00 2001 From: kennethreitz Date: Mon, 23 Mar 2026 02:11:12 +0000 Subject: [PATCH] deploy: f86c7eed7083c3d17667f5dc838cc7cb38e66305 --- .buildinfo | 2 +- .doctrees/api.doctree | Bin 153772 -> 225069 bytes .doctrees/changes.doctree | Bin 75708 -> 87426 bytes .doctrees/environment.pickle | Bin 190742 -> 230493 bytes .doctrees/guide-config.doctree | Bin 0 -> 19213 bytes .doctrees/index.doctree | Bin 20284 -> 20393 bytes .doctrees/quickstart.doctree | Bin 46486 -> 51654 bytes .doctrees/tour.doctree | Bin 71114 -> 72928 bytes .doctrees/tutorial-auth.doctree | Bin 0 -> 18867 bytes .doctrees/tutorial-middleware.doctree | Bin 0 -> 22643 bytes .doctrees/tutorial-websockets.doctree | Bin 0 -> 18453 bytes _modules/index.html | 6 +- _modules/responder/api.html | 86 ++++- _modules/responder/background.html | 175 ++++++++++ _modules/responder/ext/ratelimit.html | 161 +++++++++ _modules/responder/models.html | 131 +++++-- _modules/responder/status_codes.html | 4 +- _sources/api.rst.txt | 39 +++ _sources/changes.md.txt | 38 +++ _sources/guide-config.rst.txt | 172 ++++++++++ _sources/index.rst.txt | 6 +- _sources/quickstart.rst.txt | 46 +++ _sources/tour.rst.txt | 16 + _sources/tutorial-auth.rst.txt | 191 +++++++++++ _sources/tutorial-middleware.rst.txt | 129 +++++++ _sources/tutorial-websockets.rst.txt | 171 ++++++++++ _static/documentation_options.js | 2 +- api.html | 393 ++++++++++++++++++--- backlog.html | 4 +- changes.html | 471 ++++++++++++++------------ cli.html | 4 +- deployment.html | 4 +- genindex.html | 116 +++++-- guide-config.html | 264 +++++++++++++++ index.html | 48 ++- objects.inv | Bin 889 -> 1106 bytes py-modindex.html | 4 +- quickstart.html | 50 ++- sandbox.html | 4 +- search.html | 4 +- searchindex.js | 2 +- testing.html | 4 +- tour.html | 19 +- tutorial-auth.html | 287 ++++++++++++++++ tutorial-flask.html | 8 +- tutorial-middleware.html | 222 ++++++++++++ tutorial-rest.html | 4 +- tutorial-sqlalchemy.html | 6 +- tutorial-websockets.html | 261 ++++++++++++++ 49 files changed, 3202 insertions(+), 352 deletions(-) create mode 100644 .doctrees/guide-config.doctree create mode 100644 .doctrees/tutorial-auth.doctree create mode 100644 .doctrees/tutorial-middleware.doctree create mode 100644 .doctrees/tutorial-websockets.doctree create mode 100644 _modules/responder/background.html create mode 100644 _modules/responder/ext/ratelimit.html create mode 100644 _sources/guide-config.rst.txt create mode 100644 _sources/tutorial-auth.rst.txt create mode 100644 _sources/tutorial-middleware.rst.txt create mode 100644 _sources/tutorial-websockets.rst.txt create mode 100644 guide-config.html create mode 100644 tutorial-auth.html create mode 100644 tutorial-middleware.html create mode 100644 tutorial-websockets.html diff --git a/.buildinfo b/.buildinfo index b2e6262..a121562 100644 --- a/.buildinfo +++ b/.buildinfo @@ -1,4 +1,4 @@ # Sphinx build info version 1 # This file records the configuration used when building these files. When it is not found, a full rebuild will be done. -config: 48bd624a1e2c91349b6c4e0ee21cd6e5 +config: e5a35904bc7bb78a12349affaec49f9c tags: 645f666f9bcd5a90fca523b33c5a78b7 diff --git a/.doctrees/api.doctree b/.doctrees/api.doctree index 48989080494d6c90a548844014f945cbaa7d852f..cd61576658d636de351b52e82151669badb4748f 100644 GIT binary patch literal 225069 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 diff --git a/.doctrees/environment.pickle b/.doctrees/environment.pickle index 6d7a69d928d0bb24f803c0fbb795f70743416119..492732dea866c0a5f99b24854d6b7620168e8d59 100644 GIT binary patch literal 230493 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 z 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\OP`QQCFO#v4)aXk6Uf700&j zLp`niSoVbaTlam005;VK* zx>#Dby=7_Wrlsw)`<4c*Ep4xT+tPr9rQM~Io@{?ZJF>y$m$VSR1a|lmsNqZC@#|>r N4tMtW=xDq3e*mW6KVSd= literal 190742 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 literal 0 HcmV?d00001 diff --git a/.doctrees/index.doctree b/.doctrees/index.doctree index 90c799ec3ca73e5bfa53631f9f4368baf6ffc20e..aaba530252d5ddaa8c9e6a949a24a6ce7a06c642 100644 GIT binary patch delta 773 zcmdlpk8$OEMwSNFsq;3n=-BWm22_@0lqqMwziSuQAQHjoMN+wDUG+Jv?RYM zGciXuv9u&(O4}5_9$~mpd1_K|esXqdNimv4Ze~hKPHK5#Q7Tx153VCEC$TsiEXI>w znwgTSo1CAQmYF_T-(FfU%Z`s*gxQo0SUx|h{Va&4vxxk zKxSf=GDsi=NR(!1W&LGgV91ck(9V$cF3yn3@}GR);Q(XKH z*Sm;wRspqilqO~6P7Ze}Qp^GJfST%nnvQ|Ykj`KRnUjT3^~xz9rm7ydsw(F)n5qWc zssvqfVX7K&tD5gpDG7B~6NakIhOX?)jDI&7#9km#+QXTbn44Ns zS&&*hrFM!&)`fbYXeZd}PO!C|U@JSp)^&ib>Hu5Q0k)z8YLlAW@p3mGzf}fgwXCLpwv(J3m7z%YCws;{lEopd?VBVzP*n0%PiAQ>Q#d zs8A(P%`uP`=?rF&wyYwc(vH%ktklUzoQhzos&K0ccg}~Ys>ZGAxpNszRSj-cbuPIu zRkgTP@wiq>LS0{np=$FyS9WH`ubY>7G_$as00qp^$@;z$^#?%Ay&xhVMC5>o8W2$l zB04}sD~Ol^A|`@}1t4NBh*$$6R)UBfAYvo>B{pFOXH8S*1)M z@-Q$wJF`GGc7ko|$g0r-ayr1)bbzhs02|){Ho60BY)5H^0?44FlRx;1`+!{viWi7W q(}3C`E-ePJz%H!^vA{0v2C={{oepAwUAh>=0=YD6{pMi5Fh&5NSF|+% diff --git a/.doctrees/quickstart.doctree b/.doctrees/quickstart.doctree index 1e297e38278c67172d9eeb7ffd5a54ea400340ba..586a5ae621255982194b09b180b6d5200a810f8d 100644 GIT binary patch delta 3867 zcmds4O>7fK6wWV(jYG;$gp?-fWI^NyI}S9tIE99v0FeldAhbx3+7s_MyUTia*_}<| z($wKlRH~H<+AUQj4lQb>9#9KSD-P`?mr9&^>ZQGLrK*sSIQPx09dC>SG%c4}vgO%* z^Zvf~y*G2?VcjoYedA)|r$61l+cX*u2-2sXOsjuVS? z+X$nKkuxsGwmh%JH5qkHg=w>4J88NH%sxK zeNwPr?*~IwgxzDduS^h4$}9Vk(uxik?b|Nddu!hvn!!y~P^)f93_UyzaaN zRR(3W}<-Wn?8*5aP~+b)!GEDgz&n#n{$Gcs6{ z4Vxy11_t*fglE1DxCfm|lb$VDz><`BJuz64il0S{JZl(bEJEiwCE~}Cc-YV>(P?}# zZxWzpxeF##+t5W6mr(a5@dC*M(ZpG-IYeCOE@dwWuke!NdtP|wS0(j7iEo7pk2w{L zG8GE%9%VxSW)+MPGH+^z#fU*rQZh2hG&LM6jk1QtpJg4GZ5GyN2r{xLOE7hy3&xOP z396Gbk)jt{FLkJ4DOj`1JlRp*P636=uQpm5e8DtuTWk{s)qFpsOgAKA`)<@Ex&*T; zHE)ru@A;*%;5LOE4)CmTHz>LWGcP2jZe}Keq1?cNYYv&;8U-4*@9S|JxN^7NrjqYQ z;5QD*@QJ(&hWT#z_DuPX+^4?6bhW9`sCRd`v*2z3kC>b*Ty&Jo1)E}v`tBzFl(lYO z?SKt#1RhYRPT#HP(oL{tiB~cT^{?{RbJ)`TkN8$l0!Ino<<4@e0<#*N3>=0dOB!^I z6RqwW{|cz`P_B)7mv0Sj=h{nW5ocNz8({FBNOlws6jNOUISw^I)9AsXkER_(lVBk7 zLOFcu%n>$(gJud`Q(&^ec_ct*qZPoay=-$B(9`U}3j?Yqn0SSctdK&G&NE04fgB$MeUR0` z7fov!z(X9s2-kIh1raNZ^TjYIW+zKPGYZG3m0S;2-@j%`f$8E7S?atSHtDpsTUK~W2!xvk2U5T=Xk!Swy-V)`*S@J}(V z>S+bCd4_BrlmoJTt!^79O!dT;k<153^1V(GNxoPM$vqWFVu#8BhR{P1TfuZJUJNP$ z{I)uPtBE+G#ktNZ(EV73u3Y3yI0V|g^?z=B;JOpQ1s6C#tIJ1K za#+UdPJk8Pc$;IjahxxPqu!rK#DY4|SW~0!g&$_B3%Y5sjdN<28!eGL*_9AY`R)!g zxL3v%8poOzr=@!(mPMFDFppM5*r^pnfTG2#Ck~A&d6V4cUAq#k8=qJ@cKcpk-OlFk zziVoUJc0Ps$5C(VlG>sE#TE})#O@|`?_fj9X17!IN!0sf=}-%oxa!D=J%e4pFDVhe MLG_nLet5g~Z&oWU6951J delta 96 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 delta 2638 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 literal 0 HcmV?d00001 diff --git a/.doctrees/tutorial-middleware.doctree b/.doctrees/tutorial-middleware.doctree new file mode 100644 index 0000000000000000000000000000000000000000..7d702be684cc72465259a1260820e7fa739e4ddf GIT binary patch literal 22643 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 literal 0 HcmV?d00001 diff --git a/.doctrees/tutorial-websockets.doctree b/.doctrees/tutorial-websockets.doctree new file mode 100644 index 0000000000000000000000000000000000000000..27a0a2cd8fb8a48d2c3d379f731d6be7e5d813f0 GIT binary patch literal 18453 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 TRT_m25v+J-@F-MCI?ewBi$4)8 literal 0 HcmV?d00001 diff --git a/_modules/index.html b/_modules/index.html index 394b367..ef1a4f1 100644 --- a/_modules/index.html +++ b/_modules/index.html @@ -4,13 +4,13 @@ - Overview: module code — responder 3.2.0 documentation + Overview: module code — responder 3.4.1 documentation - + @@ -39,6 +39,8 @@

All modules for which code is available

diff --git a/_modules/responder/api.html b/_modules/responder/api.html index f175740..618dbe8 100644 --- a/_modules/responder/api.html +++ b/_modules/responder/api.html @@ -4,13 +4,13 @@ - responder.api — responder 3.2.0 documentation + responder.api — responder 3.4.1 documentation - + @@ -103,6 +103,31 @@ lifespan=None, request_id=False, ): + """Create a new Responder API instance. + + :param debug: If ``True``, enable debug mode with verbose error pages. + :param title: The title of the API, used in OpenAPI documentation. + :param version: The version string for the API (e.g. ``"1.0"``). + :param description: A longer description of the API for OpenAPI docs. + :param terms_of_service: URL to the API's terms of service. + :param contact: Contact information dict for the API (``name``, ``url``, ``email``). + :param license: License information dict (``name``, ``url``). + :param openapi: The OpenAPI version string (e.g. ``"3.0.2"``). Enables OpenAPI schema generation. + :param openapi_route: The URL path for the OpenAPI schema (default ``"/schema.yml"``). + :param static_dir: Directory for static files. Set to ``None`` to disable. Created automatically if missing. + :param static_route: URL prefix for serving static files (default ``"/static"``). + :param templates_dir: Directory for Jinja2 templates (default ``"templates"``). + :param auto_escape: If ``True``, auto-escape HTML/XML in templates. + :param secret_key: Secret key for signing cookie-based sessions. **Always set this in production.** + :param enable_hsts: If ``True``, redirect all HTTP requests to HTTPS. + :param docs_route: URL path for interactive API docs (e.g. ``"/docs"``). Enables OpenAPI if not already set. + :param cors: If ``True``, enable CORS middleware. + :param cors_params: Dict of CORS configuration (``allow_origins``, ``allow_methods``, etc.). + :param allowed_hosts: List of allowed hostnames (e.g. ``["example.com"]``). Defaults to ``["*"]``. + :param openapi_theme: Documentation UI theme: ``"swagger_ui"``, ``"redoc"``, ``"rapidoc"``, or ``"elements"``. + :param lifespan: An async context manager for startup/shutdown logic. + :param request_id: If ``True``, add ``X-Request-ID`` headers to all responses. + """ # noqa: E501 self.background = BackgroundQueue() self.secret_key = secret_key @@ -192,17 +217,38 @@ @property def static_app(self): + """The Starlette ``StaticFiles`` application for serving static assets.""" if not hasattr(self, "_static_app"): assert self.static_dir is not None self._static_app = StaticFiles(directory=self.static_dir) return self._static_app +
+[docs] def before_request(self, websocket=False): + """Register a function to run before every request. + + If the hook sets ``resp.status_code``, the route handler is skipped + and the response is sent immediately (short-circuiting). + + :param websocket: If ``True``, register as a WebSocket before-request hook instead of HTTP. + + Usage:: + + @api.before_request() + def check_auth(req, resp): + if "Authorization" not in req.headers: + resp.status_code = 401 + resp.media = {"error": "unauthorized"} + + """ # noqa: E501 + def decorator(f): self.router.before_request(f, websocket=websocket) return f - return decorator + return decorator
+
[docs] @@ -224,8 +270,26 @@ return decorator
+
+[docs] def add_middleware(self, middleware_cls, **middleware_config): - self.app = middleware_cls(self.app, **middleware_config) + """Add ASGI middleware to the application. + + Middleware wraps the entire application and can inspect or modify + every request and response. Middleware is applied in reverse order — + the last middleware added runs first. + + :param middleware_cls: A Starlette-compatible middleware class. + :param middleware_config: Keyword arguments passed to the middleware constructor. + + Usage:: + + from starlette.middleware.httpsredirect import HTTPSRedirectMiddleware + api.add_middleware(HTTPSRedirectMiddleware) + + """ + self.app = middleware_cls(self.app, **middleware_config)
+
[docs] @@ -590,10 +654,17 @@ uvicorn.run(self, host=address, port=port, **options)
+
+[docs] def run(self, **kwargs): + """Run the application. Shorthand for :meth:`serve` that inherits the ``debug`` setting. + + :param kwargs: Keyword arguments passed through to :meth:`serve`. + """ if "debug" not in kwargs: kwargs.update({"debug": self.debug}) - self.serve(**kwargs) + self.serve(**kwargs)
+
[docs] @@ -621,6 +692,8 @@ +
+[docs] class RouteGroup: """A group of routes with a shared URL prefix.""" @@ -633,7 +706,8 @@ return self.api.route(full_route, **options) def before_request(self, **kwargs): - return self.api.before_request(**kwargs) + return self.api.before_request(**kwargs)
+
diff --git a/_modules/responder/background.html b/_modules/responder/background.html new file mode 100644 index 0000000..bfd8fea --- /dev/null +++ b/_modules/responder/background.html @@ -0,0 +1,175 @@ + + + + + + + responder.background — responder 3.4.1 documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +

Source code for responder.background

+import asyncio
+import concurrent.futures
+import multiprocessing
+import traceback
+
+from starlette.concurrency import run_in_threadpool
+
+__all__ = ["BackgroundQueue"]
+
+
+
+[docs] +class BackgroundQueue: + """A queue for running tasks in background threads. + + Uses a ``ThreadPoolExecutor`` sized to the number of CPUs. Access it + via ``api.background``. + + Usage:: + + # As a decorator — fire and forget + @api.background.task + def send_email(to, subject): + ... + + send_email("user@example.com", "Hello") + + # Direct submission + future = api.background.run(send_email, "user@example.com", "Hello") + + # As a callable (supports async functions) + await api.background(send_email, "user@example.com", "Hello") + + """ + + def __init__(self, n=None): + """Create a new background queue. + + :param n: Number of worker threads. Defaults to CPU count. + """ + if n is None: + n = multiprocessing.cpu_count() + + self.n = n + self.pool = concurrent.futures.ThreadPoolExecutor(max_workers=n) + self.results = [] + +
+[docs] + def run(self, f, *args, **kwargs): + """Submit a function to run in a background thread. + + :param f: The function to run. + :returns: A ``concurrent.futures.Future`` for the result. + """ + f = self.pool.submit(f, *args, **kwargs) + self.results.append(f) + return f
+ + +
+[docs] + def task(self, f): + """Decorator that wraps a function to run in the background thread pool. + + The decorated function returns a ``Future`` instead of blocking. + Exceptions are printed to stderr via traceback. + + :param f: The function to wrap. + """ + + def on_future_done(fs): + try: + fs.result() + except Exception: + traceback.print_exc() + + def do_task(*args, **kwargs): + result = self.run(f, *args, **kwargs) + result.add_done_callback(on_future_done) + return result + + return do_task
+ + + async def __call__(self, func, *args, **kwargs) -> None: + if asyncio.iscoroutinefunction(func): + return await asyncio.create_task(func(*args, **kwargs)) + return await run_in_threadpool(func, *args, **kwargs)
+ +
+ +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/_modules/responder/ext/ratelimit.html b/_modules/responder/ext/ratelimit.html new file mode 100644 index 0000000..2dbf046 --- /dev/null +++ b/_modules/responder/ext/ratelimit.html @@ -0,0 +1,161 @@ + + + + + + + responder.ext.ratelimit — responder 3.4.1 documentation + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +

Source code for responder.ext.ratelimit

+"""Simple in-memory rate limiter for Responder."""
+
+import time
+from collections import defaultdict
+
+
+
+[docs] +class RateLimiter: + """Token bucket rate limiter. + + Usage:: + + from responder.ext.ratelimit import RateLimiter + + limiter = RateLimiter(requests=100, period=60) # 100 req/min + + @api.route(before_request=True) + def rate_limit(req, resp): + limiter.check(req, resp) + + Or use the shorthand:: + + limiter = RateLimiter(requests=100, period=60) + limiter.install(api) + + """ + + def __init__(self, requests=100, period=60): + self.max_requests = requests + self.period = period + self._buckets: dict[str, list[float]] = defaultdict(list) + + def _client_key(self, req): + client = req.client + if client: + return client[0] + return req.headers.get("X-Forwarded-For", "unknown") + + def _cleanup(self, key): + now = time.time() + cutoff = now - self.period + self._buckets[key] = [ + t for t in self._buckets[key] if t > cutoff + ] + +
+[docs] + def check(self, req, resp): + """Check rate limit. Sets 429 status if exceeded.""" + key = self._client_key(req) + self._cleanup(key) + + if len(self._buckets[key]) >= self.max_requests: + resp.status_code = 429 + resp.media = {"error": "rate limit exceeded"} + resp.headers["Retry-After"] = str(self.period) + return False + + self._buckets[key].append(time.time()) + remaining = self.max_requests - len(self._buckets[key]) + resp.headers["X-RateLimit-Limit"] = str(self.max_requests) + resp.headers["X-RateLimit-Remaining"] = str(remaining) + return True
+ + +
+[docs] + def install(self, api): + """Install as a before_request hook on the API.""" + + @api.route(before_request=True) + def _rate_limit(req, resp): + self.check(req, resp)
+
+ +
+ +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/_modules/responder/models.html b/_modules/responder/models.html index 8931cfd..beec017 100644 --- a/_modules/responder/models.html +++ b/_modules/responder/models.html @@ -4,13 +4,13 @@ - responder.models — responder 3.2.0 documentation + responder.models — responder 3.4.1 documentation - + @@ -88,7 +88,15 @@ self[key] = value +
+[docs] class QueryDict(dict): + """A dictionary for query string parameters that handles multi-value keys. + + Single-value access returns the last value for a key. Use :meth:`get_list` + to retrieve all values for a multi-value parameter. + """ + def __init__(self, query_string): self.update(parse_qs(query_string)) @@ -103,6 +111,8 @@ except IndexError: return [] +
+[docs] def get(self, key, default=None): """ Return the last data value for the passed key. If key doesn't exist @@ -114,7 +124,8 @@ return default if val == []: return default - return val + return val
+ def _get_list(self, key, default=None, force_list=False): """ @@ -134,31 +145,48 @@ values = list(values) if values is not None else None return values +
+[docs] def get_list(self, key, default=None): """ Return the list of values for the key. If key doesn't exist, return a default value. """ - return self._get_list(key, default, force_list=True) + return self._get_list(key, default, force_list=True)
+ +
+[docs] def items(self): """ Yield (key, value) pairs, where value is the last item in the list associated with the key. """ for key in self: - yield key, self[key] + yield key, self[key]
+ +
+[docs] def items_list(self): """ Yield (key, value) pairs, where value is the the list. """ - yield from super().items() + yield from super().items()
+
+
[docs] class Request: + """An HTTP request, passed to each view as the first argument. + + Provides access to headers, cookies, query parameters, the request body, + session data, and more. Most properties are synchronous; reading the body + (via :attr:`content`, :attr:`text`, or :meth:`media`) requires ``await``. + """ + __slots__ = [ "_starlette", "formats", @@ -195,6 +223,7 @@ @property def mimetype(self): + """The MIME type of the request body, from the ``Content-Type`` header.""" return self.headers.get("Content-Type", "") @property @@ -312,6 +341,7 @@ @property def is_secure(self): + """``True`` if the request was made over HTTPS.""" return self.url.scheme == "https"
@@ -366,6 +396,22 @@
[docs] class Response: + """An HTTP response, passed to each view as the second argument. + + Mutate this object to control what gets sent back to the client. Set + :attr:`text`, :attr:`html`, :attr:`media`, or :attr:`content` to define + the body. Use :attr:`headers` and :meth:`set_cookie` to control metadata. + + :var text: Set the response body as plain text (sets ``Content-Type: text/plain``). + :var html: Set the response body as HTML (sets ``Content-Type: text/html``). + :var media: Set a Python object (dict, list) to be serialized as JSON (or negotiated format). + :var content: Set the raw response body as bytes. + :var status_code: The HTTP status code (e.g. ``200``, ``404``). Defaults to ``200`` if not set. + :var headers: A dict of response headers. + :var cookies: A ``SimpleCookie`` holding cookies to set on the response. + :var session: A dict of session data. Changes are persisted in a signed cookie. + """ # noqa: E501 + __slots__ = [ "req", "status_code", @@ -385,28 +431,42 @@ def __init__(self, req, *, formats): self.req = req - #: The HTTP Status Code to use for the Response. self.status_code: int | None = None - self.content = None #: A bytes representation of the response body. + self.content = None self.mimetype = None self.encoding = DEFAULT_ENCODING - self.media = None #: A Python object that will be content-negotiated and - #: sent back to the client. Typically, in JSON formatting. + self.media = None self._stream = None - self.headers = {} #: A Python dictionary of ``{key: value}``, - #: representing the headers of the response. + self.headers = {} self.formats = formats - self.cookies: SimpleCookie = SimpleCookie() #: The cookies set in the Response - self.session = ( - req.session - ) #: The cookie-based session data, in dict form, to add to the Response. + self.cookies: SimpleCookie = SimpleCookie() + self.session = req.session +
+[docs] def stream(self, func, *args, **kwargs): + """Set up a streaming response from an async generator function. + + The generator yields chunks of bytes that are sent to the client + as they are produced, without buffering the full response in memory. + + Usage:: + + @api.route("/stream") + async def stream_data(req, resp): + @resp.stream + async def body(): + for i in range(10): + yield f"chunk {i}\\n".encode() + + :param func: An async generator function that yields response chunks. + """ assert inspect.isasyncgenfunction(func) self._stream = functools.partial(func, *args, **kwargs) - return func + return func
+
[docs] @@ -510,11 +570,20 @@ self.mimetype = guessed or "application/octet-stream"
+
+[docs] def redirect(self, location, *, set_text=True, status_code=HTTP_301): + """Redirect the client to a different URL. + + :param location: The URL to redirect to. + :param set_text: If ``True``, set a default redirect message as the body. + :param status_code: The HTTP status code (default ``301``). + """ self.status_code = status_code if set_text: self.text = f"Redirecting to: {location}" - self.headers.update({"Location": location}) + self.headers.update({"Location": location})
+ @property async def body(self): @@ -545,6 +614,8 @@ {"Content-Type": "application/json"}, ) + + def _prepare_cookies(self, starlette_response): cookie_header = ( @@ -594,10 +685,12 @@ @property def ok(self): + """``True`` if the status code is in the 2xx range (success).""" return 200 <= self.status_code_safe < 300 @property def status_code_safe(self) -> int: + """Return the status code, raising ``RuntimeError`` if it hasn't been set.""" if self.status_code is None: raise RuntimeError("HTTP status code has not been defined") return self.status_code
diff --git a/_modules/responder/status_codes.html b/_modules/responder/status_codes.html index 154d5ce..1bd686e 100644 --- a/_modules/responder/status_codes.html +++ b/_modules/responder/status_codes.html @@ -4,13 +4,13 @@ - responder.status_codes — responder 3.2.0 documentation + responder.status_codes — responder 3.4.1 documentation - + diff --git a/_sources/api.rst.txt b/_sources/api.rst.txt index fc7851f..7bc0506 100644 --- a/_sources/api.rst.txt +++ b/_sources/api.rst.txt @@ -43,6 +43,45 @@ status code, headers, and cookies. :inherited-members: +Route Groups +------------ + +Group related routes under a shared URL prefix — useful for API versioning +and organizing large applications. + +.. autoclass:: responder.api.RouteGroup + :members: + + +Background Queue +---------------- + +Run tasks in background threads without blocking the response. Available +as ``api.background``. + +.. autoclass:: responder.background.BackgroundQueue + :members: + + +Query Dict +---------- + +A dictionary subclass for query string parameters with multi-value support. + +.. autoclass:: responder.models.QueryDict + :members: + + +Rate Limiter +------------ + +In-memory token bucket rate limiter. Limits requests per client IP address +and returns ``429 Too Many Requests`` when exceeded. + +.. autoclass:: responder.ext.ratelimit.RateLimiter + :members: + + Status Code Helpers ------------------- diff --git a/_sources/changes.md.txt b/_sources/changes.md.txt index 3cf2d0b..c485090 100644 --- a/_sources/changes.md.txt +++ b/_sources/changes.md.txt @@ -7,6 +7,44 @@ this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm ## [Unreleased] +## [v3.2.0] - 2026-03-22 + +### Added + +- Pydantic auto-validation: `request_model` validates input, returns 422 on failure +- Pydantic auto-serialization: `response_model` strips extra fields from responses +- Server-Sent Events: `@resp.sse` for real-time streaming +- `resp.stream_file()` for streaming large files without loading into memory +- `@api.after_request()` hooks +- `api.group("/prefix")` for route groups and API versioning +- `api.graphql("/path", schema=schema)` one-liner GraphQL setup +- `api = responder.API(request_id=True)` for automatic request ID generation +- Built-in rate limiter: `RateLimiter(requests=100, period=60).install(api)` +- MessagePack format support: `await req.media("msgpack")` +- `req.is_json`, `req.path_params`, `req.client` properties +- `api.exception_handler()` decorator for custom error handling +- Lifespan context manager support +- `uuid` and `path` route convertors +- PEP 561 `py.typed` marker +- Pydantic support for OpenAPI schema generation + +### Changed + +- Dependencies flattened: `pip install responder` gets everything +- Core deps reduced to starlette + uvicorn +- TestClient lazy-loaded (no httpx import in production) +- Before-request hooks can short-circuit by setting status code +- Removed poethepoet task runner + +### Fixed + +- Multipart parser losing headers when parts have multiple headers +- `url_for()` with typed route params (`{id:int}`) +- `resp.body` encoding crash on bytes content +- GraphQL text query missing `await` +- Streaming responses not sending Content-Type headers +- Python 3.9 compatibility for union type syntax + ## [v3.0.0] - 2026-03-22 ### Added diff --git a/_sources/guide-config.rst.txt b/_sources/guide-config.rst.txt new file mode 100644 index 0000000..ce62f6e --- /dev/null +++ b/_sources/guide-config.rst.txt @@ -0,0 +1,172 @@ +Configuration +============= + +Every application needs different settings for different environments — +debug mode in development, real secrets in production, different database +URLs for testing. This guide covers how to manage configuration cleanly. + + +Environment Variables +--------------------- + +The simplest and most universal approach. Environment variables work +everywhere — locally, in Docker, on cloud platforms — and keep secrets +out of your source code:: + + import os + import responder + + api = responder.API( + debug=os.getenv("DEBUG", "false").lower() == "true", + secret_key=os.environ["SECRET_KEY"], + cors=os.getenv("CORS_ENABLED", "false").lower() == "true", + ) + +Some variables Responder handles automatically: + +- ``PORT`` — when set, the server binds to ``0.0.0.0`` on this port + +Set variables in your shell:: + + $ export SECRET_KEY="your-secret-here" + $ export DEBUG=true + $ python app.py + +Or in a ``.env`` file (don't commit this to git):: + + SECRET_KEY=your-secret-here + DEBUG=true + + +Using .env Files +---------------- + +For local development, a ``.env`` file is convenient. Install +``python-dotenv`` and load it at the top of your app:: + + $ uv pip install python-dotenv + +:: + + from dotenv import load_dotenv + load_dotenv() + + import os + import responder + + api = responder.API( + secret_key=os.environ["SECRET_KEY"], + ) + +Add ``.env`` to your ``.gitignore`` — never commit secrets. + + +Configuration Class Pattern +---------------------------- + +For larger applications, a configuration class keeps things organized:: + + import os + + class Config: + SECRET_KEY = os.environ.get("SECRET_KEY", "dev-secret") + DEBUG = os.environ.get("DEBUG", "false").lower() == "true" + DATABASE_URL = os.environ.get("DATABASE_URL", "sqlite:///dev.db") + CORS_ORIGINS = os.environ.get("CORS_ORIGINS", "").split(",") + + config = Config() + + api = responder.API( + debug=config.DEBUG, + secret_key=config.SECRET_KEY, + cors=bool(config.CORS_ORIGINS[0]), + cors_params={"allow_origins": config.CORS_ORIGINS}, + ) + +This makes it easy to see all your settings in one place. + + +Secret Key +---------- + +The ``secret_key`` is used to sign session cookies. If someone knows your +secret key, they can forge session data and impersonate any user. + +Rules: + +- **Never use the default** in production +- **Generate a random key**: ``python -c "import secrets; print(secrets.token_hex(32))"`` +- **Store it in an environment variable**, not in code +- **Rotate it** if it's ever compromised (this invalidates all sessions) + +:: + + api = responder.API(secret_key=os.environ["SECRET_KEY"]) + + +Debug Mode +---------- + +Debug mode controls error page behavior: + +- **On** (``debug=True``): detailed error pages with tracebacks. Never + use this in production — it exposes your source code. +- **Off** (``debug=False``): generic error pages. This is the default. + +:: + + api = responder.API(debug=True) # development only + +A common pattern is to read it from the environment:: + + api = responder.API(debug=os.getenv("DEBUG") == "true") + + +Allowed Hosts +------------- + +In production, always set ``allowed_hosts`` to prevent Host header +attacks. This should match the domain names your application serves:: + + api = responder.API( + allowed_hosts=["example.com", "www.example.com"], + ) + +In development, you can use ``["*"]`` (the default) or specific local +addresses:: + + api = responder.API(allowed_hosts=["localhost", "127.0.0.1"]) + + +Putting It All Together +----------------------- + +A production-ready configuration setup:: + + import os + from dotenv import load_dotenv + + load_dotenv() + + import responder + + api = responder.API( + debug=os.getenv("DEBUG", "false") == "true", + secret_key=os.environ["SECRET_KEY"], + allowed_hosts=os.getenv("ALLOWED_HOSTS", "*").split(","), + cors=bool(os.getenv("CORS_ORIGINS")), + cors_params={ + "allow_origins": os.getenv("CORS_ORIGINS", "").split(","), + "allow_methods": ["GET", "POST", "PUT", "DELETE"], + }, + ) + +With a ``.env`` file for local development:: + + SECRET_KEY=dev-secret-do-not-use-in-prod + DEBUG=true + ALLOWED_HOSTS=localhost,127.0.0.1 + CORS_ORIGINS=http://localhost:3000 + +And environment variables set properly in production (via your cloud +platform's dashboard, Docker secrets, or a secrets manager). diff --git a/_sources/index.rst.txt b/_sources/index.rst.txt index 7455866..6b9ba39 100644 --- a/_sources/index.rst.txt +++ b/_sources/index.rst.txt @@ -86,7 +86,7 @@ Installation $ uv pip install responder -Python 3.9 and above. That's it. +Python 3.10 and above. That's it. .. toctree:: @@ -106,7 +106,11 @@ Python 3.9 and above. That's it. tutorial-rest tutorial-sqlalchemy + tutorial-auth + tutorial-websockets + tutorial-middleware tutorial-flask + guide-config .. toctree:: :maxdepth: 1 diff --git a/_sources/quickstart.rst.txt b/_sources/quickstart.rst.txt index 1781eed..a36cdc7 100644 --- a/_sources/quickstart.rst.txt +++ b/_sources/quickstart.rst.txt @@ -330,3 +330,49 @@ for lightweight use cases where you don't need a full message broker. your application, which makes them fast to start but means CPU-intensive work will block the event loop. For heavy computation, consider a proper task queue. + + +Putting It All Together +----------------------- + +Here's a complete, working Responder application that combines everything +from this guide:: + + import responder + + api = responder.API() + + @api.route("/") + def index(req, resp): + resp.text = "Welcome to the API" + + @api.route("/hello/{name}") + def greet(req, resp, *, name): + resp.media = {"message": f"hello, {name}!"} + + @api.route("/add/{a:int}/{b:int}") + def add(req, resp, *, a, b): + resp.media = {"result": a + b} + + @api.route("/echo", methods=["POST"]) + async def echo(req, resp): + data = await req.media() + resp.media = {"received": data} + + if __name__ == "__main__": + api.run() + +Save this as ``app.py``, run it with ``python app.py``, and try:: + + $ curl http://localhost:5042/ + $ curl http://localhost:5042/hello/world + $ curl http://localhost:5042/add/3/4 + $ curl -X POST http://localhost:5042/echo \ + -H "Content-Type: application/json" -d '{"key": "value"}' + +From here, explore the :doc:`tour` for the full range of features, or +jump into the tutorials: + +- :doc:`tutorial-rest` — build a full CRUD API with validation +- :doc:`tutorial-sqlalchemy` — connect to a database +- :doc:`tutorial-auth` — add authentication diff --git a/_sources/tour.rst.txt b/_sources/tour.rst.txt index 962c720..f041e3f 100644 --- a/_sources/tour.rst.txt +++ b/_sources/tour.rst.txt @@ -416,6 +416,22 @@ Requests to ``/flask/`` will be handled by Flask. Everything else goes through Responder. Both WSGI and ASGI apps are supported — Responder wraps WSGI apps in an ASGI adapter automatically. +You can also mount `marimo `_ notebooks as +interactive dashboards within your API:: + + import marimo + + server = ( + marimo.create_asgi_app() + .with_app(path="", root="./notebooks/dashboard.py") + .with_app(path="/analysis", root="./notebooks/analysis.py") + ) + + api.mount("/notebooks", server.build()) + +Notebooks are served at ``/notebooks/`` and ``/notebooks/analysis``, +with full interactivity — reactive cells, widgets, plots, and all. + Cookies ------- diff --git a/_sources/tutorial-auth.rst.txt b/_sources/tutorial-auth.rst.txt new file mode 100644 index 0000000..5e40408 --- /dev/null +++ b/_sources/tutorial-auth.rst.txt @@ -0,0 +1,191 @@ +Authentication +============== + +Every API that handles user data needs authentication — a way to verify +who is making a request. This guide covers the most common patterns: +API keys, JWT tokens, and how to build reusable auth guards with +Responder's before-request hooks. + + +API Key Authentication +---------------------- + +The simplest approach. The client sends a secret key in a header, and +your server checks it against a known value. This is common for +server-to-server communication and simple APIs:: + + API_KEYS = {"sk-abc123", "sk-def456"} + + @api.route(before_request=True) + def check_api_key(req, resp): + key = req.headers.get("X-API-Key") + if key not in API_KEYS: + resp.status_code = 401 + resp.media = {"error": "Invalid or missing API key"} + +Because the before-request hook sets ``resp.status_code``, the route +handler is skipped entirely for unauthorized requests. The client never +reaches your endpoint — the guard catches them first. + +The client sends the key like this:: + + $ curl -H "X-API-Key: sk-abc123" http://localhost:5042/protected + + +Bearer Token Authentication +---------------------------- + +Bearer tokens are the standard for modern APIs. The client sends a token +in the ``Authorization`` header, and the server validates it. The most +common format is `JWT `_ (JSON Web Tokens). + +Install PyJWT:: + + $ uv pip install pyjwt + +Create a helper to encode and decode tokens:: + + import jwt + from datetime import datetime, timedelta + + SECRET = "your-secret-key" + + def create_token(user_id: int) -> str: + payload = { + "sub": user_id, + "exp": datetime.utcnow() + timedelta(hours=24), + } + return jwt.encode(payload, SECRET, algorithm="HS256") + + def verify_token(token: str) -> dict | None: + try: + return jwt.decode(token, SECRET, algorithms=["HS256"]) + except jwt.InvalidTokenError: + return None + +Add a login endpoint that issues tokens, and a before-request hook that +verifies them:: + + @api.route("/login", methods=["POST"]) + async def login(req, resp): + data = await req.media() + # In a real app, check credentials against a database + if data.get("username") == "admin" and data.get("password") == "secret": + token = create_token(user_id=1) + resp.media = {"token": token} + else: + resp.status_code = 401 + resp.media = {"error": "Invalid credentials"} + + @api.route(before_request=True) + def auth_guard(req, resp): + # Skip auth for the login endpoint itself + if req.url.path == "/login": + return + + auth = req.headers.get("Authorization", "") + if not auth.startswith("Bearer "): + resp.status_code = 401 + resp.media = {"error": "Missing bearer token"} + return + + token = auth[7:] # Strip "Bearer " + payload = verify_token(token) + if payload is None: + resp.status_code = 401 + resp.media = {"error": "Invalid or expired token"} + return + + # Store the authenticated user on the request state + req.state.user_id = payload["sub"] + +Now any route can access the authenticated user:: + + @api.route("/me") + def get_me(req, resp): + resp.media = {"user_id": req.state.user_id} + +The client flow: + +1. ``POST /login`` with credentials → receive a token +2. Include ``Authorization: Bearer `` on every subsequent request +3. The token expires after 24 hours — the client must log in again + + +Skipping Auth for Public Routes +-------------------------------- + +The example above skips auth for ``/login`` by checking the path. For +more control, you can use a set of public paths:: + + PUBLIC_PATHS = {"/login", "/signup", "/health", "/docs", "/schema.yml"} + + @api.route(before_request=True) + def auth_guard(req, resp): + if req.url.path in PUBLIC_PATHS: + return + # ... check token + + +Custom Exception for Auth Errors +--------------------------------- + +For cleaner code, define a custom exception and register a handler:: + + class AuthError(Exception): + def __init__(self, message="Unauthorized", status_code=401): + self.message = message + self.status_code = status_code + + @api.exception_handler(AuthError) + async def handle_auth_error(req, resp, exc): + resp.status_code = exc.status_code + resp.media = {"error": exc.message} + +Now your auth guard can simply raise:: + + @api.route(before_request=True) + def auth_guard(req, resp): + if req.url.path in PUBLIC_PATHS: + return + if "Authorization" not in req.headers: + raise AuthError("Missing authorization header") + + +Using Sessions for Web Apps +---------------------------- + +For traditional web applications (with HTML pages and forms), cookie-based +sessions are simpler than tokens. The browser handles cookies automatically +— no client-side token management needed:: + + @api.route("/login", methods=["POST"]) + async def login(req, resp): + data = await req.media("form") + if data["username"] == "admin" and data["password"] == "secret": + resp.session["user"] = data["username"] + api.redirect(resp, location="/dashboard") + else: + resp.status_code = 401 + resp.html = "

Invalid credentials

" + + @api.route("/dashboard") + def dashboard(req, resp): + user = req.session.get("user") + if not user: + api.redirect(resp, location="/login") + return + resp.html = f"

Welcome, {user}!

" + + @api.route("/logout") + def logout(req, resp): + resp.session.clear() + api.redirect(resp, location="/login") + +Remember to set a proper secret key:: + + api = responder.API(secret_key="your-production-secret-key") + +The session data is signed (not encrypted) — users can read it but +can't tamper with it. Don't store sensitive data like passwords in +sessions. diff --git a/_sources/tutorial-middleware.rst.txt b/_sources/tutorial-middleware.rst.txt new file mode 100644 index 0000000..5679d35 --- /dev/null +++ b/_sources/tutorial-middleware.rst.txt @@ -0,0 +1,129 @@ +Writing Middleware +================== + +Middleware sits between the server and your route handlers, processing +every request and response that flows through your application. It's the +right tool for cross-cutting concerns — things that apply to *all* +requests, not just specific routes. + +Common middleware use cases: + +- Request logging and timing +- Authentication and authorization +- Adding security headers +- Request ID generation +- Rate limiting +- Response compression (built-in) + + +Hooks vs. Middleware +-------------------- + +Responder gives you two levels of request processing: + +**Hooks** (``before_request`` / ``after_request``) run inside Responder's +routing layer. They receive Responder's ``req`` and ``resp`` objects and +are the simplest way to add behavior:: + + @api.route(before_request=True) + def add_header(req, resp): + resp.headers["X-Powered-By"] = "Responder" + + @api.after_request() + def log_request(req, resp): + print(f"{req.method} {req.url.path} -> {resp.status_code}") + +**Middleware** runs at the ASGI level, wrapping the entire application. +It's more powerful but more complex — you work with raw ASGI scopes +instead of Responder objects. Use middleware when you need to process +requests *before* they reach Responder's routing, or when you need to +integrate with Starlette middleware. + + +Using Starlette Middleware +-------------------------- + +Responder is built on Starlette, so any Starlette middleware works +out of the box:: + + from starlette.middleware.base import BaseHTTPMiddleware + + class TimingMiddleware(BaseHTTPMiddleware): + async def dispatch(self, request, call_next): + import time + start = time.time() + response = await call_next(request) + duration = time.time() - start + response.headers["X-Response-Time"] = f"{duration:.3f}s" + return response + + api.add_middleware(TimingMiddleware) + +The ``dispatch`` method receives a Starlette ``Request`` and a +``call_next`` function. Call ``call_next(request)`` to pass the request +to the next middleware (or to your route handler). The return value is +a Starlette ``Response`` that you can modify before it's sent. + + +Built-in Middleware +------------------- + +Responder configures several middleware components automatically: + +- **GZipMiddleware** — compresses responses larger than 500 bytes +- **TrustedHostMiddleware** — validates the ``Host`` header +- **ServerErrorMiddleware** — catches unhandled exceptions +- **ExceptionMiddleware** — routes exceptions to your handlers +- **SessionMiddleware** — manages signed cookie sessions + +Optional middleware you can enable: + +- **CORSMiddleware** — ``api = responder.API(cors=True)`` +- **HTTPSRedirectMiddleware** — ``api = responder.API(enable_hsts=True)`` + + +Adding Third-Party Middleware +----------------------------- + +Any ASGI middleware can be added with ``api.add_middleware()``:: + + from some_package import SomeMiddleware + + api.add_middleware(SomeMiddleware, option1="value", option2=True) + +Keyword arguments are passed to the middleware's constructor. + + +Middleware Order +---------------- + +Middleware wraps your application like layers of an onion. The *last* +middleware added is the *outermost* layer — it sees the request first +and the response last. + +Responder's built-in middleware stack (from outermost to innermost): + +1. SessionMiddleware +2. ServerErrorMiddleware +3. CORSMiddleware (if enabled) +4. TrustedHostMiddleware +5. HTTPSRedirectMiddleware (if enabled) +6. GZipMiddleware +7. ExceptionMiddleware +8. Your routes + +When you call ``api.add_middleware()``, your middleware is added *outside* +the existing stack. Keep this in mind for ordering dependencies — if +middleware A depends on middleware B having run first, add B before A. + + +When to Use What +----------------- + +- **Simple header additions, logging, auth checks** → use hooks +- **Response transformation, timing, third-party integrations** → use middleware +- **Rate limiting** → use the built-in ``RateLimiter`` (it uses hooks internally) +- **Request ID** → use ``api = responder.API(request_id=True)`` + +Start with hooks. They're simpler and cover most cases. Graduate to +middleware when hooks aren't enough. diff --git a/_sources/tutorial-websockets.rst.txt b/_sources/tutorial-websockets.rst.txt new file mode 100644 index 0000000..62f17ae --- /dev/null +++ b/_sources/tutorial-websockets.rst.txt @@ -0,0 +1,171 @@ +WebSocket Tutorial +================== + +HTTP is request-response — the client asks, the server answers, and the +connection closes. WebSockets upgrade that into a persistent, bidirectional +channel where both sides can send messages at any time. This is what powers +chat apps, live dashboards, multiplayer games, and collaborative editors. + +This tutorial builds a simple chat room to show how WebSockets work in +Responder. + + +How WebSockets Work +------------------- + +1. The client sends a normal HTTP request with an ``Upgrade: websocket`` + header. +2. The server accepts the upgrade and the connection switches protocols. +3. Both sides can now send messages freely — no more request/response. +4. Either side can close the connection at any time. + +In Responder, WebSocket routes receive a ``ws`` object instead of +``req`` and ``resp``. The ``ws`` object has methods for accepting the +connection, sending and receiving data, and closing. + + +Echo Server +----------- + +The simplest WebSocket — echoes everything back:: + + @api.route("/ws", websocket=True) + async def echo(ws): + await ws.accept() + while True: + data = await ws.receive_text() + await ws.send_text(f"Echo: {data}") + +The ``await ws.accept()`` call completes the WebSocket handshake. After +that, you're in a loop — receive a message, send a response. + +Test it with a WebSocket client:: + + $ pip install websocket-client + $ python -c " + import websocket + ws = websocket.create_connection('ws://localhost:5042/ws') + ws.send('hello') + print(ws.recv()) # Echo: hello + ws.close() + " + + +Chat Room +--------- + +A chat room needs to broadcast messages to all connected clients. We keep +a set of active connections and iterate through them when someone sends +a message:: + + connected = set() + + @api.route("/chat", websocket=True) + async def chat(ws): + await ws.accept() + connected.add(ws) + try: + while True: + message = await ws.receive_text() + # Broadcast to all connected clients + for client in connected: + await client.send_text(message) + except Exception: + pass + finally: + connected.discard(ws) + +The ``try/finally`` block ensures we remove disconnected clients from +the set, even if the connection drops unexpectedly. + + +Data Formats +------------ + +WebSockets support three data formats: + +**Text** — plain strings:: + + await ws.send_text("hello") + message = await ws.receive_text() + +**JSON** — auto-serialized Python objects:: + + await ws.send_json({"type": "update", "data": [1, 2, 3]}) + message = await ws.receive_json() + +**Binary** — raw bytes, useful for images, audio, or custom protocols:: + + await ws.send_bytes(b"\x00\x01\x02") + data = await ws.receive_bytes() + + +HTML Client +----------- + +Here's a minimal HTML page that connects to the chat room. The browser's +built-in ``WebSocket`` API handles everything — no libraries needed: + +.. code-block:: html + + + + +
+ + + + + +Save this as ``static/index.html`` and serve it with Responder's +built-in static file support. + + +Before-Request Hooks for WebSockets +------------------------------------ + +You can run code before a WebSocket connection is established, just like +HTTP before-request hooks. This is useful for authentication:: + + @api.before_request(websocket=True) + async def ws_auth(ws): + # Check for a token in the query string + # (WebSocket headers are limited in browsers) + await ws.accept() + +WebSocket before-request hooks receive the ``ws`` object and must call +``await ws.accept()`` if they want the connection to proceed. + + +Testing WebSockets +------------------ + +Use Starlette's ``TestClient`` for WebSocket tests:: + + from starlette.testclient import TestClient + + def test_echo(): + client = TestClient(api) + with client.websocket_connect("/ws") as ws: + ws.send_text("hello") + assert ws.receive_text() == "Echo: hello" + +The ``websocket_connect`` context manager handles the connection +lifecycle — it connects on enter and disconnects on exit. diff --git a/_static/documentation_options.js b/_static/documentation_options.js index b1611d5..3d20959 100644 --- a/_static/documentation_options.js +++ b/_static/documentation_options.js @@ -1,5 +1,5 @@ const DOCUMENTATION_OPTIONS = { - VERSION: '3.2.0', + VERSION: '3.4.1', LANGUAGE: 'en', COLLAPSE_INDEX: false, BUILDER: 'html', diff --git a/api.html b/api.html index 45e147e..8b23b4d 100644 --- a/api.html +++ b/api.html @@ -5,13 +5,13 @@ - API Reference — responder 3.2.0 documentation + API Reference — responder 3.4.1 documentation - + @@ -78,6 +78,28 @@ module and use it to define your entire web service.

+
+
+add_middleware(middleware_cls, **middleware_config)[source]
+

Add ASGI middleware to the application.

+

Middleware wraps the entire application and can inspect or modify +every request and response. Middleware is applied in reverse order — +the last middleware added runs first.

+
+
Parameters:
+
    +
  • middleware_cls – A Starlette-compatible middleware class.

  • +
  • middleware_config – Keyword arguments passed to the middleware constructor.

  • +
+
+
+

Usage:

+
from starlette.middleware.httpsredirect import HTTPSRedirectMiddleware
+api.add_middleware(HTTPSRedirectMiddleware)
+
+
+
+
add_route(route=None, endpoint=None, *, default=False, static=True, check_existing=True, websocket=False, before_request=False, methods=None)[source]
@@ -108,6 +130,27 @@ Also, it will become a default route.

+
+
+before_request(websocket=False)[source]
+

Register a function to run before every request.

+

If the hook sets resp.status_code, the route handler is skipped +and the response is sent immediately (short-circuiting).

+
+
Parameters:
+

websocket – If True, register as a WebSocket before-request hook instead of HTTP.

+
+
+

Usage:

+
@api.before_request()
+def check_auth(req, resp):
+    if "Authorization" not in req.headers:
+        resp.status_code = 401
+        resp.media = {"error": "unauthorized"}
+
+
+
+
exception_handler(exception_cls)[source]
@@ -261,6 +304,17 @@ representing the HTTP status code of the redirect.

+
+
+run(**kwargs)[source]
+

Run the application. Shorthand for serve() that inherits the debug setting.

+
+
Parameters:
+

kwargs – Keyword arguments passed through to serve().

+
+
+
+
schema(name, **options)[source]
@@ -304,6 +358,12 @@ able to send HTTP requests to the Responder application.

+
+
+property static_app
+

The Starlette StaticFiles application for serving static assets.

+
+
template(filename, *args, **kwargs)[source]
@@ -361,7 +421,11 @@ because it involves I/O.

class responder.Request(scope, receive, api=None, formats=None)[source]
-
+

An HTTP request, passed to each view as the first argument.

+

Provides access to headers, cookies, query parameters, the request body, +session data, and more. Most properties are synchronous; reading the body +(via content, text, or media()) requires await.

+
accepts(content_type)[source]

Returns True if the incoming Request accepts the given content_type.

@@ -416,6 +480,12 @@ because it involves I/O.

Returns True if the request content type is JSON.

+
+
+property is_secure
+

True if the request was made over HTTPS.

+
+
async media(format: str | Callable = None)[source]
@@ -434,6 +504,12 @@ Alternatively, accepts a custom callable for the format type.

The incoming HTTP method used for the request, lower-cased.

+
+
+property mimetype
+

The MIME type of the request body, from the Content-Type header.

+
+
property params
@@ -485,18 +561,24 @@ status code, headers, and cookies.

class responder.Response(req, *, formats)[source]
-
-
-content
-

A bytes representation of the response body.

-
- -
-
-cookies: SimpleCookie
-

The cookies set in the Response

-
- +

An HTTP response, passed to each view as the second argument.

+

Mutate this object to control what gets sent back to the client. Set +text, html, media, or content to define +the body. Use headers and set_cookie() to control metadata.

+
+
Variables:
+
    +
  • text – Set the response body as plain text (sets Content-Type: text/plain).

  • +
  • html – Set the response body as HTML (sets Content-Type: text/html).

  • +
  • media – Set a Python object (dict, list) to be serialized as JSON (or negotiated format).

  • +
  • content – Set the raw response body as bytes.

  • +
  • status_code – The HTTP status code (e.g. 200, 404). Defaults to 200 if not set.

  • +
  • headers – A dict of response headers.

  • +
  • cookies – A SimpleCookie holding cookies to set on the response.

  • +
  • session – A dict of session data. Changes are persisted in a signed cookie.

  • +
+
+
file(path, *, content_type=None)[source]
@@ -511,28 +593,52 @@ status code, headers, and cookies.

-
-
-formats
-

representing the headers of the response.

+
+
+property ok
+

True if the status code is in the 2xx range (success).

-
-
-headers
-

A Python dictionary of {key: value},

+
+
+redirect(location, *, set_text=True, status_code=301)[source]
+

Redirect the client to a different URL.

+
+
Parameters:
+
    +
  • location – The URL to redirect to.

  • +
  • set_text – If True, set a default redirect message as the body.

  • +
  • status_code – The HTTP status code (default 301).

  • +
+
+
-
-
-media
-

A Python object that will be content-negotiated and

-
- -
-
-session
-

The cookie-based session data, in dict form, to add to the Response.

+
+ +

Set a cookie on the response with full control over directives.

+
+
Parameters:
+
    +
  • key – The cookie name.

  • +
  • value – The cookie value.

  • +
  • expires – Expiration date string (e.g. "Thu, 01 Jan 2026 00:00:00 GMT").

  • +
  • path – URL path the cookie applies to (default "/").

  • +
  • domain – Domain the cookie is valid for.

  • +
  • max_age – Maximum age in seconds before the cookie expires.

  • +
  • secure – If True, cookie is only sent over HTTPS.

  • +
  • httponly – If True (default), cookie is inaccessible to JavaScript.

  • +
+
+
+

Usage:

+
resp.set_cookie(
+    "token", value="abc123",
+    max_age=3600, secure=True, httponly=True,
+)
+
+
@@ -552,10 +658,32 @@ status code, headers, and cookies.

Yielding a string is treated as data.

-
-
-status_code: int | None
-

The HTTP Status Code to use for the Response.

+
+
+property status_code_safe: int
+

Return the status code, raising RuntimeError if it hasn’t been set.

+
+ +
+
+stream(func, *args, **kwargs)[source]
+

Set up a streaming response from an async generator function.

+

The generator yields chunks of bytes that are sent to the client +as they are produced, without buffering the full response in memory.

+

Usage:

+
@api.route("/stream")
+async def stream_data(req, resp):
+    @resp.stream
+    async def body():
+        for i in range(10):
+            yield f"chunk {i}\n".encode()
+
+
+
+
Parameters:
+

func – An async generator function that yields response chunks.

+
+
@@ -575,6 +703,149 @@ Yielding a string is treated as data.

+ +
+

Route Groups

+

Group related routes under a shared URL prefix — useful for API versioning +and organizing large applications.

+
+
+class responder.api.RouteGroup(api, prefix)[source]
+

A group of routes with a shared URL prefix.

+
+ +
+
+

Background Queue

+

Run tasks in background threads without blocking the response. Available +as api.background.

+
+
+class responder.background.BackgroundQueue(n=None)[source]
+

A queue for running tasks in background threads.

+

Uses a ThreadPoolExecutor sized to the number of CPUs. Access it +via api.background.

+

Usage:

+
# As a decorator — fire and forget
+@api.background.task
+def send_email(to, subject):
+    ...
+
+send_email("user@example.com", "Hello")
+
+# Direct submission
+future = api.background.run(send_email, "user@example.com", "Hello")
+
+# As a callable (supports async functions)
+await api.background(send_email, "user@example.com", "Hello")
+
+
+
+
+run(f, *args, **kwargs)[source]
+

Submit a function to run in a background thread.

+
+
Parameters:
+

f – The function to run.

+
+
Returns:
+

A concurrent.futures.Future for the result.

+
+
+
+ +
+
+task(f)[source]
+

Decorator that wraps a function to run in the background thread pool.

+

The decorated function returns a Future instead of blocking. +Exceptions are printed to stderr via traceback.

+
+
Parameters:
+

f – The function to wrap.

+
+
+
+ +
+ +
+
+

Query Dict

+

A dictionary subclass for query string parameters with multi-value support.

+
+
+class responder.models.QueryDict(query_string)[source]
+

A dictionary for query string parameters that handles multi-value keys.

+

Single-value access returns the last value for a key. Use get_list() +to retrieve all values for a multi-value parameter.

+
+
+get(key, default=None)[source]
+

Return the last data value for the passed key. If key doesn’t exist +or value is an empty list, return default.

+
+ +
+
+get_list(key, default=None)[source]
+

Return the list of values for the key. If key doesn’t exist, return a +default value.

+
+ +
+
+items()[source]
+

Yield (key, value) pairs, where value is the last item in the list +associated with the key.

+
+ +
+
+items_list()[source]
+

Yield (key, value) pairs, where value is the the list.

+
+ +
+ +
+
+

Rate Limiter

+

In-memory token bucket rate limiter. Limits requests per client IP address +and returns 429 Too Many Requests when exceeded.

+
+
+class responder.ext.ratelimit.RateLimiter(requests=100, period=60)[source]
+

Token bucket rate limiter.

+

Usage:

+
from responder.ext.ratelimit import RateLimiter
+
+limiter = RateLimiter(requests=100, period=60)  # 100 req/min
+
+@api.route(before_request=True)
+def rate_limit(req, resp):
+    limiter.check(req, resp)
+
+
+

Or use the shorthand:

+
limiter = RateLimiter(requests=100, period=60)
+limiter.install(api)
+
+
+
+
+check(req, resp)[source]
+

Check rate limit. Sets 429 status if exceeded.

+
+ +
+
+install(api)[source]
+

Install as a before_request hook on the API.

+
+ +
+

Status Code Helpers

@@ -635,8 +906,10 @@ into. Useful in middleware and after-request hooks.

  • The API Class
  • -
    -

    v3.0.0 - 2026-03-22

    +
    +

    [v3.2.0] - 2026-03-22

    Added

      +
    • Pydantic auto-validation: request_model validates input, returns 422 on failure

    • +
    • Pydantic auto-serialization: response_model strips extra fields from responses

    • +
    • Server-Sent Events: @resp.sse for real-time streaming

    • +
    • resp.stream_file() for streaming large files without loading into memory

    • +
    • @api.after_request() hooks

    • +
    • api.group("/prefix") for route groups and API versioning

    • +
    • api.graphql("/path", schema=schema) one-liner GraphQL setup

    • +
    • api = responder.API(request_id=True) for automatic request ID generation

    • +
    • Built-in rate limiter: RateLimiter(requests=100, period=60).install(api)

    • +
    • MessagePack format support: await req.media("msgpack")

    • +
    • req.is_json, req.path_params, req.client properties

    • +
    • api.exception_handler() decorator for custom error handling

    • +
    • Lifespan context manager support

    • +
    • uuid and path route convertors

    • +
    • PEP 561 py.typed marker

    • +
    • Pydantic support for OpenAPI schema generation

    • +
    +
    +
    +

    Changed

    +
      +
    • Dependencies flattened: pip install responder gets everything

    • +
    • Core deps reduced to starlette + uvicorn

    • +
    • TestClient lazy-loaded (no httpx import in production)

    • +
    • Before-request hooks can short-circuit by setting status code

    • +
    • Removed poethepoet task runner

    • +
    +
    +
    +

    Fixed

    +
      +
    • Multipart parser losing headers when parts have multiple headers

    • +
    • url_for() with typed route params ({id:int})

    • +
    • resp.body encoding crash on bytes content

    • +
    • GraphQL text query missing await

    • +
    • Streaming responses not sending Content-Type headers

    • +
    • Python 3.9 compatibility for union type syntax

    • +
    +
    +
    +
    +

    v3.0.0 - 2026-03-22

    +
    +

    Added

    +
    • Platform: Added support for Python 3.10 - Python 3.13

    • CLI: responder run now also accepts a filesystem path on its <target> argument, enabling usage on single-file applications.

    • CLI: responder run now also accepts URLs.

    -
    -

    Changed

    +
    +

    Changed

    • Platform: Minimum Python version is now 3.9 (dropped 3.6, 3.7, 3.8)

    • Dependencies: Dramatically reduced core dependency count (10 → 5)

      @@ -91,8 +136,8 @@ aliases for HTTP 308 (marked for removal in 3.0)

    • CLI: responder run --build ceased to exist

    -
    -

    Fixed

    +
    +

    Fixed

    • Routing: Fixed dispatching static_route=None on Windows

    • uvicorn: --debug now maps to uvicorn’s log_level = "debug"

    • @@ -102,8 +147,8 @@ aliases for HTTP 308 (marked for removal in 3.0)

    v2.0.5 - 2019-12-15

    -
    -

    Added

    +
    +

    Added

    • Update requirements to support python 3.8

    @@ -111,8 +156,8 @@ aliases for HTTP 308 (marked for removal in 3.0)

    v2.0.4 - 2019-11-19

    -
    -

    Fixed

    +
    +

    Fixed

    • Fix static app resolving

    @@ -120,8 +165,8 @@ aliases for HTTP 308 (marked for removal in 3.0)

    v2.0.3 - 2019-09-20

    -
    -

    Fixed

    +
    +

    Fixed

    • Fix template conflicts

    @@ -129,8 +174,8 @@ aliases for HTTP 308 (marked for removal in 3.0)

    v2.0.2 - 2019-09-20

    -
    -

    Fixed

    +
    +

    Fixed

    • Fix template conflicts

    @@ -138,8 +183,8 @@ aliases for HTTP 308 (marked for removal in 3.0)

    v2.0.1 - 2019-09-20

    -
    -

    Fixed

    +
    +

    Fixed

    • Fix template import

    @@ -147,8 +192,8 @@ aliases for HTTP 308 (marked for removal in 3.0)

    v2.0.0 - 2019-09-19

    -
    -

    Changed

    +
    +

    Changed

    • Refactor Router and Schema

    @@ -156,8 +201,8 @@ aliases for HTTP 308 (marked for removal in 3.0)

    v1.3.2 - 2019-08-15

    -
    -

    Added

    +
    +

    Added

    • ASGI 3 support

    • CI tests for python 3.8-dev

    • @@ -173,15 +218,15 @@ aliases for HTTP 308 (marked for removal in 3.0)

    v1.3.1 - 2019-04-28

    -
    -

    Added

    +
    +

    Added

    • Route params Converters

    • Add search for documentation pages

    -
    -

    Changed

    +
    +

    Changed

    • Bump dependencies

    @@ -189,8 +234,8 @@ aliases for HTTP 308 (marked for removal in 3.0)

    v1.3.0 - 2019-02-22

    -
    -

    Fixed

    +
    +

    Fixed

    • Versioning issue

    • Multiple cookies.

    • @@ -198,8 +243,8 @@ aliases for HTTP 308 (marked for removal in 3.0)

    • Other bugfixes.

    -
    -

    Added

    +
    +

    Added

    • Stream support via resp.stream.

    • Cookie directives via resp.set_cookie.

    • @@ -210,14 +255,14 @@ aliases for HTTP 308 (marked for removal in 3.0)

    v1.1.3 - 2019-01-12

    -
    -

    Changed

    +
    +

    Changed

    • Refactor _route_for

    -
    -

    Fixed

    +
    +

    Fixed

    • Resolve startup/shutdwown events

    @@ -225,21 +270,21 @@ aliases for HTTP 308 (marked for removal in 3.0)

    v1.2.0 - 2018-12-29

    -
    -

    Added

    +
    +

    Added

    • Documentations

    -
    -

    Changed

    +
    +

    Changed

    • Use Starlette’s LifeSpan middleware

    • Update denpendencies

    -
    -

    Fixed

    +
    +

    Fixed

    • Fix route.is_class_based

    • Fix test_500

    • @@ -249,8 +294,8 @@ aliases for HTTP 308 (marked for removal in 3.0)

    v1.1.2 - 2018-11-11

    -
    -

    Fixed

    +
    +

    Fixed

    • Minor fixes for Open API

    • Typos

    • @@ -259,8 +304,8 @@ aliases for HTTP 308 (marked for removal in 3.0)

    v1.1.1 - 2018-10-29

    -
    -

    Changed

    +
    +

    Changed

    • Run sync views in a threadpoolexecutor.

    @@ -268,8 +313,8 @@ aliases for HTTP 308 (marked for removal in 3.0)

    v1.1.0 - 2018-10-27

    -
    -

    Added

    +
    +

    Added

    • Support for before_request.

    @@ -277,8 +322,8 @@ aliases for HTTP 308 (marked for removal in 3.0)

    v1.0.5- 2018-10-27

    -
    -

    Fixed

    +
    +

    Fixed

    • Fix sessions.

    @@ -286,8 +331,8 @@ aliases for HTTP 308 (marked for removal in 3.0)

    v1.0.4 - 2018-10-27

    -
    -

    Fixed

    +
    +

    Fixed

    • Potential bufix for cookies.

    @@ -295,8 +340,8 @@ aliases for HTTP 308 (marked for removal in 3.0)

    v1.0.3 - 2018-10-27

    -
    -

    Fixed

    +
    +

    Fixed

    • Bugfix for redirects.

    @@ -304,8 +349,8 @@ aliases for HTTP 308 (marked for removal in 3.0)

    v1.0.2 - 2018-10-27

    -
    -

    Changed

    +
    +

    Changed

    • Improvement for static file hosting.

    @@ -313,8 +358,8 @@ aliases for HTTP 308 (marked for removal in 3.0)

    v1.0.1 - 2018-10-26

    -
    -

    Changed

    +
    +

    Changed

    • Improve cors configuration settings.

    @@ -322,8 +367,8 @@ aliases for HTTP 308 (marked for removal in 3.0)

    v1.0.0 - 2018-10-26

    -
    -

    Changed

    +
    +

    Changed

    • Move GraphQL support into a built-in plugin.

    @@ -331,14 +376,14 @@ aliases for HTTP 308 (marked for removal in 3.0)

    v0.3.3 - 2018-10-25

    -
    -

    Added

    +
    +

    Added

    • CORS support

    -
    -

    Changed

    +
    +

    Changed

    • Improved exceptions.

    @@ -346,8 +391,8 @@ aliases for HTTP 308 (marked for removal in 3.0)

    v0.3.2 - 2018-10-25

    -
    -

    Changed

    +
    +

    Changed

    • Subtle improvements.

    @@ -355,8 +400,8 @@ aliases for HTTP 308 (marked for removal in 3.0)

    v0.3.1 - 2018-10-24

    -
    -

    Fixed

    +
    +

    Fixed

    • Packaging fix.

    @@ -364,8 +409,8 @@ aliases for HTTP 308 (marked for removal in 3.0)

    v0.3.0 - 2018-10-24

    -
    -

    Changed

    +
    +

    Changed

    • Interactive Documentation endpoint.

    • Minor improvements.

    • @@ -374,8 +419,8 @@ aliases for HTTP 308 (marked for removal in 3.0)

    v0.2.3 - 2018-10-24

    -
    -

    Changed

    +
    +

    Changed

    • Overall improvements.

    @@ -383,8 +428,8 @@ aliases for HTTP 308 (marked for removal in 3.0)

    v0.2.2 - 2018-10-23

    -
    -

    Added

    +
    +

    Added

    • Show traceback info when background tasks raise exceptions.

    @@ -392,8 +437,8 @@ aliases for HTTP 308 (marked for removal in 3.0)

    v0.2.1 - 2018-10-23

    -
    -

    Added

    +
    +

    Added

    • api.requests.

    @@ -401,8 +446,8 @@ aliases for HTTP 308 (marked for removal in 3.0)

    v0.2.0 - 2018-10-22

    -
    -

    Added

    +
    +

    Added

    • WebSocket support.

    @@ -410,8 +455,8 @@ aliases for HTTP 308 (marked for removal in 3.0)

    v0.1.6 - 2018-10-20

    -
    -

    Added

    +
    +

    Added

    • 500 support.

    @@ -419,14 +464,14 @@ aliases for HTTP 308 (marked for removal in 3.0)

    v0.1.5 - 2018-10-20

    -
    -

    Added

    +
    +

    Added

    • File upload support

    -
    -

    Changed

    +
    +

    Changed

    • Improvements to sequential media reading.

    @@ -434,8 +479,8 @@ aliases for HTTP 308 (marked for removal in 3.0)

    v0.1.4 - 2018-10-19

    -
    -

    Fixed

    +
    +

    Fixed

    • Stability.

    @@ -443,8 +488,8 @@ aliases for HTTP 308 (marked for removal in 3.0)

    v0.1.3 - 2018-10-18

    -
    -

    Added

    +
    +

    Added

    • Sessions support.

    @@ -452,8 +497,8 @@ aliases for HTTP 308 (marked for removal in 3.0)

    v0.1.2 - 2018-10-18

    -
    -

    Added

    +
    +

    Added

    • Cookies support.

    @@ -461,8 +506,8 @@ aliases for HTTP 308 (marked for removal in 3.0)

    v0.1.1 - 2018-10-17

    -
    -

    Changed

    +
    +

    Changed

    • Default routes.

    @@ -470,8 +515,8 @@ aliases for HTTP 308 (marked for removal in 3.0)

    v0.1.0 - 2018-10-17

    -
    -

    Added

    +
    +

    Added

    • Prototype of static application support.

    @@ -479,8 +524,8 @@ aliases for HTTP 308 (marked for removal in 3.0)

    v0.0.10 - 2018-10-17

    -
    -

    Fixed

    +
    +

    Fixed

    • Bugfix for async class-based views.

    @@ -488,8 +533,8 @@ aliases for HTTP 308 (marked for removal in 3.0)

    v0.0.9 - 2018-10-17

    -
    -

    Fixed

    +
    +

    Fixed

    • Bugfix for async class-based views.

    @@ -497,14 +542,14 @@ aliases for HTTP 308 (marked for removal in 3.0)

    v0.0.8 - 2018-10-17

    -
    -

    Added

    +
    +

    Added

    • GraphiQL Support.

    -
    -

    Changed

    +
    +

    Changed

    • Improvement to route selection.

    @@ -512,8 +557,8 @@ aliases for HTTP 308 (marked for removal in 3.0)

    v0.0.7 - 2018-10-16

    -
    -

    Changed

    +
    +

    Changed

    • Immutable Request object.

    @@ -521,8 +566,8 @@ aliases for HTTP 308 (marked for removal in 3.0)

    v0.0.6 - 2018-10-16

    -
    -

    Added

    +
    +

    Added

    • Ability to mount WSGI apps.

    • Supply content-type when serving up the schema.

    • @@ -531,8 +576,8 @@ aliases for HTTP 308 (marked for removal in 3.0)

    v0.0.5 - 2018-10-15

    -
    -

    Added

    +
    +

    Added

    • OpenAPI Schema support.

    • Safe load/dump yaml.

    • @@ -541,14 +586,14 @@ aliases for HTTP 308 (marked for removal in 3.0)

    v0.0.4 - 2018-10-15

    -
    -

    Added

    +
    +

    Added

    • Asynchronous support for data uploads.

    -
    -

    Fixed

    +
    +

    Fixed

    • Bug fixes.

    @@ -556,8 +601,8 @@ aliases for HTTP 308 (marked for removal in 3.0)

    v0.0.3 - 2018-10-13

    -
    -

    Fixed

    +
    +

    Fixed

    • Bug fixes.

    @@ -565,8 +610,8 @@ aliases for HTTP 308 (marked for removal in 3.0)

    v0.0.2 - 2018-10-13

    -
    -

    Changed

    +
    +

    Changed

    • Switch to ASGI/Starlette.

    @@ -574,8 +619,8 @@ aliases for HTTP 308 (marked for removal in 3.0)

    v0.0.1 - 2018-10-12

    -
    -

    Added

    +
    +

    Added

    • Conception!

    @@ -608,201 +653,207 @@ aliases for HTTP 308 (marked for removal in 3.0)

    • Changelog
      • Unreleased
      • -
      • v3.0.0 - 2026-03-22
          +
        • [v3.2.0] - 2026-03-22
        • -
        • v2.0.5 - 2019-12-15
            +
          • v3.0.0 - 2026-03-22 -
          • -
          • v2.0.4 - 2019-11-19 -
          • -
          • v2.0.3 - 2019-09-20
          • -
          • v2.0.2 - 2019-09-20
              -
            • Fixed
            • +
            • v2.0.5 - 2019-12-15
            • -
            • v2.0.1 - 2019-09-20
                +
              • v2.0.4 - 2019-11-19
              • +
              • v2.0.3 - 2019-09-20 +
              • +
              • v2.0.2 - 2019-09-20 +
              • +
              • v2.0.1 - 2019-09-20 +
              • v2.0.0 - 2019-09-19
              • v1.3.2 - 2019-08-15
              • v1.3.1 - 2019-04-28
              • v1.3.0 - 2019-02-22
              • v1.1.3 - 2019-01-12 -
              • -
              • v1.2.0 - 2018-12-29
              • -
              • v1.1.2 - 2018-11-11 -
              • -
              • v1.1.1 - 2018-10-29
                  +
                • v1.2.0 - 2018-12-29
                • -
                • v1.1.0 - 2018-10-27 -
                • -
                • v1.0.5- 2018-10-27
                    +
                  • v1.1.2 - 2018-11-11
                  • +
                  • v1.1.1 - 2018-10-29 +
                  • +
                  • v1.1.0 - 2018-10-27 +
                  • +
                  • v1.0.5- 2018-10-27 +
                  • v1.0.4 - 2018-10-27
                  • v1.0.3 - 2018-10-27
                  • v1.0.2 - 2018-10-27
                  • v1.0.1 - 2018-10-26 -
                  • -
                  • v1.0.0 - 2018-10-26 -
                  • -
                  • v0.3.3 - 2018-10-25
                  • -
                  • v0.3.2 - 2018-10-25
                      +
                    • v1.0.0 - 2018-10-26
                    • -
                    • v0.3.1 - 2018-10-24 -
                    • -
                    • v0.3.0 - 2018-10-24 @@ -128,10 +136,14 @@

                      G

                      @@ -141,30 +153,34 @@

                      I

                      - +
                      @@ -172,11 +188,11 @@

                      M

                      - +
                      • sse() (responder.Response method)
                      • state (responder.Request property)
                      • -
                      • status_code (responder.Response attribute) +
                      • static_app (responder.API property) +
                      • +
                      • status_code_safe (responder.Response property) +
                      • +
                      • stream() (responder.Response method)
                      • stream_file() (responder.Response method)
                      • @@ -270,6 +314,8 @@

                        T

                        diff --git a/guide-config.html b/guide-config.html new file mode 100644 index 0000000..92fae7a --- /dev/null +++ b/guide-config.html @@ -0,0 +1,264 @@ + + + + + + + + Configuration — responder 3.4.1 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + +
                        +
                        +
                        + + +
                        + +
                        +

                        Configuration

                        +

                        Every application needs different settings for different environments — +debug mode in development, real secrets in production, different database +URLs for testing. This guide covers how to manage configuration cleanly.

                        +
                        +

                        Environment Variables

                        +

                        The simplest and most universal approach. Environment variables work +everywhere — locally, in Docker, on cloud platforms — and keep secrets +out of your source code:

                        +
                        import os
                        +import responder
                        +
                        +api = responder.API(
                        +    debug=os.getenv("DEBUG", "false").lower() == "true",
                        +    secret_key=os.environ["SECRET_KEY"],
                        +    cors=os.getenv("CORS_ENABLED", "false").lower() == "true",
                        +)
                        +
                        +
                        +

                        Some variables Responder handles automatically:

                        +
                          +
                        • PORT — when set, the server binds to 0.0.0.0 on this port

                        • +
                        +

                        Set variables in your shell:

                        +
                        $ export SECRET_KEY="your-secret-here"
                        +$ export DEBUG=true
                        +$ python app.py
                        +
                        +
                        +

                        Or in a .env file (don’t commit this to git):

                        +
                        SECRET_KEY=your-secret-here
                        +DEBUG=true
                        +
                        +
                        +
                        +
                        +

                        Using .env Files

                        +

                        For local development, a .env file is convenient. Install +python-dotenv and load it at the top of your app:

                        +
                        $ uv pip install python-dotenv
                        +
                        +
                        +
                        from dotenv import load_dotenv
                        +load_dotenv()
                        +
                        +import os
                        +import responder
                        +
                        +api = responder.API(
                        +    secret_key=os.environ["SECRET_KEY"],
                        +)
                        +
                        +
                        +

                        Add .env to your .gitignore — never commit secrets.

                        +
                        +
                        +

                        Configuration Class Pattern

                        +

                        For larger applications, a configuration class keeps things organized:

                        +
                        import os
                        +
                        +class Config:
                        +    SECRET_KEY = os.environ.get("SECRET_KEY", "dev-secret")
                        +    DEBUG = os.environ.get("DEBUG", "false").lower() == "true"
                        +    DATABASE_URL = os.environ.get("DATABASE_URL", "sqlite:///dev.db")
                        +    CORS_ORIGINS = os.environ.get("CORS_ORIGINS", "").split(",")
                        +
                        +config = Config()
                        +
                        +api = responder.API(
                        +    debug=config.DEBUG,
                        +    secret_key=config.SECRET_KEY,
                        +    cors=bool(config.CORS_ORIGINS[0]),
                        +    cors_params={"allow_origins": config.CORS_ORIGINS},
                        +)
                        +
                        +
                        +

                        This makes it easy to see all your settings in one place.

                        +
                        +
                        +

                        Secret Key

                        +

                        The secret_key is used to sign session cookies. If someone knows your +secret key, they can forge session data and impersonate any user.

                        +

                        Rules:

                        +
                          +
                        • Never use the default in production

                        • +
                        • Generate a random key: python -c "import secrets; print(secrets.token_hex(32))"

                        • +
                        • Store it in an environment variable, not in code

                        • +
                        • Rotate it if it’s ever compromised (this invalidates all sessions)

                        • +
                        +
                        api = responder.API(secret_key=os.environ["SECRET_KEY"])
                        +
                        +
                        +
                        +
                        +

                        Debug Mode

                        +

                        Debug mode controls error page behavior:

                        +
                          +
                        • On (debug=True): detailed error pages with tracebacks. Never +use this in production — it exposes your source code.

                        • +
                        • Off (debug=False): generic error pages. This is the default.

                        • +
                        +
                        api = responder.API(debug=True)  # development only
                        +
                        +
                        +

                        A common pattern is to read it from the environment:

                        +
                        api = responder.API(debug=os.getenv("DEBUG") == "true")
                        +
                        +
                        +
                        +
                        +

                        Allowed Hosts

                        +

                        In production, always set allowed_hosts to prevent Host header +attacks. This should match the domain names your application serves:

                        +
                        api = responder.API(
                        +    allowed_hosts=["example.com", "www.example.com"],
                        +)
                        +
                        +
                        +

                        In development, you can use ["*"] (the default) or specific local +addresses:

                        +
                        api = responder.API(allowed_hosts=["localhost", "127.0.0.1"])
                        +
                        +
                        +
                        +
                        +

                        Putting It All Together

                        +

                        A production-ready configuration setup:

                        +
                        import os
                        +from dotenv import load_dotenv
                        +
                        +load_dotenv()
                        +
                        +import responder
                        +
                        +api = responder.API(
                        +    debug=os.getenv("DEBUG", "false") == "true",
                        +    secret_key=os.environ["SECRET_KEY"],
                        +    allowed_hosts=os.getenv("ALLOWED_HOSTS", "*").split(","),
                        +    cors=bool(os.getenv("CORS_ORIGINS")),
                        +    cors_params={
                        +        "allow_origins": os.getenv("CORS_ORIGINS", "").split(","),
                        +        "allow_methods": ["GET", "POST", "PUT", "DELETE"],
                        +    },
                        +)
                        +
                        +
                        +

                        With a .env file for local development:

                        +
                        SECRET_KEY=dev-secret-do-not-use-in-prod
                        +DEBUG=true
                        +ALLOWED_HOSTS=localhost,127.0.0.1
                        +CORS_ORIGINS=http://localhost:3000
                        +
                        +
                        +

                        And environment variables set properly in production (via your cloud +platform’s dashboard, Docker secrets, or a secrets manager).

                        +
                        +
                        + + +
                        + +
                        +
                        + +
                        +
                        + + + + + + + \ No newline at end of file diff --git a/index.html b/index.html index f07f730..91fa4f0 100644 --- a/index.html +++ b/index.html @@ -5,13 +5,13 @@ - Responder — responder 3.2.0 documentation + Responder — responder 3.4.1 documentation - + @@ -114,7 +114,7 @@ work with — welcome.

                        $ uv pip install responder
                         
                        -

                        Python 3.9 and above. That’s it.

                        +

                        Python 3.10 and above. That’s it.

                        diff --git a/objects.inv b/objects.inv index c9383f04783f60b731aae156f7a830614c871529..88bec76b1d4a3ed9341e1a140dad1e7add8aa946 100644 GIT binary patch delta 1003 zcmViJY3p77A&OgqECRP4|f@h?}=$kK@4p{ zr(KJJiYcHb9zR@#cKBY&9+Wv=VI-MjyI82k!wM3O2K5Z_V68EHqTz-ZMoZH7@m?_? zdQRdUGvZ5a6ziH;npM2Se-w&=Z>J=?Qf>mWAk^iVPEcN;kFdyKk%ErODjejx$3{Bk zEM!FjM|NffNgf#JG}5{=)t2)T?NpbflQa*wU6s0k_Kx1ry-suu&|Jn&%Qmz zjIGa=c-RwqaBWgo6`xMS2MZQ{i5%M}{6vEx`VgZ6)2dLIjhqQ)iY<=r+{ibTR}Szd zx4_oCfAe^j%IPYd9>z=Nyf7e-^g@#mDH0kdW+$16G0>&SReq1Q80H-6Ou zUCxRTc2UE5seDUCz|D2cs)lx--S;;)PETz+>RvN%n}1IHeJ$~iwZuQy694)+5huAe z)rU&bxhHd1n6^*@_L3Abm*!kHb7T;C^d~>bD82_9?CNH?e<1R>&%0$`r~DQbFv5S2&2@)Z{09!EURFH zO>E5;2b{}C+uYbj&@e{KA5BvTx49=(@-QqG)?Y z8)Sa3onOBv4P*vufa~^Wb_J2gKKe;!q*V(L&OPEQU@~B1{fLsxSR)l9d_$~h7x?)? z2!9-**^K(TJ|SxEzG|1a!%DbJ*0>l!%WEY?{?)BaT`Fe3f-dQqmc6q76dP21JINnBdQd*vT5YMGY3u79;tw0pSw=%tgQAF$Vw Z9>C~}il*goCfM(WdHxt6+5a!#`N{f0@Du<5 delta 785 zcmV+s1Md9N2>Aw(KLau@Fp)w!f1Q_2Z{r{khVT9rmUgd++WolnwqKPhb)`1xo-KmM zF&i)haMk?#9Sn|fn{FUCGrZ3L!wg^zM#-)QU8=*4kaf?Yyef%e%hn41!CMv|%SE9_ zXg_9|5@WZxyP0H;30H&w5QZ7V@6ZNcOPSVPS;P@AqFw!%2Q(o%u8 zhciUZbPTRQkYqLJ=XBR#4CX|t+=5V?q|bcRSH^1AZBwyc^Qw_a8M>OP;7pAM<&scW z2qwe%k|;&At8D0~tiwXie{b}NQ_e!#W-zj|7eI2yz~n)ft*PlbuW+C8s1^t|GbhMQ z_1E|uO@{=QFv;2DpvxKrvw{ed%iyVW2^f`X24q9ErXv?4ktj>X=#L2=;UL;(qfAyxq!vwO2vKok} zQiJczvv=7dlFpxQF^2Cu;O6a(ahe`wCq2AQDDUw2(G9@~)S$RL2zMAo)MWMW&ttpTLdP&3 zFN2(u4R8mHRxiJEpT#5#UL(b73~M3WJ^jX?IxNNx5B&CjHr{j8dj@+rVAXYVdfzj; z!`;-gB~MmQKDu_fc80=W;5Kr$mS7sg^Ng`qLloD(W5yike-~4jB_}x`nzpa7!RE(W z`~C;Ag~DPjyGKqmuVC`pC*LTn?Db59ZLhcmOll3~6Iu$}Td5i0iw5g|Hv?upVMiGL zL=D3?T8i@4^-M0bJ7!LK(8H5y$nBo-;f+Sh)vxuFtBi>^drr9fML3-FGIe`je~fdq Pe!TzYt;Iiv0|8L0n_7xk diff --git a/py-modindex.html b/py-modindex.html index 845c0b7..dc59a5a 100644 --- a/py-modindex.html +++ b/py-modindex.html @@ -4,13 +4,13 @@ - Python Module Index — responder 3.2.0 documentation + Python Module Index — responder 3.4.1 documentation - + diff --git a/quickstart.html b/quickstart.html index 5c8e60f..82a22de 100644 --- a/quickstart.html +++ b/quickstart.html @@ -5,13 +5,13 @@ - Quick Start — responder 3.2.0 documentation + Quick Start — responder 3.4.1 documentation - + @@ -342,6 +342,51 @@ work will block the event loop. For heavy computation, consider a proper task queue.

                        +
                        +

                        Putting It All Together

                        +

                        Here’s a complete, working Responder application that combines everything +from this guide:

                        +
                        import responder
                        +
                        +api = responder.API()
                        +
                        +@api.route("/")
                        +def index(req, resp):
                        +    resp.text = "Welcome to the API"
                        +
                        +@api.route("/hello/{name}")
                        +def greet(req, resp, *, name):
                        +    resp.media = {"message": f"hello, {name}!"}
                        +
                        +@api.route("/add/{a:int}/{b:int}")
                        +def add(req, resp, *, a, b):
                        +    resp.media = {"result": a + b}
                        +
                        +@api.route("/echo", methods=["POST"])
                        +async def echo(req, resp):
                        +    data = await req.media()
                        +    resp.media = {"received": data}
                        +
                        +if __name__ == "__main__":
                        +    api.run()
                        +
                        +
                        +

                        Save this as app.py, run it with python app.py, and try:

                        +
                        $ curl http://localhost:5042/
                        +$ curl http://localhost:5042/hello/world
                        +$ curl http://localhost:5042/add/3/4
                        +$ curl -X POST http://localhost:5042/echo \
                        +    -H "Content-Type: application/json" -d '{"key": "value"}'
                        +
                        +
                        +

                        From here, explore the Feature Tour for the full range of features, or +jump into the tutorials:

                        + +
                        @@ -379,6 +424,7 @@ task queue.

                      • Reading Requests
                      • Rendering Templates
                      • Background Tasks
                      • +
                      • Putting It All Together
                      • diff --git a/sandbox.html b/sandbox.html index 9dd4113..e71e9a8 100644 --- a/sandbox.html +++ b/sandbox.html @@ -5,13 +5,13 @@ - Development Sandbox — responder 3.2.0 documentation + Development Sandbox — responder 3.4.1 documentation - + diff --git a/search.html b/search.html index 48d3503..6b397a9 100644 --- a/search.html +++ b/search.html @@ -4,14 +4,14 @@ - Search — responder 3.2.0 documentation + Search — responder 3.4.1 documentation - + diff --git a/searchindex.js b/searchindex.js index 1aad1cb..7c4cb80 100644 --- a/searchindex.js +++ b/searchindex.js @@ -1 +1 @@ -Search.setIndex({"alltitles":{"API Reference":[[0,null]],"Added":[[2,"added"],[2,"id1"],[2,"id7"],[2,"id8"],[2,"id11"],[2,"id14"],[2,"id19"],[2,"id26"],[2,"id32"],[2,"id33"],[2,"id34"],[2,"id35"],[2,"id36"],[2,"id39"],[2,"id40"],[2,"id42"],[2,"id45"],[2,"id48"],[2,"id49"],[2,"id50"],[2,"id54"]],"After-Request Hooks":[[9,"after-request-hooks"]],"Background Tasks":[[6,"background-tasks"]],"Backlog":[[1,null]],"Before-Request Hooks":[[9,"before-request-hooks"]],"Blueprints \u2192 Route Groups":[[10,"blueprints-route-groups"]],"Building Frontend Assets":[[3,"building-frontend-assets"]],"Building a REST API":[[11,null]],"CORS":[[9,"cors"]],"CRUD Endpoints":[[12,"crud-endpoints"]],"Changed":[[2,"changed"],[2,"id6"],[2,"id9"],[2,"id12"],[2,"id15"],[2,"id18"],[2,"id23"],[2,"id24"],[2,"id25"],[2,"id27"],[2,"id28"],[2,"id30"],[2,"id31"],[2,"id37"],[2,"id41"],[2,"id46"],[2,"id47"],[2,"id53"]],"Changelog":[[2,null]],"Class-Based Views":[[9,"class-based-views"]],"Cloud Platforms":[[4,"cloud-platforms"]],"Command Line Interface":[[3,null]],"Cookie-Based Sessions":[[9,"cookie-based-sessions"]],"Cookies":[[9,"cookies"]],"Create a Book":[[11,"create-a-book"]],"Create a Web Service":[[6,"create-a-web-service"]],"Custom Error Handling":[[9,"custom-error-handling"]],"Custom Instance Names":[[3,"custom-instance-names"]],"Database Setup":[[12,"database-setup"]],"Define Your Models":[[11,"define-your-models"],[12,"define-your-models"]],"Delete a Book":[[11,"delete-a-book"]],"Deployment":[[4,null]],"Deprecated":[[2,"deprecated"]],"Development Sandbox":[[7,null]],"Docker":[[4,"docker"]],"Error Handling":[[11,"error-handling"]],"Feature Tour":[[9,null]],"Fixed":[[2,"fixed"],[2,"id2"],[2,"id3"],[2,"id4"],[2,"id5"],[2,"id10"],[2,"id13"],[2,"id16"],[2,"id17"],[2,"id20"],[2,"id21"],[2,"id22"],[2,"id29"],[2,"id38"],[2,"id43"],[2,"id44"],[2,"id51"],[2,"id52"]],"Future Ideas":[[1,"future-ideas"]],"Get a Single Book":[[11,"get-a-single-book"]],"Getting Started":[[8,"getting-started"]],"Gradual Migration":[[10,"gradual-migration"]],"GraphQL":[[9,"graphql"]],"HSTS":[[9,"hsts"]],"Hello World":[[6,"hello-world"]],"In-Memory Storage":[[11,"in-memory-storage"]],"Installation":[[5,"installation"],[12,"installation"]],"JSON APIs":[[10,"json-apis"]],"Launching from a File":[[3,"launching-from-a-file"]],"Launching from a Module":[[3,"launching-from-a-module"]],"Launching from a URL":[[3,"launching-from-a-url"]],"Lifespan Events":[[9,"lifespan-events"]],"Lifespan for Startup and Shutdown":[[12,"lifespan-for-startup-and-shutdown"]],"List All Books":[[11,"list-all-books"]],"MessagePack":[[9,"messagepack"]],"Method Filtering":[[9,"method-filtering"]],"Migrating from Flask":[[10,null]],"Mounting Other Apps":[[9,"mounting-other-apps"]],"OpenAPI Documentation":[[9,"openapi-documentation"]],"Operations":[[7,"operations"]],"Project":[[5,null]],"Project Setup":[[11,"project-setup"]],"Quick Reference":[[10,"quick-reference"]],"Quick Start":[[6,null]],"Rate Limiting":[[9,"rate-limiting"]],"Reading Requests":[[6,"reading-requests"]],"Removed":[[2,"removed"]],"Rendering Templates":[[6,"rendering-templates"]],"Request":[[0,"request"]],"Request ID":[[9,"request-id"]],"Responder":[[5,null]],"Response":[[0,"response"]],"Reverse Proxy":[[4,"reverse-proxy"]],"Route Groups":[[9,"route-groups"]],"Route Parameters":[[6,"route-parameters"],[10,"route-parameters"]],"Run It":[[11,"run-it"],[12,"run-it"]],"Run the Server":[[6,"run-the-server"]],"Running Locally":[[4,"running-locally"]],"Sending Responses":[[6,"sending-responses"]],"Server-Sent Events (SSE)":[[9,"server-sent-events-sse"]],"Serving Files":[[9,"serving-files"]],"Setup":[[7,"setup"]],"Static Files":[[9,"static-files"]],"Status Code Helpers":[[0,"status-code-helpers"]],"Templates":[[10,"templates"]],"Testing":[[8,null]],"Testing Before and After Hooks":[[8,"testing-before-and-after-hooks"]],"Testing Error Handling":[[8,"testing-error-handling"]],"Testing File Uploads":[[8,"testing-file-uploads"]],"Testing Headers and Cookies":[[8,"testing-headers-and-cookies"]],"Testing JSON APIs":[[8,"testing-json-apis"]],"Testing Lifespan Events":[[8,"testing-lifespan-events"]],"Testing Request Validation":[[8,"testing-request-validation"]],"Testing WebSockets":[[8,"testing-websockets"]],"The API Class":[[0,"the-api-class"]],"The Big Differences":[[10,"the-big-differences"]],"The Idea":[[5,"the-idea"]],"Tips":[[8,"tips"],[12,"tips"]],"Trusted Hosts":[[9,"trusted-hosts"]],"Try It Out":[[11,"try-it-out"]],"Tutorials":[[5,null]],"Type Convertors":[[6,"type-convertors"]],"Unreleased":[[2,"unreleased"]],"Update a Book":[[11,"update-a-book"]],"User Guide":[[5,null]],"Using Fixtures":[[8,"using-fixtures"]],"Using PostgreSQL":[[12,"using-postgresql"]],"Using SQLAlchemy":[[12,null]],"Uvicorn Directly":[[4,"uvicorn-directly"]],"WebSocket Support":[[9,"websocket-support"]],"What You Get":[[5,"what-you-get"]],"What\u2019s Next":[[11,"what-s-next"]],"v0.0.1 - 2018-10-12":[[2,"v0-0-1-2018-10-12"]],"v0.0.10 - 2018-10-17":[[2,"v0-0-10-2018-10-17"]],"v0.0.2 - 2018-10-13":[[2,"v0-0-2-2018-10-13"]],"v0.0.3 - 2018-10-13":[[2,"v0-0-3-2018-10-13"]],"v0.0.4 - 2018-10-15":[[2,"v0-0-4-2018-10-15"]],"v0.0.5 - 2018-10-15":[[2,"v0-0-5-2018-10-15"]],"v0.0.6 - 2018-10-16":[[2,"v0-0-6-2018-10-16"]],"v0.0.7 - 2018-10-16":[[2,"v0-0-7-2018-10-16"]],"v0.0.8 - 2018-10-17":[[2,"v0-0-8-2018-10-17"]],"v0.0.9 - 2018-10-17":[[2,"v0-0-9-2018-10-17"]],"v0.1.0 - 2018-10-17":[[2,"v0-1-0-2018-10-17"]],"v0.1.1 - 2018-10-17":[[2,"v0-1-1-2018-10-17"]],"v0.1.2 - 2018-10-18":[[2,"v0-1-2-2018-10-18"]],"v0.1.3 - 2018-10-18":[[2,"v0-1-3-2018-10-18"]],"v0.1.4 - 2018-10-19":[[2,"v0-1-4-2018-10-19"]],"v0.1.5 - 2018-10-20":[[2,"v0-1-5-2018-10-20"]],"v0.1.6 - 2018-10-20":[[2,"v0-1-6-2018-10-20"]],"v0.2.0 - 2018-10-22":[[2,"v0-2-0-2018-10-22"]],"v0.2.1 - 2018-10-23":[[2,"v0-2-1-2018-10-23"]],"v0.2.2 - 2018-10-23":[[2,"v0-2-2-2018-10-23"]],"v0.2.3 - 2018-10-24":[[2,"v0-2-3-2018-10-24"]],"v0.3.0 - 2018-10-24":[[2,"v0-3-0-2018-10-24"]],"v0.3.1 - 2018-10-24":[[2,"v0-3-1-2018-10-24"]],"v0.3.2 - 2018-10-25":[[2,"v0-3-2-2018-10-25"]],"v0.3.3 - 2018-10-25":[[2,"v0-3-3-2018-10-25"]],"v1.0.0 - 2018-10-26":[[2,"v1-0-0-2018-10-26"]],"v1.0.1 - 2018-10-26":[[2,"v1-0-1-2018-10-26"]],"v1.0.2 - 2018-10-27":[[2,"v1-0-2-2018-10-27"]],"v1.0.3 - 2018-10-27":[[2,"v1-0-3-2018-10-27"]],"v1.0.4 - 2018-10-27":[[2,"v1-0-4-2018-10-27"]],"v1.0.5- 2018-10-27":[[2,"v1-0-5-2018-10-27"]],"v1.1.0 - 2018-10-27":[[2,"v1-1-0-2018-10-27"]],"v1.1.1 - 2018-10-29":[[2,"v1-1-1-2018-10-29"]],"v1.1.2 - 2018-11-11":[[2,"v1-1-2-2018-11-11"]],"v1.1.3 - 2019-01-12":[[2,"v1-1-3-2019-01-12"]],"v1.2.0 - 2018-12-29":[[2,"v1-2-0-2018-12-29"]],"v1.3.0 - 2019-02-22":[[2,"v1-3-0-2019-02-22"]],"v1.3.1 - 2019-04-28":[[2,"v1-3-1-2019-04-28"]],"v1.3.2 - 2019-08-15":[[2,"v1-3-2-2019-08-15"]],"v2.0.0 - 2019-09-19":[[2,"v2-0-0-2019-09-19"]],"v2.0.1 - 2019-09-20":[[2,"v2-0-1-2019-09-20"]],"v2.0.2 - 2019-09-20":[[2,"v2-0-2-2019-09-20"]],"v2.0.3 - 2019-09-20":[[2,"v2-0-3-2019-09-20"]],"v2.0.4 - 2019-11-19":[[2,"v2-0-4-2019-11-19"]],"v2.0.5 - 2019-12-15":[[2,"v2-0-5-2019-12-15"]],"v3.0.0 - 2026-03-22":[[2,"v3-0-0-2026-03-22"]]},"docnames":["api","backlog","changes","cli","deployment","index","quickstart","sandbox","testing","tour","tutorial-flask","tutorial-rest","tutorial-sqlalchemy"],"envversion":{"sphinx":65,"sphinx.domains.c":3,"sphinx.domains.changeset":1,"sphinx.domains.citation":1,"sphinx.domains.cpp":9,"sphinx.domains.index":1,"sphinx.domains.javascript":3,"sphinx.domains.math":2,"sphinx.domains.python":4,"sphinx.domains.rst":2,"sphinx.domains.std":2,"sphinx.ext.viewcode":1},"filenames":["api.rst","backlog.md","changes.md","cli.rst","deployment.rst","index.rst","quickstart.rst","sandbox.md","testing.rst","tour.rst","tutorial-flask.rst","tutorial-rest.rst","tutorial-sqlalchemy.rst"],"indexentries":{"accepts() (responder.request method)":[[0,"responder.Request.accepts",false]],"add_event_handler() (responder.api method)":[[0,"responder.API.add_event_handler",false]],"add_route() (responder.api method)":[[0,"responder.API.add_route",false]],"after_request() (responder.api method)":[[0,"responder.API.after_request",false]],"api (class in responder)":[[0,"responder.API",false]],"apparent_encoding (responder.request property)":[[0,"responder.Request.apparent_encoding",false]],"client (responder.request property)":[[0,"responder.Request.client",false]],"content (responder.request property)":[[0,"responder.Request.content",false]],"content (responder.response attribute)":[[0,"responder.Response.content",false]],"cookies (responder.request property)":[[0,"responder.Request.cookies",false]],"cookies (responder.response attribute)":[[0,"responder.Response.cookies",false]],"encoding (responder.request property)":[[0,"responder.Request.encoding",false]],"exception_handler() (responder.api method)":[[0,"responder.API.exception_handler",false]],"file() (responder.response method)":[[0,"responder.Response.file",false]],"formats (responder.response attribute)":[[0,"responder.Response.formats",false]],"full_url (responder.request property)":[[0,"responder.Request.full_url",false]],"graphql() (responder.api method)":[[0,"responder.API.graphql",false]],"group() (responder.api method)":[[0,"responder.API.group",false]],"headers (responder.request property)":[[0,"responder.Request.headers",false]],"headers (responder.response attribute)":[[0,"responder.Response.headers",false]],"is_100() (in module responder.status_codes)":[[0,"responder.status_codes.is_100",false]],"is_200() (in module responder.status_codes)":[[0,"responder.status_codes.is_200",false]],"is_300() (in module responder.status_codes)":[[0,"responder.status_codes.is_300",false]],"is_400() (in module responder.status_codes)":[[0,"responder.status_codes.is_400",false]],"is_500() (in module responder.status_codes)":[[0,"responder.status_codes.is_500",false]],"is_json (responder.request property)":[[0,"responder.Request.is_json",false]],"media (responder.response attribute)":[[0,"responder.Response.media",false]],"media() (responder.request method)":[[0,"responder.Request.media",false]],"method (responder.request property)":[[0,"responder.Request.method",false]],"module":[[0,"module-responder",false]],"mount() (responder.api method)":[[0,"responder.API.mount",false]],"on_event() (responder.api method)":[[0,"responder.API.on_event",false]],"params (responder.request property)":[[0,"responder.Request.params",false]],"path_matches_route() (responder.api method)":[[0,"responder.API.path_matches_route",false]],"path_params (responder.request property)":[[0,"responder.Request.path_params",false]],"redirect() (responder.api method)":[[0,"responder.API.redirect",false]],"request (class in responder)":[[0,"responder.Request",false]],"requests (responder.api property)":[[0,"responder.API.requests",false]],"responder":[[0,"module-responder",false]],"response (class in responder)":[[0,"responder.Response",false]],"route() (responder.api method)":[[0,"responder.API.route",false]],"schema() (responder.api method)":[[0,"responder.API.schema",false]],"serve() (responder.api method)":[[0,"responder.API.serve",false]],"session (responder.request property)":[[0,"responder.Request.session",false]],"session (responder.response attribute)":[[0,"responder.Response.session",false]],"session() (responder.api method)":[[0,"responder.API.session",false]],"sse() (responder.response method)":[[0,"responder.Response.sse",false]],"state (responder.request property)":[[0,"responder.Request.state",false]],"status_code (responder.response attribute)":[[0,"responder.Response.status_code",false]],"stream_file() (responder.response method)":[[0,"responder.Response.stream_file",false]],"template() (responder.api method)":[[0,"responder.API.template",false]],"template_string() (responder.api method)":[[0,"responder.API.template_string",false]],"text (responder.request property)":[[0,"responder.Request.text",false]],"url (responder.request property)":[[0,"responder.Request.url",false]],"url_for() (responder.api method)":[[0,"responder.API.url_for",false]]},"objects":{"":[[0,0,0,"-","responder"]],"responder":[[0,1,1,"","API"],[0,1,1,"","Request"],[0,1,1,"","Response"]],"responder.API":[[0,2,1,"","add_event_handler"],[0,2,1,"","add_route"],[0,2,1,"","after_request"],[0,2,1,"","exception_handler"],[0,2,1,"","graphql"],[0,2,1,"","group"],[0,2,1,"","mount"],[0,2,1,"","on_event"],[0,2,1,"","path_matches_route"],[0,2,1,"","redirect"],[0,3,1,"","requests"],[0,2,1,"","route"],[0,2,1,"","schema"],[0,2,1,"","serve"],[0,2,1,"","session"],[0,2,1,"","template"],[0,2,1,"","template_string"],[0,2,1,"","url_for"]],"responder.Request":[[0,2,1,"","accepts"],[0,3,1,"","apparent_encoding"],[0,3,1,"","client"],[0,3,1,"","content"],[0,3,1,"","cookies"],[0,3,1,"","encoding"],[0,3,1,"","full_url"],[0,3,1,"","headers"],[0,3,1,"","is_json"],[0,2,1,"","media"],[0,3,1,"","method"],[0,3,1,"","params"],[0,3,1,"","path_params"],[0,3,1,"","session"],[0,3,1,"","state"],[0,3,1,"","text"],[0,3,1,"","url"]],"responder.Response":[[0,4,1,"","content"],[0,4,1,"","cookies"],[0,2,1,"","file"],[0,4,1,"","formats"],[0,4,1,"","headers"],[0,4,1,"","media"],[0,4,1,"","session"],[0,2,1,"","sse"],[0,4,1,"","status_code"],[0,2,1,"","stream_file"]],"responder.status_codes":[[0,5,1,"","is_100"],[0,5,1,"","is_200"],[0,5,1,"","is_300"],[0,5,1,"","is_400"],[0,5,1,"","is_500"]]},"objnames":{"0":["py","module","Python module"],"1":["py","class","Python class"],"2":["py","method","Python method"],"3":["py","property","Python property"],"4":["py","attribute","Python attribute"],"5":["py","function","Python function"]},"objtypes":{"0":"py:module","1":"py:class","2":"py:method","3":"py:property","4":"py:attribute","5":"py:function"},"terms":{"":[0,2,3,4,5,6,8,9,10,12],"0":[3,4,6,9,11,12],"0441172719":11,"1":[0,3,4,6,9,10,11],"10":[0,6,9],"100":9,"127":[3,4],"13":4,"150mb":4,"1965":11,"2":[4,6,8,9,11,12],"200":[6,8,9,11],"201":[6,8,10,11,12],"204":[11,12],"3":[4,5,6,8,9,11],"301":[0,6],"308":2,"3600":9,"4":4,"40":2,"400":[0,8,9,11],"401":9,"404":[6,10,11,12],"41d4":6,"422":[8,9,11],"429":9,"446655440000":6,"500":[2,6,8,9,11],"5000":9,"5042":[3,4,6,11],"550e8400":6,"60":9,"600":[0,9],"8":0,"80":4,"8000":[4,6],"8192":0,"9":[5,8],"978":11,"99":8,"A":[0,4,5,6,9],"And":[5,6],"As":9,"But":[6,8,9],"By":[3,6,8,9,11],"For":[0,3,4,6,8,9,11,12],"If":[0,3,5,6,8,9,10,12],"In":[5,6,9,10,12],"It":[0,3,5,6,8,9],"No":[5,8,9,10,11],"Not":6,"On":9,"One":[5,6,8],"That":[4,5,6,8],"The":[2,3,4,6,8,9,11,12],"There":[8,9],"These":6,"To":[11,12],"Will":0,"With":0,"__main__":[4,5,8,11,12],"__name__":[4,5,8,9,10,11,12],"__tablename__":12,"_route_for":2,"a2wsgi":2,"a716":6,"abc":11,"abc123":[8,9],"abil":2,"abl":0,"abort":10,"about":[4,6,8,10],"abov":5,"abstract":12,"accept":[0,2,6,8,9],"access":[0,4,9,12],"acm":3,"acquir":7,"across":[4,9,12],"activ":7,"actual":[0,6,9],"ad":[1,9],"adapt":9,"add":[0,1,2,6,11,12],"add_event_handl":0,"add_head":9,"add_request_id":0,"add_rout":[0,9],"add_tim":[8,9],"add_vers":8,"addit":0,"address":[0,6,9],"adher":2,"affect":9,"after":[0,5,6,12],"after_request":[0,1,8,9],"ag":9,"against":[0,4,9],"agre":6,"ai":9,"aiosqlit":12,"alemb":12,"alias":2,"alic":9,"all":[0,2,3,4,5,6,7,8,9,10,12],"alloc":8,"allow":9,"allow_credenti":[0,9],"allow_head":[0,9],"allow_method":[0,9],"allow_origin":[0,9],"allow_origin_regex":0,"allowed_host":[0,9],"alongsid":9,"alpin":4,"alreadi":[0,8,9],"also":[0,2,3,6,8,9],"altern":[0,9],"alwai":[4,5,6,9],"an":[0,3,6,9,10,11,12],"angle_bracket":10,"angular":9,"ani":[0,3,4,5,6,8,9,11,12],"annot":[5,6,9],"annual":[6,9],"answer":9,"anyon":5,"anyth":6,"anywher":[4,9],"api":[2,3,4,5,6,9,12],"api_v1":10,"apispec":2,"app":[0,2,3,4,5,8,10,11,12],"appar":0,"apparent_encod":0,"appear":9,"applic":[0,2,3,4,6,8,9,11,12],"approach":[9,10],"appropri":[9,12],"ar":[0,2,3,4,5,6,8,9,10,12],"architectur":9,"aren":6,"arg":[0,10],"argument":[0,2,6,10],"around":[0,5],"arriv":[6,10],"asgi":[0,2,4,5,6,9,10],"ask":[5,9],"assert":8,"asset":[4,5,9],"assign":11,"async":[0,1,2,4,5,6,8,9,10,11,12],"async_sess":12,"async_sessionmak":12,"asynccontextmanag":[9,12],"asynchron":[2,4],"asyncio":12,"asyncpg":12,"attach":9,"attack":[4,9],"attribut":[0,3,12],"auth":[5,9],"auth_check":9,"authent":[6,9],"author":[6,7,9,11,12],"auto":9,"auto_escap":0,"autobuild":7,"autoincr":12,"automat":[0,4,5,6,8,9,10,11,12],"avail":6,"avoid":[8,9],"aw":4,"await":[0,6,8,9,10,11,12],"azur":[3,4],"b":[6,8,12],"back":[0,6,9,12],"background":[2,5],"backlog":5,"bad":[8,9,11],"balanc":4,"bandwidth":9,"bar":9,"base":[0,2,5,12],"base_url":0,"basemodel":[0,8,9,11,12],"basic":6,"batteri":5,"battl":5,"becaus":[0,5,6,10,11],"becom":[0,12],"befor":[5,6,12],"before_request":[0,1,2,8,9,10],"begin":12,"behind":[4,9],"being":0,"best":5,"better":5,"bidirect":9,"big":5,"biggest":10,"bin":7,"binari":[6,9],"bind":[0,4,6],"blob":3,"block":[6,8,9,10],"blueprint":5,"bodi":[0,6,8,9,10,11],"boilerpl":5,"book":[5,12],"book_id":[11,12],"bookin":[11,12],"bookout":12,"books_db":11,"born":5,"both":[5,6,9,10],"bottom":11,"bp":10,"break":8,"bring":5,"broke":[6,8],"broker":6,"browser":[6,7,9,11],"bucket":9,"buffer":6,"bufix":2,"bug":[2,8],"bugfix":2,"build":[2,4,5,6,7,12],"builder":12,"built":[2,4,5,6,8,9],"bump":2,"bypass":4,"byte":[0,5,6],"cach":[6,8,9],"caddi":4,"call":[3,6,8,9,11],"callabl":0,"came":6,"can":[0,3,4,5,6,8,9,10,11,12],"carri":6,"case":[0,5,6],"cat":9,"catalog":11,"catch":9,"categori":0,"cd":7,"ceas":2,"celeri":6,"central":[0,6],"certain":0,"certif":4,"chang":12,"changelog":5,"channel":9,"chardet":0,"chat":9,"check":[0,7,8,9],"check_exist":[0,9,11,12],"choic":[6,9],"choos":9,"chunk":[0,9],"chunk_siz":0,"ci":2,"circuit":[1,5,9],"class":[2,5,6,8,11,12],"clean":[5,9,11],"cleaner":9,"cleanup":9,"cli":2,"click":5,"client":[0,5,6,8,9,11],"clone":7,"close":[8,9,12],"close_database_connection_pool":0,"cloud":[3,5,6],"cmd":4,"code":[2,3,4,5,6,7,8,9,11,12],"collabor":9,"colon":3,"column":12,"com":[3,6,7,9],"come":[6,9,10],"command":[4,5],"commit":12,"common":[3,4,6,9,10,11],"commonli":6,"commun":9,"compact":9,"complement":[1,9],"complet":[9,11],"complex":12,"compos":12,"compress":[5,6],"comput":6,"concept":[2,9,10],"concern":6,"concurr":4,"condit":[8,9],"config":12,"configur":[0,2,4,6,8,9],"conflict":2,"confus":8,"conn":12,"connect":[0,4,8,9,12],"consid":[1,6,12],"consist":[6,9],"consol":[9,12],"const":9,"consum":9,"contact":0,"contain":[0,4,6],"container":4,"content":[0,2,5,6,8,9,11],"content_typ":[0,8,9],"context":[5,8,9,12],"contextlib":[9,12],"continu":6,"contract":8,"control":[0,4,6,9,12],"conveni":[0,12],"convent":[4,11],"convert":[2,6],"convertor":[5,10],"cooki":[0,2,5,6,10],"copi":4,"cor":[0,2,5,8],"core":[2,4],"coroutin":0,"correctli":4,"correspond":12,"cors_param":[0,9],"count":2,"cpu":[4,6],"creat":[0,5,7,8,9,10,12],"create_al":12,"create_async_engin":12,"create_book":[11,12],"create_item":[0,9,10],"create_pet":9,"creation":12,"cross":9,"crud":[5,11],"css":9,"csv":9,"curl":[3,6,11],"curly_brac":10,"custom":[0,5,6,8,11],"cycl":6,"d":[8,11],"dashboard":9,"data":[0,2,6,8,9,10,11,12],"databas":[5,6,8,9,11],"database_url":12,"db":12,"debug":[0,2,9,10],"decim":6,"declar":[2,6],"declarativebas":12,"decod":[2,9],"decor":[0,6,9],"deep":5,"def":[0,5,6,8,9,10,11,12],"default":[0,1,2,3,6,8,9,12],"default_valu":[0,9],"defend":9,"defin":[0,5,6,9],"definit":0,"del":11,"delet":[5,6,9,12],"delete_book":[11,12],"deliber":6,"demo":3,"denpend":2,"depend":[2,4,8],"deploi":[4,5],"deploy":5,"depth":9,"describ":9,"descript":[0,9],"design":[6,9,11],"detail":[4,9,11],"detect":[0,5,9],"dev":2,"develop":[3,4,9,12],"devic":9,"dict":[0,5,6,9,11,12],"dictionari":0,"differ":[3,5,8,9,12],"digit":6,"direct":[2,9],"directli":[3,5,6,8,11,12],"directori":[0,6,9],"disabl":[8,12],"disk":[0,6,9],"dispatch":[2,9],"dispos":12,"distribut":[4,9],"django":[5,9],"do":[4,6,9],"doc":[7,8,9,11],"docker":5,"dockerfil":4,"docs_rout":[0,9,11],"docstr":9,"document":[0,2,4,5,7,11],"doe":12,"doesn":[0,9,11,12],"domain":9,"don":[6,8,9,10,12],"done":4,"dot":3,"doubl":11,"down":[9,12],"download":9,"dramat":2,"driver":12,"drop":2,"dump":2,"dune":11,"duplex":9,"duplic":9,"dure":[3,4,8,12],"duti":11,"dynam":6,"e":0,"e29b":6,"each":[0,4,8,9,12],"easi":[3,6],"echo":12,"ecosystem":[5,6],"edit":7,"editor":9,"effect":[8,11],"effici":4,"either":0,"element":[0,9],"els":[6,9,10,12],"email":6,"emb":9,"empti":11,"enabl":[2,9,11],"enable_async":6,"enable_hst":[0,9],"encod":0,"end":[6,11],"endpoint":[0,2,5,8,9,10,11],"enforc":9,"engin":[6,12],"enough":4,"ensur":[9,11,12],"enter":8,"entir":[0,9,11],"entri":11,"env":4,"environ":[0,3,4,6],"eol":2,"equival":10,"error":[0,5,12],"errorhandl":10,"escap":0,"essenti":9,"etc":[6,8,9],"even":[3,4,9],"event":[0,2,5,6,10],"event_typ":0,"eventsourc":9,"ever":5,"everi":[0,4,5,6,8,9,11,12],"everyth":[0,4,9,10,11,12],"everywher":3,"evolv":12,"exactli":[8,9],"exampl":[0,3,6,9],"exc":[0,8,9,11],"exceed":9,"except":[0,2,5,8,9],"exception_cl":0,"exception_handl":[0,8,9,10,11],"execut":12,"exist":[0,2,5,10],"exit":[8,9],"expect":6,"expir":9,"expire_on_commit":12,"explain":9,"explan":0,"explicit":[6,9,10],"explicitli":[9,10],"explor":[1,9],"export":9,"expos":4,"expose_head":0,"express":[5,6],"ext":[2,9,12],"extens":[2,6],"extern":6,"extra":[2,4,9],"extract":0,"extrem":6,"f":[0,5,6,8,9,11],"factori":12,"fail":[8,9,12],"failur":8,"falcon":[5,9],"fall":0,"fals":[0,8,9,11,12],"familiar":[5,10],"fast":[4,5,6,8],"fastapi":5,"faster":9,"featur":[0,5,6],"feed":9,"feel":5,"fetch":3,"few":10,"fido":9,"field":[0,8,9,11],"figur":6,"file":[0,2,4,5,6,11,12],"filenam":[0,8],"filepath":6,"filesystem":[2,3],"fill":6,"filter":[5,6],"find":[3,9,10],"fine":[4,9,12],"fire":8,"first":[0,9,11,12],"fit":5,"fix":7,"fixtur":5,"flag":[4,9,12],"flask":[5,9],"flask_app":[9,10],"float":[0,6,8],"fly":4,"follow":6,"font":9,"forg":9,"form":[0,6,10],"format":[0,2,6,7,9],"formerli":9,"forward":[4,9],"found":[2,6,11,12],"foundat":9,"fragment":3,"framework":[5,9],"franca":6,"frank":11,"fresh":8,"from":[0,2,4,5,6,8,9,11,12],"from_attribut":12,"front":4,"frontend":[5,9],"fsspec":3,"full":[0,2,3,6,9],"full_url":[0,6,9],"fulli":6,"fun":5,"func":0,"function":[0,6,9,10],"futur":5,"g":0,"game":9,"gatewai":4,"gener":[0,5,8,9,11],"get":[0,6,9,12],"get_book":[11,12],"get_us":[0,9,10],"git":7,"github":[3,7],"give":[0,8,9,12],"given":[0,8],"global":[10,11],"go":[6,10],"goe":[9,10],"good":[4,5,9],"googl":[3,4],"grace":4,"grade":6,"gradual":[5,9],"grain":12,"graphen":[0,2,5,9],"graphiql":[2,5,9],"graphql":[0,2,5],"great":[3,5,9],"greet":[5,9],"greet_world":5,"greetingresourc":9,"group":[0,5],"grow":9,"guard":5,"guid":[6,10,12],"guido":6,"gzip":[5,6],"h":11,"h1":6,"ha":[6,8,10,11],"half":6,"halv":9,"hand":0,"handl":[4,5,6],"handle_value_error":[0,9,11],"handler":[0,5,8,9,11],"happen":[5,6],"hard":8,"have":[0,2,3,6,8,10,11],"hdf":3,"head":3,"header":[0,4,5,6,9,10],"heavi":6,"hello":[0,3,5,8,9,10],"hello_html":6,"hello_json":6,"hello_to":6,"hello_world":6,"helloworld":3,"help":[0,12],"helper":5,"herbert":11,"here":[4,6,9,10],"high":[4,9],"hold":[0,5,6],"home":5,"honor":[4,6],"hood":9,"hook":[0,1,5,6],"host":[0,2,4,5,6],"hostnam":9,"hour":9,"how":[5,6,9,10,11,12],"hst":5,"html":[0,2,5,6,9,10],"http":[0,2,3,4,5,6,7,8,9,11],"httponli":9,"httpsredirectmiddlewar":4,"httpx":[2,8],"i":[0,2,3,4,5,6,8,9,10,11,12],"id":[0,5,6,10,11,12],"idea":10,"idempot":11,"ident":10,"identifi":9,"imag":[4,6,9],"immedi":[5,6,9],"immut":2,"implement":8,"import":[0,2,3,5,6,8,9,10,11,12],"improv":2,"includ":[3,4,5,6,7,8,9,11],"incom":[0,6,11],"incredibli":9,"independ":4,"index":[0,9],"individu":9,"industri":9,"info":[0,2,9],"inform":[0,11],"infrastructur":[4,5],"inherit":9,"initi":[0,8],"inject":9,"input":[8,9,11],"insensit":[0,5,6],"instal":[0,3,4,7,9],"instanc":[0,4,5,6,8],"instant":6,"instead":[6,8,9,11,12],"int":[0,6,9,10,11,12],"integ":[0,6,11,12],"integr":[11,12],"intens":6,"intent":5,"intention":9,"interact":[2,9,11],"interfac":[4,5,6,10],"intern":[8,9],"invalid":[8,9],"involv":0,"io":4,"iot":9,"ip":[6,9],"is_100":0,"is_200":0,"is_300":0,"is_400":0,"is_500":0,"is_class_bas":2,"is_json":[0,6],"is_secur":6,"isbn":[11,12],"isn":[6,9,10],"issu":2,"item":[0,8,9,10,12],"itemin":0,"itemout":0,"its":[0,2,4,11,12],"j":9,"javascript":[3,9],"jinja2":[0,6,10],"jpeg":9,"jpg":9,"json":[0,3,5,6,9,11],"jsonifi":10,"just":[4,8,9,12],"keep":[2,6,8,9,12],"kei":[0,8,9,10,12],"kennethreitz":[3,7],"keyword":[0,6,10],"know":6,"known":0,"kwarg":0,"languag":9,"larg":9,"larger":8,"later":[6,8],"launch":[4,5],"lazili":0,"lead":8,"learn":9,"legaci":10,"less":9,"let":[3,4,6,9,11,12],"level":4,"librari":[8,9],"licens":0,"lifespan":[0,2,5,11],"lift":6,"lightn":4,"lightweight":6,"like":[4,6,8,9,11],"limit":[1,4,5,12],"line":[5,6],"lingua":6,"list":[0,5,6,8,9,12],"list_book":[11,12],"list_item":9,"list_pet":9,"list_us":[0,9,10],"list_users_v2":9,"live":9,"ll":[5,6,9,10,11,12],"load":[0,2,3,4,6,9],"local":[3,5,10],"localhost":[6,11,12],"locat":[0,6,10],"log":[4,9],"log_level":2,"log_respons":9,"logic":[5,6,9],"login":9,"long":6,"look":[3,5,6],"loop":[6,10],"lose":12,"lower":0,"lowercas":6,"machin":9,"made":5,"magic":10,"mai":4,"main":3,"make":[4,6,8,9,10],"malici":9,"manag":[5,8,9,12],"mani":[4,6,9],"manual":0,"map":[2,6,9,10,12],"mapper":12,"mark":[2,9],"marshmallow":[0,2,9],"match":[0,6,9,11],"matter":9,"max_ag":[0,9],"mean":[4,6,10],"mechan":9,"media":[0,2,5,6,8,9,10,11,12],"memori":[0,5,6,9],"messag":[0,6,9],"messagepack":5,"metadata":[6,12],"method":[0,5,6,8,10,11,12],"microservic":9,"middelwar":0,"middlewar":[0,1,2,6,9],"might":6,"migrat":[2,5,9,12],"mime":0,"mimetyp":[6,9],"min":9,"minim":4,"minimum":2,"minor":2,"miss":[8,9],"mix":9,"ml":9,"mode":[0,7],"model":[0,5,8,9],"model_dump":12,"model_valid":12,"modern":[4,9,10,12],"modifi":[9,11,12],"modul":[0,2,5,6,9],"more":[0,3,4,6,9,10,11],"most":[0,3,4,6,8,9,12],"mount":[0,2,5,10],"move":[2,6,9,10],"msgpack":9,"much":[6,9],"multipart":[2,6],"multipl":[2,4,9,11],"multiplay":9,"must":[0,6,9,11],"mutabl":5,"mutat":[0,6,10],"my_templ":6,"myapi":4,"myapp":3,"mydb":12,"mysql":12,"n":6,"name":[0,5,6,8,9,10],"namespac":2,"nativ":10,"natur":[8,12],"nearli":10,"need":[4,5,6,8,9,10,12],"negoti":[0,5,6,8,9],"nervou":6,"network":8,"never":[9,11],"new":[0,6,8,9,10,11],"new_endpoint":10,"next":5,"next_id":11,"nginx":4,"non":6,"none":[0,2,11,12],"normal":9,"notabl":2,"notasecret":0,"note":[6,9,10,11],"notic":6,"notif":9,"now":[2,6,9,12],"npm":3,"nullabl":12,"number":6,"o":[0,6,10],"object":[0,2,6,9,10,12],"objecttyp":[0,9],"obviou":8,"off":6,"offload":4,"offset":12,"often":[3,6,9],"ok":[6,8,11],"old":10,"on_delet":9,"on_ev":[0,8,9],"on_get":[5,9],"on_post":[5,9],"on_put":9,"on_request":[5,9],"on_startup":8,"onc":[9,10,11],"one":[0,5,6,9,10,12],"ones":[5,6,9],"onli":[6,9,10,11],"onmessag":9,"open":[2,6,7,12],"open_database_connection_pool":0,"openapi":[0,2,5,11],"openapi_rout":0,"openapi_them":0,"oper":[6,9,10,11],"opt":9,"option":[0,2,4,5,6],"order_bi":12,"organ":[8,9,10],"origin":9,"orm":12,"other":[0,2,5,6,12],"otherwis":[0,9],"our":11,"out":[5,6],"outgo":6,"output":11,"over":[0,5,6,9,10,12],"overal":2,"overhead":8,"overrid":[0,9],"overwhelm":9,"own":[4,9,12],"p":4,"pace":9,"packag":[2,3,4],"page":[0,2,6,9],"pagin":6,"painless":8,"param":[0,2,5,6,10],"paramet":[0,5,8,9,11],"parameter":0,"pars":[0,2,6,8,9],"part":[5,6,9],"pass":[0,6,8,10,12],"passion":5,"patch":[6,9],"path":[0,2,3,5,6,8,9],"path_matches_rout":0,"path_param":[0,6],"pattern":[4,5,6,9,10,11,12],"pdf":[6,8,9],"per":[4,8,9],"perfect":9,"period":9,"perman":6,"permit":9,"persist":9,"person":5,"pet":[0,9],"petin":9,"petout":9,"petschema":[0,9],"photo":9,"piec":9,"pin":2,"pip":[3,4,5,7,12],"place":9,"placehold":6,"plain":[6,9],"platform":[2,5,6],"pleasant":5,"plu":12,"plugin":2,"point":[3,4,11],"polici":9,"pool":[5,6,9,10,12],"popular":[6,9,12],"port":[0,4,6,8],"portion":0,"possibl":6,"post":[0,6,8,9,10,11,12],"postgresql":5,"potenti":2,"power":[5,8,9,12],"practic":9,"prefer":9,"prefix":[0,9],"present":6,"prevent":9,"price":[0,8],"primari":0,"primary_kei":12,"print":[9,12],"privat":9,"process":[4,5,6,8,9],"process_data":6,"produc":6,"product":[3,4,5,6,8,9,12],"profil":9,"programmat":9,"progress":9,"project":[2,3,7],"propag":8,"proper":[6,12],"properli":[8,12],"properti":[0,6,8],"protect":4,"proto":4,"protocol":[3,6,8,9],"prototyp":[2,3,5],"provid":0,"proxi":5,"public":[0,9],"push":[4,5,9],"put":[6,9,11,12],"py":[2,3,4,8,11,12],"pydant":[0,8,9,11,12],"pyproject":2,"pytest":[5,7,8],"python":[0,2,3,4,5,6,9,11,12],"pythonpath":3,"q":[6,10],"queri":[0,5,6,9,12],"queue":6,"quick":[0,3,5],"r":[6,8],"race":8,"railwai":4,"rais":[2,8,9],"raise_server_except":8,"random":0,"rang":[0,9],"rapidoc":[0,9],"rare":6,"rate":[1,4,5],"ratelimit":9,"rather":8,"raw":[3,5,6,9,12],"re":[0,4,6,8,9,10,11],"react":[2,9],"read":[0,2,5,9,10,11,12],"readabl":9,"readi":[4,5,6],"real":[9,11,12],"realli":[8,9],"receiv":[0,5,6,8,9],"receive_byt":9,"receive_incom":6,"receive_json":9,"receive_text":[8,9],"recommend":9,"reconnect":9,"redirect":[0,2,6,10],"redoc":[0,9],"reduc":2,"ref":3,"refactor":[2,8],"refer":[5,8],"refresh":12,"refus":9,"regist":[0,8,9],"register_blueprint":10,"reject":[8,9],"relat":[9,12],"releas":7,"reliabl":8,"remain":9,"remov":[9,10,11],"renam":8,"render":[0,1,4,5,9],"render_async":6,"render_templ":10,"replac":[2,6,9,11],"report":[6,8,9],"repres":0,"represent":0,"req":[0,5,6,8,9,10,11,12],"request":[2,3,4,5,10,11,12],"request_id":[0,9],"request_model":[0,8,9,11,12],"requir":[0,2,8,9],"research":5,"resolv":[2,9],"resolve_hello":[0,9],"resourc":[6,9,11],"resp":[0,2,5,6,8,9,10,11,12],"respect":3,"respond":[0,2,3,4,6,7,8,9,10,11,12],"respons":[5,8,9,10,11,12],"response_model":[0,9,11,12],"rest":[4,5,9],"restrict":9,"result":[9,12],"resum":2,"resume_incomplet":2,"retri":[0,9],"retriev":[9,11],"return":[0,2,5,6,8,9,10,11,12],"revers":5,"rfc3986":2,"right":[5,6,9,10],"roll":12,"rout":[0,2,5,8,11,12],"router":2,"ruff":7,"run":[0,2,3,5,7,8,9,10],"run_sync":12,"runner":4,"s3":3,"safe":[2,11],"sai":6,"said":4,"same":[3,4,5,6,9,10,11,12],"sandbox":5,"scalar":12,"scale":5,"schema":[0,2,5,9,11,12],"scope":[0,9],"scratch":[5,11],"search":[0,2,6,9],"second":0,"secret":9,"secret_kei":[0,9],"section":9,"secur":9,"see":[0,4,6,8,9,11,12],"select":[0,2,12],"self":[0,9],"semant":2,"send":[0,2,5,8,9,11],"send_byt":9,"send_json":9,"send_text":[8,9],"sent":[0,5,6],"separ":[6,8,11],"sequenti":2,"serial":[6,9],"serializ":6,"serv":[0,2,3,4,5,6,8,11],"server":[0,2,3,4,5,8,11,12],"servestat":2,"servic":[0,3,5,8,9,11],"session":[0,2,5,6,8,10,12],"session_id":9,"set":[0,2,4,5,6,7,8,9,12],"set_cooki":[2,9],"set_text":0,"setattr":12,"setup":[2,5,8],"sever":9,"sftp":3,"share":[0,3,6,8,9,12],"short":[1,5,9],"should":[11,12],"shouldn":0,"show":[2,9,10,12],"shut":[9,12],"shutdown":[0,4,5,8,9],"shutdwown":2,"sibl":5,"side":[6,9],"sign":[5,6,9],"signatur":[6,9,10],"simpl":[3,8,9,11],"simplecooki":0,"simpler":[6,9],"simplest":6,"simplic":[5,12],"simul":6,"sinc":[6,8],"singl":[2,3,5,6,9,10,12],"size":[0,12],"skip":9,"slash":6,"sleep":[6,8],"slim":4,"slow":6,"slowlori":4,"slug":6,"small":[4,5,8,9],"smaller":4,"so":[8,9,10,11,12],"solv":9,"some":[4,9],"someon":[6,9],"someth":[5,6,8,9],"sometim":[6,9],"somewher":6,"sourc":[0,7,9],"spawn":4,"spec":[6,9],"special":[5,9],"specif":[0,8,9,11],"specifi":3,"sphinx":7,"spin":6,"sprawl":5,"sql":12,"sqlalchemi":[5,11],"sqlite":12,"sse":[0,5],"ssl":4,"stabil":2,"stai":[10,12],"standard":[3,4,9,11],"starlett":[0,2,5,8],"start":[0,3,4,5,9,11,12],"startup":[0,2,5,8,9],"state":[0,2,8,9],"statement":5,"static":[0,2,4,5,6],"static_dir":[0,9],"static_rout":[0,2,9],"statu":[2,5,6,8,9,11],"status_cod":[0,5,6,8,9,10,11,12],"stdlib":2,"still":[9,10],"stop":9,"storag":[3,5],"store":[0,9,11],"str":[0,6,8,9,11,12],"straightforward":9,"stranger":[0,9],"stream":[0,2,9],"stream_fil":[0,9],"strict":9,"string":[0,5,6,9,12],"strip":9,"structur":9,"style":9,"stylesheet":9,"subcommand":3,"subrout":[5,9,10],"subsequ":9,"subtl":2,"success":[6,11],"successfulli":11,"successor":4,"suit":8,"suppli":2,"support":[0,1,2,3,4,5,6,10,12],"swagger":[5,9,11],"swagger_ui":[0,9],"switch":[2,12],"sync":[2,5,6,10],"synchron":[0,10],"syntax":[5,6,10],"system":[3,6,9],"t":[0,4,6,8,9,10,11,12],"tabl":12,"take":[5,6],"tamper":9,"target":2,"task":[2,5],"teach":5,"tear":9,"tell":[6,9,11,12],"templat":[0,1,2,5],"template_str":[0,6],"templates_dir":0,"termin":[3,4],"terms_of_servic":0,"test":[0,2,3,5,7,11],"test_500":[2,8],"test_api":8,"test_create_item":8,"test_custom_error":8,"test_head":8,"test_hello":8,"test_hook":8,"test_json":8,"test_upload":8,"test_valid":8,"test_websocket":8,"test_with_lifespan":8,"testclient":[0,2,8],"text":[0,5,6,8,9,10],"than":[8,9,10,11],"thei":[6,9,10,11],"them":[5,6,8,9,10,11],"theme":[0,9],"themselv":9,"thi":[0,2,3,4,5,6,8,9,10,11,12],"thing":[5,6,8],"think":6,"though":4,"thousand":4,"thread":[5,6,10],"threadpoolexecutor":2,"three":[6,9],"through":[6,9,11],"throughput":9,"time":[0,5,6,8,9,10,11,12],"time_start":0,"timeout":4,"tip":5,"titl":[0,6,9,11,12],"tl":4,"togeth":[5,9],"token":[6,9],"toml":2,"too":[3,4,8,9],"tool":7,"toolbelt":2,"toolkit":12,"top":0,"total":9,"tour":[0,5],"trace":9,"traceback":[2,9],"track":12,"tradit":9,"traffic":4,"transact":12,"translat":10,"transport":9,"treat":[0,9],"trick":9,"trigger":8,"true":[0,6,8,9,10,12],"trust":5,"trustedhostmiddlewar":4,"try":5,"tupl":[0,6,8],"tutori":11,"two":[6,9],"type":[0,2,5,9,10,11],"typic":[6,9],"typo":[2,9],"ui":[2,5,9,11],"unauthor":9,"under":[6,9,10],"understand":[5,6],"unicod":0,"uniqu":9,"unit":12,"unknown":0,"unless":9,"unlik":9,"unmaintain":2,"unmatch":9,"unpin":2,"unrecogn":9,"until":6,"up":[0,2,6,7,9],"updat":[2,5,6,9,12],"update_book":[11,12],"upgrad":[2,7,9],"upload":[2,5,6],"url":[0,2,5,6,8,9,10,12],"url_for":[0,8],"url_prefix":10,"urllib":2,"us":[0,2,3,4,5,6,9,10,11],"usag":[0,2],"user":[0,6,9,10,12],"user_id":[6,9,10],"usernam":9,"usual":8,"utf":0,"uuid":[0,6,9],"uuid4":0,"uv":[3,5,7,12],"uvicorn":[0,2,5,6],"uvloop":4,"v1":[0,9],"v2":9,"valid":[5,6,9,11,12],"valu":[0,5,6,8,9,10,11,12],"valueerror":[0,8,9,10,11],"variabl":[0,4,6],"ve":[5,8,10],"venv":7,"verb":9,"veri":[0,6,12],"verifi":8,"version":[0,2,8,9,11],"via":[2,9,10],"view":[0,2,5,6,8,10],"virtual":[3,4],"virtualenv":7,"visit":[9,11],"vue":9,"w":[8,9],"wa":[0,2,6,11],"wai":[3,4,5,6,9,10,12],"wait":10,"walk":[6,9,11],"want":[0,3,4,5,6,8,9,11,12],"watch":7,"we":[11,12],"web":[0,4,5,9,12],"websit":9,"websocket":[0,1,2,4,5],"websocket_connect":8,"welcom":5,"well":5,"went":5,"what":[0,6,8,9],"whatev":6,"when":[2,4,6,8,9,10,11,12],"where":[4,6,9,12],"whether":[0,6],"which":[0,2,6,8,9,10,12],"whichev":5,"while":[6,9,10],"whitenois":2,"who":[5,6],"widget":8,"wildcard":9,"window":2,"wire":6,"within":[2,12],"without":[0,4,6,8,9,12],"won":[6,8,9,12],"work":[3,4,5,6,9,11,12],"workdir":4,"worker":4,"world":[0,3,5,8,9,10],"worri":8,"would":8,"wrap":[6,8,9],"write":[5,6,9,10],"wrong":9,"wsgi":[0,2,4,5,9,10],"x":[0,4,6,8,9,10,11],"x89png":6,"xml":0,"xss":9,"yaml":[0,2,5,6,8,9],"year":[11,12],"yield":[0,9,12],"yml":[0,9],"you":[0,3,4,6,8,9,10,11,12],"your":[0,3,4,5,6,8,9,10],"yourself":6,"zero":4},"titles":["API Reference","Backlog","Changelog","Command Line Interface","Deployment","Responder","Quick Start","Development Sandbox","Testing","Feature Tour","Migrating from Flask","Building a REST API","Using SQLAlchemy"],"titleterms":{"":11,"0":2,"01":2,"02":2,"03":2,"04":2,"08":2,"09":2,"1":2,"10":2,"11":2,"12":2,"13":2,"15":2,"16":2,"17":2,"18":2,"19":2,"2":2,"20":2,"2018":2,"2019":2,"2026":2,"22":2,"23":2,"24":2,"25":2,"26":2,"27":2,"28":2,"29":2,"3":2,"4":2,"5":2,"6":2,"7":2,"8":2,"9":2,"In":11,"It":[11,12],"The":[0,5,10],"ad":2,"after":[8,9],"all":11,"api":[0,8,10,11],"app":9,"asset":3,"background":6,"backlog":1,"base":9,"befor":[8,9],"big":10,"blueprint":10,"book":11,"build":[3,11],"chang":2,"changelog":2,"class":[0,9],"cloud":4,"code":0,"command":3,"convertor":6,"cooki":[8,9],"cor":9,"creat":[6,11],"crud":12,"custom":[3,9],"databas":12,"defin":[11,12],"delet":11,"deploy":4,"deprec":2,"develop":7,"differ":10,"directli":4,"docker":4,"document":9,"endpoint":12,"error":[8,9,11],"event":[8,9],"featur":9,"file":[3,8,9],"filter":9,"fix":2,"fixtur":8,"flask":10,"from":[3,10],"frontend":3,"futur":1,"get":[5,8,11],"gradual":10,"graphql":9,"group":[9,10],"guid":5,"handl":[8,9,11],"header":8,"hello":6,"helper":0,"hook":[8,9],"host":9,"hst":9,"id":9,"idea":[1,5],"instal":[5,12],"instanc":3,"interfac":3,"json":[8,10],"launch":3,"lifespan":[8,9,12],"limit":9,"line":3,"list":11,"local":4,"memori":11,"messagepack":9,"method":9,"migrat":10,"model":[11,12],"modul":3,"mount":9,"name":3,"next":11,"openapi":9,"oper":7,"other":9,"out":11,"paramet":[6,10],"platform":4,"postgresql":12,"project":[5,11],"proxi":4,"quick":[6,10],"rate":9,"read":6,"refer":[0,10],"remov":2,"render":6,"request":[0,6,8,9],"respond":5,"respons":[0,6],"rest":11,"revers":4,"rout":[6,9,10],"run":[4,6,11,12],"sandbox":7,"send":6,"sent":9,"serv":9,"server":[6,9],"servic":6,"session":9,"setup":[7,11,12],"shutdown":12,"singl":11,"sqlalchemi":12,"sse":9,"start":[6,8],"startup":12,"static":9,"statu":0,"storag":11,"support":9,"task":6,"templat":[6,10],"test":8,"tip":[8,12],"tour":9,"trust":9,"try":11,"tutori":5,"type":6,"unreleas":2,"updat":11,"upload":8,"url":3,"us":[8,12],"user":5,"uvicorn":4,"v0":2,"v1":2,"v2":2,"v3":2,"valid":8,"view":9,"web":6,"websocket":[8,9],"what":[5,11],"world":6,"you":5,"your":[11,12]}}) \ No newline at end of file +Search.setIndex({"alltitles":{"API Key Authentication":[[11,"api-key-authentication"]],"API Reference":[[0,null]],"Added":[[2,"added"],[2,"id1"],[2,"id4"],[2,"id10"],[2,"id11"],[2,"id14"],[2,"id17"],[2,"id22"],[2,"id29"],[2,"id35"],[2,"id36"],[2,"id37"],[2,"id38"],[2,"id39"],[2,"id42"],[2,"id43"],[2,"id45"],[2,"id48"],[2,"id51"],[2,"id52"],[2,"id53"],[2,"id57"]],"Adding Third-Party Middleware":[[13,"adding-third-party-middleware"]],"After-Request Hooks":[[10,"after-request-hooks"]],"Allowed Hosts":[[5,"allowed-hosts"]],"Authentication":[[11,null]],"Background Queue":[[0,"background-queue"]],"Background Tasks":[[7,"background-tasks"]],"Backlog":[[1,null]],"Bearer Token Authentication":[[11,"bearer-token-authentication"]],"Before-Request Hooks":[[10,"before-request-hooks"]],"Before-Request Hooks for WebSockets":[[16,"before-request-hooks-for-websockets"]],"Blueprints \u2192 Route Groups":[[12,"blueprints-route-groups"]],"Building Frontend Assets":[[3,"building-frontend-assets"]],"Building a REST API":[[14,null]],"Built-in Middleware":[[13,"built-in-middleware"]],"CORS":[[10,"cors"]],"CRUD Endpoints":[[15,"crud-endpoints"]],"Changed":[[2,"changed"],[2,"id2"],[2,"id9"],[2,"id12"],[2,"id15"],[2,"id18"],[2,"id21"],[2,"id26"],[2,"id27"],[2,"id28"],[2,"id30"],[2,"id31"],[2,"id33"],[2,"id34"],[2,"id40"],[2,"id44"],[2,"id49"],[2,"id50"],[2,"id56"]],"Changelog":[[2,null]],"Chat Room":[[16,"chat-room"]],"Class-Based Views":[[10,"class-based-views"]],"Cloud Platforms":[[4,"cloud-platforms"]],"Command Line Interface":[[3,null]],"Configuration":[[5,null]],"Configuration Class Pattern":[[5,"configuration-class-pattern"]],"Cookie-Based Sessions":[[10,"cookie-based-sessions"]],"Cookies":[[10,"cookies"]],"Create a Book":[[14,"create-a-book"]],"Create a Web Service":[[7,"create-a-web-service"]],"Custom Error Handling":[[10,"custom-error-handling"]],"Custom Exception for Auth Errors":[[11,"custom-exception-for-auth-errors"]],"Custom Instance Names":[[3,"custom-instance-names"]],"Data Formats":[[16,"data-formats"]],"Database Setup":[[15,"database-setup"]],"Debug Mode":[[5,"debug-mode"]],"Define Your Models":[[14,"define-your-models"],[15,"define-your-models"]],"Delete a Book":[[14,"delete-a-book"]],"Deployment":[[4,null]],"Deprecated":[[2,"deprecated"]],"Development Sandbox":[[8,null]],"Docker":[[4,"docker"]],"Echo Server":[[16,"echo-server"]],"Environment Variables":[[5,"environment-variables"]],"Error Handling":[[14,"error-handling"]],"Feature Tour":[[10,null]],"Fixed":[[2,"fixed"],[2,"id3"],[2,"id5"],[2,"id6"],[2,"id7"],[2,"id8"],[2,"id13"],[2,"id16"],[2,"id19"],[2,"id20"],[2,"id23"],[2,"id24"],[2,"id25"],[2,"id32"],[2,"id41"],[2,"id46"],[2,"id47"],[2,"id54"],[2,"id55"]],"Future Ideas":[[1,"future-ideas"]],"Get a Single Book":[[14,"get-a-single-book"]],"Getting Started":[[9,"getting-started"]],"Gradual Migration":[[12,"gradual-migration"]],"GraphQL":[[10,"graphql"]],"HSTS":[[10,"hsts"]],"HTML Client":[[16,"html-client"]],"Hello World":[[7,"hello-world"]],"Hooks vs. Middleware":[[13,"hooks-vs-middleware"]],"How WebSockets Work":[[16,"how-websockets-work"]],"In-Memory Storage":[[14,"in-memory-storage"]],"Installation":[[6,"installation"],[15,"installation"]],"JSON APIs":[[12,"json-apis"]],"Launching from a File":[[3,"launching-from-a-file"]],"Launching from a Module":[[3,"launching-from-a-module"]],"Launching from a URL":[[3,"launching-from-a-url"]],"Lifespan Events":[[10,"lifespan-events"]],"Lifespan for Startup and Shutdown":[[15,"lifespan-for-startup-and-shutdown"]],"List All Books":[[14,"list-all-books"]],"MessagePack":[[10,"messagepack"]],"Method Filtering":[[10,"method-filtering"]],"Middleware Order":[[13,"middleware-order"]],"Migrating from Flask":[[12,null]],"Mounting Other Apps":[[10,"mounting-other-apps"]],"OpenAPI Documentation":[[10,"openapi-documentation"]],"Operations":[[8,"operations"]],"Project":[[6,null]],"Project Setup":[[14,"project-setup"]],"Putting It All Together":[[5,"putting-it-all-together"],[7,"putting-it-all-together"]],"Query Dict":[[0,"query-dict"]],"Quick Reference":[[12,"quick-reference"]],"Quick Start":[[7,null]],"Rate Limiter":[[0,"rate-limiter"]],"Rate Limiting":[[10,"rate-limiting"]],"Reading Requests":[[7,"reading-requests"]],"Removed":[[2,"removed"]],"Rendering Templates":[[7,"rendering-templates"]],"Request":[[0,"request"]],"Request ID":[[10,"request-id"]],"Responder":[[6,null]],"Response":[[0,"response"]],"Reverse Proxy":[[4,"reverse-proxy"]],"Route Groups":[[0,"route-groups"],[10,"route-groups"]],"Route Parameters":[[7,"route-parameters"],[12,"route-parameters"]],"Run It":[[14,"run-it"],[15,"run-it"]],"Run the Server":[[7,"run-the-server"]],"Running Locally":[[4,"running-locally"]],"Secret Key":[[5,"secret-key"]],"Sending Responses":[[7,"sending-responses"]],"Server-Sent Events (SSE)":[[10,"server-sent-events-sse"]],"Serving Files":[[10,"serving-files"]],"Setup":[[8,"setup"]],"Skipping Auth for Public Routes":[[11,"skipping-auth-for-public-routes"]],"Static Files":[[10,"static-files"]],"Status Code Helpers":[[0,"status-code-helpers"]],"Templates":[[12,"templates"]],"Testing":[[9,null]],"Testing Before and After Hooks":[[9,"testing-before-and-after-hooks"]],"Testing Error Handling":[[9,"testing-error-handling"]],"Testing File Uploads":[[9,"testing-file-uploads"]],"Testing Headers and Cookies":[[9,"testing-headers-and-cookies"]],"Testing JSON APIs":[[9,"testing-json-apis"]],"Testing Lifespan Events":[[9,"testing-lifespan-events"]],"Testing Request Validation":[[9,"testing-request-validation"]],"Testing WebSockets":[[9,"testing-websockets"],[16,"testing-websockets"]],"The API Class":[[0,"the-api-class"]],"The Big Differences":[[12,"the-big-differences"]],"The Idea":[[6,"the-idea"]],"Tips":[[9,"tips"],[15,"tips"]],"Trusted Hosts":[[10,"trusted-hosts"]],"Try It Out":[[14,"try-it-out"]],"Tutorials":[[6,null]],"Type Convertors":[[7,"type-convertors"]],"Unreleased":[[2,"unreleased"]],"Update a Book":[[14,"update-a-book"]],"User Guide":[[6,null]],"Using .env Files":[[5,"using-env-files"]],"Using Fixtures":[[9,"using-fixtures"]],"Using PostgreSQL":[[15,"using-postgresql"]],"Using SQLAlchemy":[[15,null]],"Using Sessions for Web Apps":[[11,"using-sessions-for-web-apps"]],"Using Starlette Middleware":[[13,"using-starlette-middleware"]],"Uvicorn Directly":[[4,"uvicorn-directly"]],"WebSocket Support":[[10,"websocket-support"]],"WebSocket Tutorial":[[16,null]],"What You Get":[[6,"what-you-get"]],"What\u2019s Next":[[14,"what-s-next"]],"When to Use What":[[13,"when-to-use-what"]],"Writing Middleware":[[13,null]],"[v3.2.0] - 2026-03-22":[[2,"v3-2-0-2026-03-22"]],"v0.0.1 - 2018-10-12":[[2,"v0-0-1-2018-10-12"]],"v0.0.10 - 2018-10-17":[[2,"v0-0-10-2018-10-17"]],"v0.0.2 - 2018-10-13":[[2,"v0-0-2-2018-10-13"]],"v0.0.3 - 2018-10-13":[[2,"v0-0-3-2018-10-13"]],"v0.0.4 - 2018-10-15":[[2,"v0-0-4-2018-10-15"]],"v0.0.5 - 2018-10-15":[[2,"v0-0-5-2018-10-15"]],"v0.0.6 - 2018-10-16":[[2,"v0-0-6-2018-10-16"]],"v0.0.7 - 2018-10-16":[[2,"v0-0-7-2018-10-16"]],"v0.0.8 - 2018-10-17":[[2,"v0-0-8-2018-10-17"]],"v0.0.9 - 2018-10-17":[[2,"v0-0-9-2018-10-17"]],"v0.1.0 - 2018-10-17":[[2,"v0-1-0-2018-10-17"]],"v0.1.1 - 2018-10-17":[[2,"v0-1-1-2018-10-17"]],"v0.1.2 - 2018-10-18":[[2,"v0-1-2-2018-10-18"]],"v0.1.3 - 2018-10-18":[[2,"v0-1-3-2018-10-18"]],"v0.1.4 - 2018-10-19":[[2,"v0-1-4-2018-10-19"]],"v0.1.5 - 2018-10-20":[[2,"v0-1-5-2018-10-20"]],"v0.1.6 - 2018-10-20":[[2,"v0-1-6-2018-10-20"]],"v0.2.0 - 2018-10-22":[[2,"v0-2-0-2018-10-22"]],"v0.2.1 - 2018-10-23":[[2,"v0-2-1-2018-10-23"]],"v0.2.2 - 2018-10-23":[[2,"v0-2-2-2018-10-23"]],"v0.2.3 - 2018-10-24":[[2,"v0-2-3-2018-10-24"]],"v0.3.0 - 2018-10-24":[[2,"v0-3-0-2018-10-24"]],"v0.3.1 - 2018-10-24":[[2,"v0-3-1-2018-10-24"]],"v0.3.2 - 2018-10-25":[[2,"v0-3-2-2018-10-25"]],"v0.3.3 - 2018-10-25":[[2,"v0-3-3-2018-10-25"]],"v1.0.0 - 2018-10-26":[[2,"v1-0-0-2018-10-26"]],"v1.0.1 - 2018-10-26":[[2,"v1-0-1-2018-10-26"]],"v1.0.2 - 2018-10-27":[[2,"v1-0-2-2018-10-27"]],"v1.0.3 - 2018-10-27":[[2,"v1-0-3-2018-10-27"]],"v1.0.4 - 2018-10-27":[[2,"v1-0-4-2018-10-27"]],"v1.0.5- 2018-10-27":[[2,"v1-0-5-2018-10-27"]],"v1.1.0 - 2018-10-27":[[2,"v1-1-0-2018-10-27"]],"v1.1.1 - 2018-10-29":[[2,"v1-1-1-2018-10-29"]],"v1.1.2 - 2018-11-11":[[2,"v1-1-2-2018-11-11"]],"v1.1.3 - 2019-01-12":[[2,"v1-1-3-2019-01-12"]],"v1.2.0 - 2018-12-29":[[2,"v1-2-0-2018-12-29"]],"v1.3.0 - 2019-02-22":[[2,"v1-3-0-2019-02-22"]],"v1.3.1 - 2019-04-28":[[2,"v1-3-1-2019-04-28"]],"v1.3.2 - 2019-08-15":[[2,"v1-3-2-2019-08-15"]],"v2.0.0 - 2019-09-19":[[2,"v2-0-0-2019-09-19"]],"v2.0.1 - 2019-09-20":[[2,"v2-0-1-2019-09-20"]],"v2.0.2 - 2019-09-20":[[2,"v2-0-2-2019-09-20"]],"v2.0.3 - 2019-09-20":[[2,"v2-0-3-2019-09-20"]],"v2.0.4 - 2019-11-19":[[2,"v2-0-4-2019-11-19"]],"v2.0.5 - 2019-12-15":[[2,"v2-0-5-2019-12-15"]],"v3.0.0 - 2026-03-22":[[2,"v3-0-0-2026-03-22"]]},"docnames":["api","backlog","changes","cli","deployment","guide-config","index","quickstart","sandbox","testing","tour","tutorial-auth","tutorial-flask","tutorial-middleware","tutorial-rest","tutorial-sqlalchemy","tutorial-websockets"],"envversion":{"sphinx":65,"sphinx.domains.c":3,"sphinx.domains.changeset":1,"sphinx.domains.citation":1,"sphinx.domains.cpp":9,"sphinx.domains.index":1,"sphinx.domains.javascript":3,"sphinx.domains.math":2,"sphinx.domains.python":4,"sphinx.domains.rst":2,"sphinx.domains.std":2,"sphinx.ext.viewcode":1},"filenames":["api.rst","backlog.md","changes.md","cli.rst","deployment.rst","guide-config.rst","index.rst","quickstart.rst","sandbox.md","testing.rst","tour.rst","tutorial-auth.rst","tutorial-flask.rst","tutorial-middleware.rst","tutorial-rest.rst","tutorial-sqlalchemy.rst","tutorial-websockets.rst"],"indexentries":{"accepts() (responder.request method)":[[0,"responder.Request.accepts",false]],"add_event_handler() (responder.api method)":[[0,"responder.API.add_event_handler",false]],"add_middleware() (responder.api method)":[[0,"responder.API.add_middleware",false]],"add_route() (responder.api method)":[[0,"responder.API.add_route",false]],"after_request() (responder.api method)":[[0,"responder.API.after_request",false]],"api (class in responder)":[[0,"responder.API",false]],"apparent_encoding (responder.request property)":[[0,"responder.Request.apparent_encoding",false]],"backgroundqueue (class in responder.background)":[[0,"responder.background.BackgroundQueue",false]],"before_request() (responder.api method)":[[0,"responder.API.before_request",false]],"check() (responder.ext.ratelimit.ratelimiter method)":[[0,"responder.ext.ratelimit.RateLimiter.check",false]],"client (responder.request property)":[[0,"responder.Request.client",false]],"content (responder.request property)":[[0,"responder.Request.content",false]],"cookies (responder.request property)":[[0,"responder.Request.cookies",false]],"encoding (responder.request property)":[[0,"responder.Request.encoding",false]],"exception_handler() (responder.api method)":[[0,"responder.API.exception_handler",false]],"file() (responder.response method)":[[0,"responder.Response.file",false]],"full_url (responder.request property)":[[0,"responder.Request.full_url",false]],"get() (responder.models.querydict method)":[[0,"responder.models.QueryDict.get",false]],"get_list() (responder.models.querydict method)":[[0,"responder.models.QueryDict.get_list",false]],"graphql() (responder.api method)":[[0,"responder.API.graphql",false]],"group() (responder.api method)":[[0,"responder.API.group",false]],"headers (responder.request property)":[[0,"responder.Request.headers",false]],"install() (responder.ext.ratelimit.ratelimiter method)":[[0,"responder.ext.ratelimit.RateLimiter.install",false]],"is_100() (in module responder.status_codes)":[[0,"responder.status_codes.is_100",false]],"is_200() (in module responder.status_codes)":[[0,"responder.status_codes.is_200",false]],"is_300() (in module responder.status_codes)":[[0,"responder.status_codes.is_300",false]],"is_400() (in module responder.status_codes)":[[0,"responder.status_codes.is_400",false]],"is_500() (in module responder.status_codes)":[[0,"responder.status_codes.is_500",false]],"is_json (responder.request property)":[[0,"responder.Request.is_json",false]],"is_secure (responder.request property)":[[0,"responder.Request.is_secure",false]],"items() (responder.models.querydict method)":[[0,"responder.models.QueryDict.items",false]],"items_list() (responder.models.querydict method)":[[0,"responder.models.QueryDict.items_list",false]],"media() (responder.request method)":[[0,"responder.Request.media",false]],"method (responder.request property)":[[0,"responder.Request.method",false]],"mimetype (responder.request property)":[[0,"responder.Request.mimetype",false]],"module":[[0,"module-responder",false]],"mount() (responder.api method)":[[0,"responder.API.mount",false]],"ok (responder.response property)":[[0,"responder.Response.ok",false]],"on_event() (responder.api method)":[[0,"responder.API.on_event",false]],"params (responder.request property)":[[0,"responder.Request.params",false]],"path_matches_route() (responder.api method)":[[0,"responder.API.path_matches_route",false]],"path_params (responder.request property)":[[0,"responder.Request.path_params",false]],"querydict (class in responder.models)":[[0,"responder.models.QueryDict",false]],"ratelimiter (class in responder.ext.ratelimit)":[[0,"responder.ext.ratelimit.RateLimiter",false]],"redirect() (responder.api method)":[[0,"responder.API.redirect",false]],"redirect() (responder.response method)":[[0,"responder.Response.redirect",false]],"request (class in responder)":[[0,"responder.Request",false]],"requests (responder.api property)":[[0,"responder.API.requests",false]],"responder":[[0,"module-responder",false]],"response (class in responder)":[[0,"responder.Response",false]],"route() (responder.api method)":[[0,"responder.API.route",false]],"routegroup (class in responder.api)":[[0,"responder.api.RouteGroup",false]],"run() (responder.api method)":[[0,"responder.API.run",false]],"run() (responder.background.backgroundqueue method)":[[0,"responder.background.BackgroundQueue.run",false]],"schema() (responder.api method)":[[0,"responder.API.schema",false]],"serve() (responder.api method)":[[0,"responder.API.serve",false]],"session (responder.request property)":[[0,"responder.Request.session",false]],"session() (responder.api method)":[[0,"responder.API.session",false]],"set_cookie() (responder.response method)":[[0,"responder.Response.set_cookie",false]],"sse() (responder.response method)":[[0,"responder.Response.sse",false]],"state (responder.request property)":[[0,"responder.Request.state",false]],"static_app (responder.api property)":[[0,"responder.API.static_app",false]],"status_code_safe (responder.response property)":[[0,"responder.Response.status_code_safe",false]],"stream() (responder.response method)":[[0,"responder.Response.stream",false]],"stream_file() (responder.response method)":[[0,"responder.Response.stream_file",false]],"task() (responder.background.backgroundqueue method)":[[0,"responder.background.BackgroundQueue.task",false]],"template() (responder.api method)":[[0,"responder.API.template",false]],"template_string() (responder.api method)":[[0,"responder.API.template_string",false]],"text (responder.request property)":[[0,"responder.Request.text",false]],"url (responder.request property)":[[0,"responder.Request.url",false]],"url_for() (responder.api method)":[[0,"responder.API.url_for",false]]},"objects":{"":[[0,0,0,"-","responder"]],"responder":[[0,1,1,"","API"],[0,1,1,"","Request"],[0,1,1,"","Response"]],"responder.API":[[0,2,1,"","add_event_handler"],[0,2,1,"","add_middleware"],[0,2,1,"","add_route"],[0,2,1,"","after_request"],[0,2,1,"","before_request"],[0,2,1,"","exception_handler"],[0,2,1,"","graphql"],[0,2,1,"","group"],[0,2,1,"","mount"],[0,2,1,"","on_event"],[0,2,1,"","path_matches_route"],[0,2,1,"","redirect"],[0,3,1,"","requests"],[0,2,1,"","route"],[0,2,1,"","run"],[0,2,1,"","schema"],[0,2,1,"","serve"],[0,2,1,"","session"],[0,3,1,"","static_app"],[0,2,1,"","template"],[0,2,1,"","template_string"],[0,2,1,"","url_for"]],"responder.Request":[[0,2,1,"","accepts"],[0,3,1,"","apparent_encoding"],[0,3,1,"","client"],[0,3,1,"","content"],[0,3,1,"","cookies"],[0,3,1,"","encoding"],[0,3,1,"","full_url"],[0,3,1,"","headers"],[0,3,1,"","is_json"],[0,3,1,"","is_secure"],[0,2,1,"","media"],[0,3,1,"","method"],[0,3,1,"","mimetype"],[0,3,1,"","params"],[0,3,1,"","path_params"],[0,3,1,"","session"],[0,3,1,"","state"],[0,3,1,"","text"],[0,3,1,"","url"]],"responder.Response":[[0,2,1,"","file"],[0,3,1,"","ok"],[0,2,1,"","redirect"],[0,2,1,"","set_cookie"],[0,2,1,"","sse"],[0,3,1,"","status_code_safe"],[0,2,1,"","stream"],[0,2,1,"","stream_file"]],"responder.api":[[0,1,1,"","RouteGroup"]],"responder.background":[[0,1,1,"","BackgroundQueue"]],"responder.background.BackgroundQueue":[[0,2,1,"","run"],[0,2,1,"","task"]],"responder.ext.ratelimit":[[0,1,1,"","RateLimiter"]],"responder.ext.ratelimit.RateLimiter":[[0,2,1,"","check"],[0,2,1,"","install"]],"responder.models":[[0,1,1,"","QueryDict"]],"responder.models.QueryDict":[[0,2,1,"","get"],[0,2,1,"","get_list"],[0,2,1,"","items"],[0,2,1,"","items_list"]],"responder.status_codes":[[0,4,1,"","is_100"],[0,4,1,"","is_200"],[0,4,1,"","is_300"],[0,4,1,"","is_400"],[0,4,1,"","is_500"]]},"objnames":{"0":["py","module","Python module"],"1":["py","class","Python class"],"2":["py","method","Python method"],"3":["py","property","Python property"],"4":["py","function","Python function"]},"objtypes":{"0":"py:module","1":"py:class","2":"py:method","3":"py:property","4":"py:function"},"terms":{"":[0,2,3,4,5,6,7,9,10,11,12,13,15,16],"0":[3,4,5,7,10,14,15],"00":0,"01":0,"0441172719":14,"1":[0,3,4,5,7,10,11,12,14,16],"10":[0,6,7,10],"100":[0,2,10],"127":[3,4,5],"13":4,"150mb":4,"1965":14,"2":[4,7,9,10,14,15,16],"200":[0,7,9,10,14],"201":[7,9,12,14,15],"2026":0,"204":[14,15],"24":11,"2xx":0,"3":[4,6,7,9,10,14,16],"3000":5,"301":[0,7],"308":2,"32":5,"3600":[0,10],"3f":13,"4":[4,7],"40":2,"400":[0,9,10,14],"401":[0,10,11],"404":[0,7,12,14,15],"41d4":7,"422":[2,9,10,14],"429":[0,10],"446655440000":7,"500":[2,7,9,10,13,14],"5000":10,"5042":[3,4,7,11,14,16],"550e8400":7,"561":2,"60":[0,2,10],"600":[0,10],"7":11,"8":0,"80":4,"8000":[4,7],"8192":0,"9":9,"978":14,"99":9,"A":[0,4,5,6,7,10,13,16],"And":[5,6,7],"As":[0,10],"But":[7,9,10],"By":[3,7,9,10,13,14],"For":[0,3,4,5,7,9,10,11,14,15],"If":[0,3,5,6,7,9,10,12,15],"In":[0,5,6,7,10,11,12,15,16],"It":[0,3,6,9,10,13],"No":[6,9,10,12,14],"Not":7,"On":[5,10],"One":[6,7,9],"Or":[0,5],"That":[4,6,7,9],"The":[2,3,4,5,7,9,10,11,13,14,15,16],"There":[9,10],"These":7,"To":[14,15],"Will":0,"With":[0,5],"__init__":11,"__main__":[4,6,7,9,14,15],"__name__":[4,6,7,9,10,12,14,15],"__tablename__":15,"_route_for":2,"a2wsgi":2,"a716":7,"abc":14,"abc123":[0,9,10,11],"abil":2,"abl":0,"abort":12,"about":[4,7,9,12],"abov":[6,11],"abstract":15,"accept":[0,2,7,9,10,16],"access":[0,4,10,11,15],"acm":3,"acquir":8,"across":[4,10,15],"activ":[8,16],"actual":[0,7,10],"ad":[0,1,6,10],"adapt":10,"add":[0,1,2,5,7,11,13,14,15,16],"add_event_handl":0,"add_head":[10,13],"add_middlewar":[0,13],"add_request_id":0,"add_rout":[0,10],"add_tim":[9,10],"add_vers":9,"addeventlisten":16,"addit":[0,13],"address":[0,5,7,10],"adher":2,"admin":11,"affect":10,"after":[0,6,7,11,15,16],"after_request":[0,1,2,9,10,13],"ag":[0,10],"again":11,"against":[0,4,10,11],"agre":7,"ai":10,"aiosqlit":15,"alemb":15,"algorithm":11,"alias":2,"alic":10,"all":[0,2,3,4,6,8,9,10,12,13,15,16],"alloc":9,"allow":[6,10],"allow_credenti":[0,10],"allow_head":[0,10],"allow_method":[0,5,10],"allow_origin":[0,5,10],"allow_origin_regex":0,"allowed_host":[0,5,10],"alongsid":10,"alpin":4,"alreadi":[0,9,10],"also":[0,2,3,7,9,10],"altern":[0,10],"alwai":[4,5,6,7,10],"an":[0,3,5,7,10,12,13,14,15,16],"analysi":10,"angle_bracket":12,"angular":10,"ani":[0,3,4,5,6,7,9,10,11,13,14,15,16],"annot":[6,7,10],"annual":[7,10],"answer":[10,16],"anyon":6,"anyth":7,"anywher":[4,10],"api":[2,3,4,5,6,7,10,13,15,16],"api_kei":11,"api_v1":12,"apispec":2,"app":[0,2,3,4,5,6,7,9,12,14,15,16],"appar":0,"apparent_encod":0,"appear":10,"appendchild":16,"appli":[0,13],"applic":[0,2,3,4,5,7,9,10,11,13,14,15],"approach":[5,10,11,12],"appropri":[10,15],"ar":[0,2,3,4,6,7,9,10,11,12,13,15,16],"architectur":10,"aren":[7,13],"arg":[0,12],"argument":[0,2,7,12,13],"around":[0,6],"arriv":[7,12],"asgi":[0,2,4,6,7,10,12,13],"ask":[6,10,16],"assert":[9,16],"asset":[0,4,6,10],"assign":14,"associ":0,"async":[0,1,2,4,6,7,9,10,11,12,13,14,15,16],"async_sess":15,"async_sessionmak":15,"asynccontextmanag":[10,15],"asynchron":[2,4],"asyncio":15,"asyncpg":15,"attach":10,"attack":[4,5,10],"attribut":[0,3,15],"audio":16,"auth":[6,10,13],"auth_check":10,"auth_guard":11,"authent":[6,7,10,13,16],"autherror":11,"author":[0,7,8,10,11,13,14,15],"auto":[2,10,16],"auto_escap":0,"autobuild":8,"autoincr":15,"automat":[0,2,4,5,6,7,9,10,11,12,13,14,15],"avail":[0,7],"avoid":[9,10],"aw":4,"await":[0,2,7,9,10,11,12,13,14,15,16],"azur":[3,4],"b":[7,9,13,15,16],"back":[0,7,10,15,16],"background":[2,6],"backgroundqueu":0,"backlog":6,"bad":[9,10,14],"balanc":4,"bandwidth":10,"bar":10,"base":[0,2,6,11,13,15],"base_url":0,"basehttpmiddlewar":13,"basemodel":[0,9,10,14,15],"basic":7,"batteri":6,"battl":6,"bearer":6,"becaus":[0,6,7,11,12,14],"becom":[0,15],"been":0,"befor":[0,2,6,7,11,13,15],"before_request":[0,1,2,9,10,11,12,13,16],"begin":15,"behavior":[5,13],"behind":[4,10],"being":0,"best":6,"better":6,"between":13,"bidirect":[10,16],"big":6,"biggest":12,"bin":8,"binari":[7,10,16],"bind":[0,4,5,7],"blob":3,"block":[0,7,9,10,12,16],"blueprint":6,"bodi":[0,2,7,9,10,12,14,16],"boilerpl":6,"book":[6,15],"book_id":[14,15],"bookin":[14,15],"bookout":15,"books_db":14,"bool":5,"born":6,"both":[6,7,10,12,16],"bottom":14,"box":13,"bp":12,"break":9,"bring":6,"broadcast":16,"broke":[7,9],"broker":7,"browser":[7,8,10,11,14,16],"bucket":[0,10],"buffer":[0,7],"bufix":2,"bug":[2,9],"bugfix":2,"build":[2,4,6,7,8,10,11,15,16],"builder":15,"built":[2,4,6,7,9,10,16],"bump":2,"bypass":4,"byte":[0,2,6,7,13,16],"c":[5,16],"cach":[7,9,10],"caddi":4,"call":[3,7,9,10,13,14,16],"call_next":13,"callabl":0,"came":7,"can":[0,2,3,4,5,6,7,9,10,11,12,13,14,15,16],"carri":7,"case":[0,6,7,13],"cat":10,"catalog":14,"catch":[10,11,13],"categori":0,"cd":8,"ceas":2,"celeri":7,"cell":10,"central":[0,7],"certain":0,"certif":4,"chang":[0,15],"changelog":6,"channel":[10,16],"chardet":0,"chat":[6,10],"check":[0,8,9,10,11,13,16],"check_api_kei":11,"check_auth":0,"check_exist":[0,10,14,15],"choic":[7,10],"choos":10,"chunk":[0,10],"chunk_siz":0,"ci":2,"circuit":[0,1,2,6,10],"class":[2,6,7,9,11,13,14,15],"clean":[6,10,14],"cleaner":[10,11],"cleanli":5,"cleanup":10,"clear":11,"cli":2,"click":6,"client":[0,2,6,7,9,10,11,14],"clone":8,"close":[9,10,15,16],"close_database_connection_pool":0,"cloud":[3,5,6,7],"cmd":4,"code":[2,3,4,5,6,7,8,9,10,11,14,15,16],"collabor":[10,16],"colon":3,"column":15,"com":[0,3,5,7,8,10],"combin":7,"come":[7,10,12],"command":[4,6],"commit":[5,15],"common":[3,4,5,7,10,11,12,13,14],"commonli":7,"commun":[10,11],"compact":10,"compat":[0,2],"complement":[1,10],"complet":[7,10,14,16],"complex":[13,15],"compon":13,"compos":15,"compress":[6,7,13],"compromis":5,"comput":7,"concept":[2,10,12],"concern":[7,13],"concurr":[0,4],"condit":[9,10],"config":[5,15],"configur":[0,2,4,6,7,9,10,13],"conflict":2,"confus":9,"conn":15,"connect":[0,4,7,9,10,15,16],"consid":[1,7,15],"consist":[7,10],"consol":[10,15],"const":[10,16],"constructor":[0,13],"consum":10,"contact":0,"contain":[0,4,7],"container":4,"content":[0,2,6,7,9,10,14],"content_typ":[0,9,10],"context":[2,6,9,10,15,16],"contextlib":[10,15],"continu":7,"contract":9,"control":[0,4,5,7,10,11,15],"conveni":[0,5,15],"convent":[4,14],"convert":[2,7],"convertor":[2,6,12],"cooki":[0,2,5,6,7,11,12,13],"copi":4,"cor":[0,2,5,6,9,13],"core":[2,4],"coroutin":0,"correctli":4,"correspond":15,"cors_en":5,"cors_origin":5,"cors_param":[0,5,10],"corsmiddlewar":13,"count":2,"cover":[5,11,13],"cpu":[0,4,7],"crash":2,"creat":[0,6,8,9,10,11,12,15],"create_al":15,"create_asgi_app":10,"create_async_engin":15,"create_book":[14,15],"create_connect":16,"create_item":[0,10,12],"create_pet":10,"create_token":11,"createel":16,"creation":15,"credenti":11,"cross":[10,13],"crud":[6,7,14],"css":10,"csv":10,"curl":[3,7,11,14],"curly_brac":12,"custom":[0,2,6,7,9,14,16],"cut":13,"cycl":7,"d":[7,9,14],"dashboard":[5,10,11,16],"data":[0,2,5,6,7,9,10,11,12,14,15],"databas":[5,6,7,9,10,11,14],"database_url":[5,15],"date":0,"datetim":11,"db":[5,15],"debug":[0,2,6,10,12],"decim":7,"declar":[2,7],"declarativebas":15,"decod":[2,10,11],"decor":[0,2,7,10],"deep":6,"def":[0,6,7,9,10,11,12,13,14,15,16],"def456":11,"default":[0,1,2,3,5,7,9,10,15],"default_valu":[0,10],"defend":10,"defin":[0,6,7,10,11],"definit":0,"del":14,"delet":[5,6,7,10,15],"delete_book":[14,15],"deliber":7,"demo":3,"denpend":2,"dep":2,"depend":[2,4,9,13],"deploi":[4,6],"deploy":6,"depth":10,"describ":10,"descript":[0,10],"design":[7,10,14],"detail":[4,5,10,14],"detect":[0,6,10],"dev":[2,5],"develop":[3,4,5,10,15],"devic":10,"dict":[6,7,10,11,14,15],"dictionari":0,"differ":[0,3,5,6,9,10,15],"digit":7,"direct":[0,2,10],"directli":[3,6,7,9,14,15],"directori":[0,7,10],"disabl":[9,15],"discard":16,"disconnect":16,"disk":[0,7,10],"dispatch":[2,10,13],"dispos":15,"distribut":[4,10],"div":16,"django":[6,10],"do":[4,5,7,10],"doc":[8,9,10,11,14],"docker":[5,6],"dockerfil":4,"docs_rout":[0,10,14],"docstr":10,"doctyp":16,"document":[0,2,4,6,8,14,16],"doe":15,"doesn":[0,10,14,15],"domain":[0,5,10],"don":[5,7,9,10,11,12,15],"done":4,"dot":3,"dotenv":5,"doubl":14,"down":[10,15],"download":10,"dramat":2,"driver":15,"drop":[2,16],"dump":2,"dune":14,"duplex":10,"duplic":10,"durat":13,"dure":[3,4,9,15],"duti":14,"dynam":7,"e":[0,16],"e29b":7,"each":[0,4,9,10,15],"easi":[3,5,7],"echo":[6,7,15],"ecosystem":[6,7],"edit":8,"editor":[10,16],"effect":[9,14],"effici":4,"either":[0,16],"element":[0,10],"els":[7,10,11,12,15],"email":7,"emb":10,"empti":[0,14],"enabl":[2,10,13,14],"enable_async":7,"enable_hst":[0,10,13],"encod":[0,2,11],"encrypt":11,"end":[7,14],"endpoint":[0,2,6,9,10,11,12,14],"enforc":10,"engin":[7,15],"enough":[4,13],"ensur":[10,14,15,16],"enter":[9,16],"entir":[0,10,11,13,14],"entri":14,"env":[4,6],"environ":[0,3,4,6,7],"eol":2,"equival":12,"error":[0,2,5,6,15],"errorhandl":12,"escap":0,"essenti":10,"establish":16,"etc":[7,9,10],"even":[3,4,10,16],"event":[0,2,6,7,12,16],"event_typ":0,"eventsourc":10,"ever":[5,6],"everi":[0,4,5,6,7,9,10,11,13,14,15],"everyth":[0,2,4,7,10,12,14,15,16],"everywher":[3,5],"evolv":15,"exactli":[9,10],"exampl":[0,3,5,7,10,11],"exc":[0,9,10,11,14],"exceed":[0,10],"except":[0,2,6,9,10,13,16],"exception_cl":0,"exception_handl":[0,2,9,10,11,12,14],"exceptionmiddlewar":13,"execut":15,"exist":[0,2,6,12,13],"exit":[9,10,16],"exp":11,"expect":7,"expir":[0,10,11],"expire_on_commit":15,"explain":10,"explan":0,"explicit":[7,10,12],"explicitli":[10,12],"explor":[1,7,10],"export":[5,10],"expos":[4,5],"expose_head":0,"express":[6,7],"ext":[0,2,10,15],"extens":[2,7],"extern":7,"extra":[2,4,10],"extract":0,"extrem":7,"f":[0,6,7,9,10,11,13,14,16],"factori":15,"fail":[9,10,15],"failur":[2,9],"falcon":[6,10],"fall":0,"fals":[0,5,9,10,14,15],"familiar":[6,12],"fast":[4,6,7,9],"fastapi":6,"faster":10,"featur":[0,6,7],"feed":10,"feel":6,"fetch":3,"few":12,"fido":10,"field":[0,2,9,10,14],"figur":7,"file":[0,2,4,6,7,14,15,16],"filenam":[0,9],"filepath":7,"filesystem":[2,3],"fill":7,"filter":[6,7],"final":16,"find":[3,10,12],"fine":[4,10,15],"fire":[0,9],"first":[0,10,11,13,14,15],"fit":6,"fix":8,"fixtur":6,"flag":[4,10,15],"flask":[6,10],"flask_app":[10,12],"flatten":2,"float":[0,7,9],"flow":[11,13],"fly":4,"follow":7,"font":10,"forg":[5,10],"forget":0,"form":[0,7,11,12],"format":[0,2,6,7,8,10,11],"formerli":10,"forward":[4,10],"found":[2,7,14,15],"foundat":10,"fragment":3,"framework":[6,10],"franca":7,"frank":14,"freeli":16,"fresh":9,"from":[0,2,4,5,6,7,9,10,11,13,14,15,16],"from_attribut":15,"front":4,"frontend":[6,10],"fsspec":3,"full":[0,2,3,7,10],"full_url":[0,7,10],"fulli":7,"fun":6,"func":0,"function":[0,7,10,12,13],"futur":[0,6],"g":0,"game":[10,16],"gatewai":4,"gener":[0,2,5,6,9,10,13,14],"get":[0,2,5,7,10,11,15],"get_book":[14,15],"get_list":0,"get_m":11,"get_us":[0,10,12],"getelementbyid":16,"getenv":5,"git":[5,8],"github":[3,8],"gitignor":5,"give":[0,9,10,13,15],"given":[0,9],"global":[12,14],"gmt":0,"go":[7,12],"goe":[10,12],"good":[4,6,10],"googl":[3,4],"grace":4,"grade":7,"gradual":[6,10],"graduat":13,"grain":15,"graphen":[0,2,6,10],"graphiql":[2,6,10],"graphql":[0,2,6],"great":[3,6,10],"greet":[6,7,10],"greet_world":6,"greetingresourc":10,"group":[2,6],"grow":10,"guard":[6,11],"guid":[5,7,11,12,15],"guido":7,"gzip":[6,7],"gzipmiddlewar":13,"h":[7,11,14],"h1":[7,11],"ha":[7,9,12,14,16],"half":7,"halv":10,"hand":0,"handl":[0,2,4,5,6,7,11,16],"handle_auth_error":11,"handle_value_error":[0,10,14],"handler":[0,6,9,10,11,13,14],"handshak":16,"happen":[6,7],"hard":9,"hasn":0,"have":[0,2,3,7,9,12,13,14],"hdf":3,"head":3,"header":[0,2,4,5,6,7,10,11,12,13,16],"health":11,"heavi":7,"hello":[0,3,6,9,10,12,16],"hello_html":7,"hello_json":7,"hello_to":7,"hello_world":7,"helloworld":3,"help":[0,15],"helper":[6,11],"herbert":14,"here":[4,5,7,10,12,16],"high":[4,10],"hold":[0,6,7],"home":6,"honor":[4,7],"hood":10,"hook":[0,1,2,6,7,11],"host":[0,2,4,6,7,13],"hostnam":10,"hour":[10,11],"how":[5,6,7,10,11,12,14,15],"hs256":11,"hst":6,"html":[0,2,6,7,10,11,12],"http":[0,2,3,4,5,6,7,8,9,10,11,14,16],"httponli":[0,10],"httpsredirect":0,"httpsredirectmiddlewar":[0,4,13],"httpx":[2,9],"i":[0,2,3,4,5,6,7,9,10,11,12,13,14,15,16],"id":[0,2,6,7,12,13,14,15,16],"idea":12,"idempot":14,"ident":12,"identifi":10,"imag":[4,7,10,16],"immedi":[0,6,7,10],"immut":2,"imperson":5,"implement":9,"import":[0,2,3,5,6,7,9,10,11,12,13,14,15,16],"improv":2,"inaccess":0,"includ":[3,4,6,7,8,9,10,11,14],"incom":[0,7,14],"incredibli":10,"independ":4,"index":[0,7,10,16],"individu":10,"industri":10,"info":[0,2,10],"inform":[0,14],"infrastructur":[4,6],"inherit":[0,10],"initi":[0,9],"inject":10,"innermost":13,"input":[2,9,10,14,16],"insensit":[0,6,7],"insid":13,"inspect":0,"instal":[0,2,3,4,5,8,10,11,16],"instanc":[0,4,6,7,9],"instant":7,"instead":[0,7,9,10,13,14,15,16],"int":[0,2,7,10,11,12,14,15],"integ":[0,7,14,15],"integr":[13,14,15],"intens":7,"intent":6,"intention":10,"interact":[2,10,14],"interfac":[4,6,7,12],"intern":[9,10,13],"invalid":[5,9,10,11],"invalidtokenerror":11,"involv":0,"io":4,"iot":10,"ip":[0,7,10],"is_100":0,"is_200":0,"is_300":0,"is_400":0,"is_500":0,"is_class_bas":2,"is_json":[0,2,7],"is_secur":[0,7],"isbn":[14,15],"isn":[7,10,12],"issu":[2,11],"item":[0,9,10,12,15],"itemin":0,"itemout":0,"items_list":0,"iter":16,"its":[0,2,4,14,15],"itself":11,"j":10,"jan":0,"javascript":[0,3,10],"jinja2":[0,7,12],"jpeg":10,"jpg":10,"json":[0,3,6,7,10,11,14,16],"jsonifi":12,"jump":7,"just":[4,9,10,13,15,16],"jwt":11,"keep":[2,5,7,9,10,13,15,16],"kei":[0,6,7,9,10,12,15,16],"kennethreitz":[3,8],"keypress":16,"keyword":[0,7,12,13],"know":[5,7],"known":[0,11],"kwarg":0,"languag":10,"larg":[0,2,10],"larger":[5,9,13],"last":[0,13],"later":[7,9],"launch":[4,6],"layer":13,"lazi":2,"lazili":0,"lead":9,"learn":10,"legaci":12,"less":10,"let":[3,4,7,10,14,15],"level":[4,13],"librari":[9,10,16],"licens":0,"lifecycl":16,"lifespan":[0,2,6,14],"lift":7,"lightn":4,"lightweight":7,"like":[4,7,9,10,11,13,14,16],"limit":[1,2,4,6,13,15,16],"line":[6,7],"liner":2,"lingua":7,"list":[0,6,7,9,10,15],"list_book":[14,15],"list_item":10,"list_pet":10,"list_us":[0,10,12],"list_users_v2":10,"live":[10,16],"ll":[6,7,10,12,14,15],"load":[0,2,3,4,5,7,10],"load_dotenv":5,"local":[3,5,6,12],"localhost":[5,7,11,14,15,16],"locat":[0,7,11,12],"log":[4,10,11,13],"log_level":2,"log_request":13,"log_respons":10,"logic":[6,7,10],"login":[10,11],"logout":11,"long":7,"look":[3,6,7],"loop":[7,12,16],"lose":[2,15],"lower":[0,5],"lowercas":7,"machin":10,"made":[0,6],"magic":12,"mai":4,"main":3,"make":[4,5,7,9,10,11,12],"malici":10,"manag":[2,5,6,9,10,11,13,15,16],"mani":[0,4,7,10],"manual":0,"map":[2,7,10,12,15],"mapper":15,"marimo":10,"mark":[2,10],"marker":2,"marshmallow":[0,2,10],"match":[0,5,7,10,14],"matter":10,"max_ag":[0,10],"maximum":0,"me":11,"mean":[4,7,12],"mechan":10,"media":[0,2,6,7,9,10,11,12,14,15],"memori":[0,2,6,7,10],"messag":[0,7,10,11,16],"messagepack":[2,6],"metadata":[0,7,15],"method":[0,6,7,9,11,12,13,14,15,16],"microservic":10,"middelwar":0,"middlewar":[0,1,2,6,7,10],"middleware_cl":0,"middleware_config":0,"might":7,"migrat":[2,6,10,15],"mime":0,"mimetyp":[0,7,10],"min":[0,10],"mind":13,"minim":[4,16],"minimum":2,"minor":2,"miss":[2,9,10,11],"mix":10,"ml":10,"mode":[0,6,8],"model":[0,6,9,10],"model_dump":15,"model_valid":15,"modern":[4,10,11,12,15],"modifi":[0,10,13,14,15],"modul":[0,2,6,7,10],"more":[0,3,4,7,10,11,12,13,14,16],"most":[0,3,4,5,7,9,10,11,13,15],"mount":[0,2,6,12],"move":[2,7,10,12],"msgpack":[2,10],"much":[7,10],"multi":0,"multipart":[2,7],"multipl":[2,4,10,14],"multiplay":[10,16],"must":[0,7,10,11,14,16],"mutabl":6,"mutat":[0,7,12],"my_templ":7,"myapi":4,"myapp":3,"mydb":15,"mysql":15,"n":[0,7],"name":[0,5,6,7,9,10,12],"namespac":2,"nativ":12,"natur":[9,15],"nearli":12,"need":[4,5,6,7,9,10,11,12,13,15,16],"negoti":[0,6,7,9,10],"nervou":7,"network":9,"never":[5,10,11,14],"new":[0,7,9,10,12,14,16],"new_endpoint":12,"next":[6,13],"next_id":14,"nginx":4,"non":7,"none":[0,2,11,14,15],"normal":[10,16],"notabl":2,"notasecret":0,"note":[7,10,12,14],"notebook":10,"notic":7,"notif":10,"now":[2,7,10,11,15,16],"npm":3,"nullabl":15,"number":[0,7],"o":[0,5,7,12],"object":[0,2,7,10,12,13,15,16],"objecttyp":[0,10],"obviou":9,"off":[5,7],"offload":4,"offset":15,"often":[3,7,10],"ok":[0,7,9,14],"old":12,"on_delet":10,"on_ev":[0,9,10],"on_get":[6,10],"on_post":[6,10],"on_put":10,"on_request":[6,10],"on_startup":9,"onc":[10,12,14],"one":[0,2,5,6,7,10,12,15],"ones":[6,7,10],"onion":13,"onli":[0,5,7,10,12,14],"onmessag":[10,16],"open":[2,7,8,15],"open_database_connection_pool":0,"openapi":[0,2,6,14],"openapi_rout":0,"openapi_them":0,"oper":[7,10,12,14],"opt":10,"option":[0,2,4,6,7,13],"option1":13,"option2":13,"order":[0,6],"order_bi":15,"organ":[0,5,9,10,12],"origin":10,"orm":15,"other":[0,2,6,7,15],"otherwis":[0,10],"our":14,"out":[5,6,7,13],"outermost":13,"outgo":7,"output":14,"outsid":13,"over":[0,6,7,10,12,15],"overal":2,"overhead":9,"overrid":[0,10],"overwhelm":10,"own":[4,10,15],"p":[4,11,16],"pace":10,"packag":[2,3,4],"page":[0,2,5,7,10,11,16],"pagin":7,"painless":9,"pair":0,"param":[0,2,6,7,12],"paramet":[0,6,9,10,14],"parameter":0,"pars":[0,2,7,9,10],"parser":2,"part":[2,6,7,10],"parti":6,"pass":[0,7,9,12,13,15,16],"passion":6,"password":11,"patch":[7,10],"path":[0,2,3,6,7,9,10,11,13],"path_matches_rout":0,"path_param":[0,2,7],"pattern":[4,6,7,10,11,12,14,15],"payload":11,"pdf":[7,9,10],"pep":2,"per":[0,4,9,10],"perfect":10,"period":[0,2,10],"perman":7,"permit":10,"persist":[0,10,16],"person":6,"pet":[0,10],"petin":10,"petout":10,"petschema":[0,10],"photo":10,"piec":10,"pin":2,"pip":[2,3,4,5,6,8,11,15,16],"place":[5,10],"placehold":[7,16],"plain":[0,7,10,16],"platform":[2,5,6,7],"pleasant":6,"plot":10,"plu":15,"plugin":2,"poethepoet":2,"point":[3,4,14],"polici":10,"pool":[0,6,7,10,12,15],"popular":[7,10,15],"port":[0,4,5,7,9],"portion":0,"possibl":7,"post":[0,5,7,9,10,11,12,14,15],"postgresql":6,"potenti":2,"power":[6,9,10,13,15,16],"practic":10,"prefer":10,"prefix":[0,2,10],"present":7,"prevent":[5,10],"price":[0,9],"primari":0,"primary_kei":15,"print":[0,5,10,13,15,16],"privat":10,"proce":16,"process":[4,6,7,9,10,13],"process_data":7,"prod":5,"produc":[0,7],"product":[2,3,4,5,6,7,9,10,11,15],"profil":10,"programmat":10,"progress":10,"project":[2,3,8],"propag":9,"proper":[7,11,15],"properli":[5,9,15],"properti":[0,2,7,9],"protect":[4,11],"proto":4,"protocol":[3,7,9,10,16],"prototyp":[2,3,6],"provid":0,"proxi":6,"public":[0,6,10],"public_path":11,"push":[4,6,10],"put":[6,10,14,15],"py":[2,3,4,5,7,9,10,14,15],"pydant":[0,2,9,10,14,15],"pyjwt":11,"pyproject":2,"pytest":[6,8,9],"python":[0,2,3,4,5,6,7,10,14,15,16],"pythonpath":3,"q":[7,12],"queri":[2,6,7,10,15,16],"query_str":0,"querydict":0,"queue":[6,7],"quick":[0,3,6],"r":[7,9],"race":9,"railwai":4,"rais":[0,2,9,10,11],"raise_server_except":9,"random":[0,5],"rang":[0,7,10],"rapidoc":[0,10],"rare":7,"rate":[1,2,4,6,13],"rate_limit":0,"ratelimit":[0,2,10,13],"rather":9,"raw":[0,3,6,7,10,13,15,16],"re":[0,4,7,9,10,12,13,14,16],"reach":[11,13],"react":[2,10],"reactiv":10,"read":[0,2,5,6,10,11,12,14,15],"readabl":10,"readi":[4,5,6,7],"real":[2,5,10,11,14,15],"realli":[9,10],"receiv":[0,6,7,9,10,11,13,16],"receive_byt":[10,16],"receive_incom":7,"receive_json":[10,16],"receive_text":[9,10,16],"recommend":10,"reconnect":10,"recv":16,"redirect":[0,2,7,11,12],"redoc":[0,10],"reduc":2,"ref":3,"refactor":[2,9],"refer":[6,9],"refresh":15,"refus":10,"regist":[0,9,10,11],"register_blueprint":12,"reject":[9,10],"relat":[0,10,15],"releas":8,"reliabl":9,"remain":10,"rememb":11,"remov":[10,12,14,16],"renam":9,"render":[0,1,4,6,10],"render_async":7,"render_templ":12,"replac":[2,7,10,14],"report":[7,9,10],"repres":0,"represent":0,"req":[0,2,6,7,9,10,11,12,13,14,15,16],"request":[2,3,4,6,11,12,13,14,15],"request_id":[0,2,10,13],"request_model":[0,2,9,10,14,15],"requir":[0,2,9,10],"research":6,"resolv":[2,10],"resolve_hello":[0,10],"resourc":[7,10,14],"resp":[0,2,6,7,9,10,11,12,13,14,15,16],"respect":3,"respond":[0,2,3,4,5,7,8,9,10,11,12,13,14,15,16],"respons":[2,6,9,10,12,13,14,15,16],"response_model":[0,2,10,14,15],"rest":[4,6,7,10],"restrict":10,"result":[0,7,10,15],"resum":2,"resume_incomplet":2,"retri":[0,10],"retriev":[0,10,14],"return":[0,2,6,7,9,10,11,12,13,14,15],"reusabl":11,"revers":[0,6],"rfc3986":2,"right":[6,7,10,12,13],"roll":15,"room":6,"root":10,"rotat":5,"rout":[2,6,9,13,14,15,16],"routegroup":0,"router":2,"ruff":8,"rule":5,"run":[0,2,3,6,8,9,10,12,13,16],"run_sync":15,"runner":[2,4],"runtimeerror":0,"s3":3,"safe":[2,14],"sai":7,"said":4,"same":[3,4,6,7,10,12,14,15],"sandbox":6,"save":[7,16],"scalar":15,"scale":6,"schema":[0,2,6,10,11,14,15],"scope":[0,10,13],"scratch":[6,14],"script":16,"search":[0,2,7,10],"second":0,"secret":[6,10,11],"secret_kei":[0,5,10,11],"section":10,"secur":[0,10,13],"see":[0,4,5,7,9,10,13,14,15],"select":[0,2,15],"self":[0,10,11,13],"semant":2,"send":[0,2,6,9,10,11,14,16],"send_byt":[10,16],"send_email":0,"send_json":[10,16],"send_text":[9,10,16],"sensit":11,"sent":[0,2,6,7,13],"separ":[7,9,14],"sequenti":2,"serial":[0,2,7,10,16],"serializ":7,"serv":[0,2,3,4,5,6,7,9,14,16],"server":[0,2,3,4,5,6,9,11,13,14,15],"servererrormiddlewar":13,"servestat":2,"servic":[0,3,6,9,10,14],"session":[0,2,5,6,7,9,12,13,15],"session_id":10,"sessionmiddlewar":13,"set":[0,2,4,5,6,7,8,9,10,11,15,16],"set_cooki":[0,2,10],"set_text":0,"setattr":15,"setup":[2,5,6,9],"sever":[10,13],"sftp":3,"share":[0,3,7,9,10,15],"shell":5,"short":[0,1,2,6,10],"shorthand":0,"should":[5,14,15],"shouldn":0,"show":[2,10,12,15,16],"shut":[10,15],"shutdown":[0,4,6,9,10],"shutdwown":2,"sibl":6,"side":[7,10,11,16],"sign":[0,5,6,7,10,11,13],"signatur":[7,10,12],"signup":11,"simpl":[3,9,10,11,13,14,16],"simplecooki":0,"simpler":[7,10,11,13],"simplest":[5,7,11,13,16],"simpli":11,"simplic":[6,15],"simul":7,"sinc":[7,9],"singl":[0,2,3,6,7,10,12,15],"sit":13,"size":[0,15],"sk":11,"skip":[0,6,10],"slash":7,"sleep":[7,9],"slim":4,"slow":7,"slowlori":4,"slug":7,"small":[4,6,9,10],"smaller":4,"so":[9,10,12,13,14,15],"solv":10,"some":[4,5,10],"some_packag":13,"somemiddlewar":13,"someon":[5,7,10,16],"someth":[6,7,9,10],"sometim":[7,10],"somewher":7,"sourc":[0,5,8,10],"spawn":4,"spec":[7,10],"special":[6,10],"specif":[0,5,9,10,13,14],"specifi":3,"sphinx":8,"spin":7,"split":5,"sprawl":6,"sql":15,"sqlalchemi":[6,7,14],"sqlite":[5,15],"sse":[0,2,6],"ssl":4,"stabil":2,"stack":13,"stai":[12,15],"standard":[3,4,10,11,14],"starlett":[0,2,6,9,16],"start":[0,3,4,6,10,13,14,15],"startswith":11,"startup":[0,2,6,9,10],"state":[0,2,9,10,11],"statement":6,"static":[0,2,4,6,7,16],"static_app":0,"static_dir":[0,10],"static_rout":[0,2,10],"staticfil":0,"statu":[2,6,7,9,10,14],"status_cod":[0,6,7,9,10,11,12,13,14,15],"status_code_saf":0,"stderr":0,"stdlib":2,"still":[10,12],"stop":10,"storag":[3,6],"store":[0,5,10,11,14],"str":[0,7,9,10,11,14,15],"straightforward":10,"stranger":[0,10],"stream":[0,2,10],"stream_data":0,"stream_fil":[0,2,10],"strict":10,"string":[0,6,7,10,15,16],"strip":[2,10,11],"structur":10,"style":10,"stylesheet":10,"sub":11,"subclass":0,"subcommand":3,"subject":0,"submiss":0,"submit":0,"subrout":[6,10,12],"subsequ":[10,11],"subtl":2,"success":[0,7,14],"successfulli":14,"successor":4,"suit":9,"suppli":2,"support":[0,1,2,3,4,6,7,12,15,16],"swagger":[6,10,14],"swagger_ui":[0,10],"switch":[2,15,16],"sync":[2,6,7,12],"synchron":[0,12],"syntax":[2,6,7,12],"system":[3,7,10],"t":[0,4,5,7,9,10,11,12,13,14,15],"tabl":15,"take":[6,7],"tamper":[10,11],"target":2,"task":[0,2,6],"teach":6,"tear":10,"tell":[7,10,14,15],"templat":[0,1,2,6],"template_str":[0,7],"templates_dir":0,"termin":[3,4],"terms_of_servic":0,"test":[0,2,3,5,6,8,14],"test_500":[2,9],"test_api":9,"test_create_item":9,"test_custom_error":9,"test_echo":16,"test_head":9,"test_hello":9,"test_hook":9,"test_json":9,"test_upload":9,"test_valid":9,"test_websocket":9,"test_with_lifespan":9,"testclient":[0,2,9,16],"text":[0,2,6,7,9,10,12,16],"textcont":16,"than":[9,10,11,12,13,14],"thei":[0,5,7,10,12,13,14,16],"them":[6,7,9,10,11,12,14,16],"theme":[0,10],"themselv":10,"thi":[0,2,3,4,5,6,7,9,10,11,12,13,14,15,16],"thing":[5,6,7,9,13],"think":7,"third":6,"though":4,"thousand":4,"thread":[0,6,7,12],"threadpoolexecutor":[0,2],"three":[7,10,16],"through":[0,7,10,13,14,16],"throughput":10,"thu":0,"time":[0,2,6,7,9,10,12,13,14,15,16],"time_start":0,"timedelta":11,"timeout":4,"timingmiddlewar":13,"tip":6,"titl":[0,7,10,14,15],"tl":4,"togeth":[6,10],"token":[0,6,7,10,16],"token_hex":5,"toml":2,"too":[0,3,4,9,10],"tool":[8,13],"toolbelt":2,"toolkit":15,"top":[0,5],"total":10,"tour":[0,6,7],"trace":10,"traceback":[0,2,5,10],"track":15,"tradit":[10,11],"traffic":4,"transact":15,"transform":13,"translat":12,"transport":10,"treat":[0,10],"trick":10,"trigger":9,"true":[0,2,5,7,9,10,11,12,13,15,16],"trust":6,"trustedhostmiddlewar":[4,13],"try":[6,7,11,16],"tupl":[0,7,9],"tutori":[7,14],"two":[7,10,13],"type":[0,2,6,10,12,14,16],"typic":[7,10],"typo":[2,10],"ui":[2,6,10,14],"unauthor":[0,10,11],"under":[0,7,10,12],"understand":[6,7],"unexpectedli":16,"unhandl":13,"unicod":0,"union":2,"uniqu":10,"unit":15,"univers":5,"unknown":0,"unless":10,"unlik":10,"unmaintain":2,"unmatch":10,"unpin":2,"unrecogn":10,"until":7,"up":[0,2,7,8,10],"updat":[2,6,7,10,15,16],"update_book":[14,15],"upgrad":[2,8,10,16],"upload":[2,6,7],"url":[0,2,5,6,7,9,10,11,12,13,15],"url_for":[0,2,9],"url_prefix":12,"urllib":2,"us":[0,2,3,4,6,7,10,12,14,16],"usag":[0,2],"user":[0,5,7,10,11,12,15],"user_id":[7,10,11,12],"usernam":[10,11],"usual":9,"utcnow":11,"utf":0,"uuid":[0,2,7,10],"uuid4":0,"uv":[3,5,6,8,11,15],"uvicorn":[0,2,6,7],"uvloop":4,"v":6,"v1":[0,10],"v2":10,"valid":[0,2,6,7,10,11,13,14,15],"valu":[0,6,7,9,10,11,12,13,14,15,16],"valueerror":[0,9,10,12,14],"variabl":[0,4,6,7],"ve":[6,9,12],"venv":8,"verb":10,"veri":[0,7,15],"verifi":[9,11],"verify_token":11,"version":[0,2,9,10,14],"via":[0,2,5,10,12],"view":[0,2,6,7,9,12],"virtual":[3,4],"virtualenv":8,"visit":[10,14],"vue":10,"w":[9,10,16],"wa":[0,2,7,14],"wai":[3,4,6,7,10,11,12,13,15],"wait":12,"walk":[7,10,14],"want":[0,3,4,6,7,9,10,14,15,16],"watch":8,"we":[14,15,16],"web":[0,4,6,10,15],"websit":10,"websocket":[0,1,2,4,6],"websocket_connect":[9,16],"welcom":[6,7,11],"well":6,"went":6,"what":[0,7,9,10,16],"whatev":7,"when":[0,2,4,5,6,7,9,10,12,14,15,16],"where":[0,4,7,10,15,16],"whether":[0,7],"which":[0,2,7,9,10,12,15],"whichev":6,"while":[7,10,12,16],"whitenois":2,"who":[6,7,11],"widget":[9,10],"wildcard":10,"window":2,"wire":7,"with_app":10,"within":[2,10,15],"without":[0,2,4,7,9,10,15],"won":[7,9,10,15],"work":[3,4,5,6,7,10,13,14,15],"workdir":4,"worker":4,"world":[0,3,6,9,10,12],"worri":9,"would":9,"wrap":[0,7,9,10,13],"write":[6,7,10,12],"wrong":10,"ws_auth":16,"wsgi":[0,2,4,6,10,12],"www":5,"x":[0,4,7,9,10,11,12,13,14],"x00":16,"x01":16,"x02":16,"x89png":7,"xml":0,"xss":10,"yaml":[0,2,6,7,9,10],"year":[14,15],"yield":[0,10,15],"yml":[0,10,11],"you":[0,3,4,5,7,9,10,11,12,13,14,15,16],"your":[0,3,4,5,6,7,9,10,11,12,13],"yourself":7,"zero":4},"titles":["API Reference","Backlog","Changelog","Command Line Interface","Deployment","Configuration","Responder","Quick Start","Development Sandbox","Testing","Feature Tour","Authentication","Migrating from Flask","Writing Middleware","Building a REST API","Using SQLAlchemy","WebSocket Tutorial"],"titleterms":{"":14,"0":2,"01":2,"02":2,"03":2,"04":2,"08":2,"09":2,"1":2,"10":2,"11":2,"12":2,"13":2,"15":2,"16":2,"17":2,"18":2,"19":2,"2":2,"20":2,"2018":2,"2019":2,"2026":2,"22":2,"23":2,"24":2,"25":2,"26":2,"27":2,"28":2,"29":2,"3":2,"4":2,"5":2,"6":2,"7":2,"8":2,"9":2,"In":14,"It":[5,7,14,15],"The":[0,6,12],"ad":[2,13],"after":[9,10],"all":[5,7,14],"allow":5,"api":[0,9,11,12,14],"app":[10,11],"asset":3,"auth":11,"authent":11,"background":[0,7],"backlog":1,"base":10,"bearer":11,"befor":[9,10,16],"big":12,"blueprint":12,"book":14,"build":[3,14],"built":13,"chang":2,"changelog":2,"chat":16,"class":[0,5,10],"client":16,"cloud":4,"code":0,"command":3,"configur":5,"convertor":7,"cooki":[9,10],"cor":10,"creat":[7,14],"crud":15,"custom":[3,10,11],"data":16,"databas":15,"debug":5,"defin":[14,15],"delet":14,"deploy":4,"deprec":2,"develop":8,"dict":0,"differ":12,"directli":4,"docker":4,"document":10,"echo":16,"endpoint":15,"env":5,"environ":5,"error":[9,10,11,14],"event":[9,10],"except":11,"featur":10,"file":[3,5,9,10],"filter":10,"fix":2,"fixtur":9,"flask":12,"format":16,"from":[3,12],"frontend":3,"futur":1,"get":[6,9,14],"gradual":12,"graphql":10,"group":[0,10,12],"guid":6,"handl":[9,10,14],"header":9,"hello":7,"helper":0,"hook":[9,10,13,16],"host":[5,10],"how":16,"hst":10,"html":16,"id":10,"idea":[1,6],"instal":[6,15],"instanc":3,"interfac":3,"json":[9,12],"kei":[5,11],"launch":3,"lifespan":[9,10,15],"limit":[0,10],"line":3,"list":14,"local":4,"memori":14,"messagepack":10,"method":10,"middlewar":13,"migrat":12,"mode":5,"model":[14,15],"modul":3,"mount":10,"name":3,"next":14,"openapi":10,"oper":8,"order":13,"other":10,"out":14,"paramet":[7,12],"parti":13,"pattern":5,"platform":4,"postgresql":15,"project":[6,14],"proxi":4,"public":11,"put":[5,7],"queri":0,"queue":0,"quick":[7,12],"rate":[0,10],"read":7,"refer":[0,12],"remov":2,"render":7,"request":[0,7,9,10,16],"respond":6,"respons":[0,7],"rest":14,"revers":4,"room":16,"rout":[0,7,10,11,12],"run":[4,7,14,15],"sandbox":8,"secret":5,"send":7,"sent":10,"serv":10,"server":[7,10,16],"servic":7,"session":[10,11],"setup":[8,14,15],"shutdown":15,"singl":14,"skip":11,"sqlalchemi":15,"sse":10,"starlett":13,"start":[7,9],"startup":15,"static":10,"statu":0,"storag":14,"support":10,"task":7,"templat":[7,12],"test":[9,16],"third":13,"tip":[9,15],"togeth":[5,7],"token":11,"tour":10,"trust":10,"try":14,"tutori":[6,16],"type":7,"unreleas":2,"updat":14,"upload":9,"url":3,"us":[5,9,11,13,15],"user":6,"uvicorn":4,"v":13,"v0":2,"v1":2,"v2":2,"v3":2,"valid":9,"variabl":5,"view":10,"web":[7,11],"websocket":[9,10,16],"what":[6,13,14],"when":13,"work":16,"world":7,"write":13,"you":6,"your":[14,15]}}) \ No newline at end of file diff --git a/testing.html b/testing.html index 031454d..f68e6b6 100644 --- a/testing.html +++ b/testing.html @@ -5,13 +5,13 @@ - Testing — responder 3.2.0 documentation + Testing — responder 3.4.1 documentation - + diff --git a/tour.html b/tour.html index 37d5e51..276e4a5 100644 --- a/tour.html +++ b/tour.html @@ -5,13 +5,13 @@ - Feature Tour — responder 3.2.0 documentation + Feature Tour — responder 3.4.1 documentation - + @@ -420,6 +420,21 @@ side by side, moving routes over one at a time:

                        Requests to /flask/ will be handled by Flask. Everything else goes through Responder. Both WSGI and ASGI apps are supported — Responder wraps WSGI apps in an ASGI adapter automatically.

                        +

                        You can also mount marimo notebooks as +interactive dashboards within your API:

                        +
                        import marimo
                        +
                        +server = (
                        +    marimo.create_asgi_app()
                        +    .with_app(path="", root="./notebooks/dashboard.py")
                        +    .with_app(path="/analysis", root="./notebooks/analysis.py")
                        +)
                        +
                        +api.mount("/notebooks", server.build())
                        +
                        +
                        +

                        Notebooks are served at /notebooks/ and /notebooks/analysis, +with full interactivity — reactive cells, widgets, plots, and all.

                        Cookies

                        diff --git a/tutorial-auth.html b/tutorial-auth.html new file mode 100644 index 0000000..27c305a --- /dev/null +++ b/tutorial-auth.html @@ -0,0 +1,287 @@ + + + + + + + + Authentication — responder 3.4.1 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + +
                        +
                        +
                        + + +
                        + +
                        +

                        Authentication

                        +

                        Every API that handles user data needs authentication — a way to verify +who is making a request. This guide covers the most common patterns: +API keys, JWT tokens, and how to build reusable auth guards with +Responder’s before-request hooks.

                        +
                        +

                        API Key Authentication

                        +

                        The simplest approach. The client sends a secret key in a header, and +your server checks it against a known value. This is common for +server-to-server communication and simple APIs:

                        +
                        API_KEYS = {"sk-abc123", "sk-def456"}
                        +
                        +@api.route(before_request=True)
                        +def check_api_key(req, resp):
                        +    key = req.headers.get("X-API-Key")
                        +    if key not in API_KEYS:
                        +        resp.status_code = 401
                        +        resp.media = {"error": "Invalid or missing API key"}
                        +
                        +
                        +

                        Because the before-request hook sets resp.status_code, the route +handler is skipped entirely for unauthorized requests. The client never +reaches your endpoint — the guard catches them first.

                        +

                        The client sends the key like this:

                        +
                        $ curl -H "X-API-Key: sk-abc123" http://localhost:5042/protected
                        +
                        +
                        +
                        +
                        +

                        Bearer Token Authentication

                        +

                        Bearer tokens are the standard for modern APIs. The client sends a token +in the Authorization header, and the server validates it. The most +common format is JWT (JSON Web Tokens).

                        +

                        Install PyJWT:

                        +
                        $ uv pip install pyjwt
                        +
                        +
                        +

                        Create a helper to encode and decode tokens:

                        +
                        import jwt
                        +from datetime import datetime, timedelta
                        +
                        +SECRET = "your-secret-key"
                        +
                        +def create_token(user_id: int) -> str:
                        +    payload = {
                        +        "sub": user_id,
                        +        "exp": datetime.utcnow() + timedelta(hours=24),
                        +    }
                        +    return jwt.encode(payload, SECRET, algorithm="HS256")
                        +
                        +def verify_token(token: str) -> dict | None:
                        +    try:
                        +        return jwt.decode(token, SECRET, algorithms=["HS256"])
                        +    except jwt.InvalidTokenError:
                        +        return None
                        +
                        +
                        +

                        Add a login endpoint that issues tokens, and a before-request hook that +verifies them:

                        +
                        @api.route("/login", methods=["POST"])
                        +async def login(req, resp):
                        +    data = await req.media()
                        +    # In a real app, check credentials against a database
                        +    if data.get("username") == "admin" and data.get("password") == "secret":
                        +        token = create_token(user_id=1)
                        +        resp.media = {"token": token}
                        +    else:
                        +        resp.status_code = 401
                        +        resp.media = {"error": "Invalid credentials"}
                        +
                        +@api.route(before_request=True)
                        +def auth_guard(req, resp):
                        +    # Skip auth for the login endpoint itself
                        +    if req.url.path == "/login":
                        +        return
                        +
                        +    auth = req.headers.get("Authorization", "")
                        +    if not auth.startswith("Bearer "):
                        +        resp.status_code = 401
                        +        resp.media = {"error": "Missing bearer token"}
                        +        return
                        +
                        +    token = auth[7:]  # Strip "Bearer "
                        +    payload = verify_token(token)
                        +    if payload is None:
                        +        resp.status_code = 401
                        +        resp.media = {"error": "Invalid or expired token"}
                        +        return
                        +
                        +    # Store the authenticated user on the request state
                        +    req.state.user_id = payload["sub"]
                        +
                        +
                        +

                        Now any route can access the authenticated user:

                        +
                        @api.route("/me")
                        +def get_me(req, resp):
                        +    resp.media = {"user_id": req.state.user_id}
                        +
                        +
                        +

                        The client flow:

                        +
                          +
                        1. POST /login with credentials → receive a token

                        2. +
                        3. Include Authorization: Bearer <token> on every subsequent request

                        4. +
                        5. The token expires after 24 hours — the client must log in again

                        6. +
                        +
                        +
                        +

                        Skipping Auth for Public Routes

                        +

                        The example above skips auth for /login by checking the path. For +more control, you can use a set of public paths:

                        +
                        PUBLIC_PATHS = {"/login", "/signup", "/health", "/docs", "/schema.yml"}
                        +
                        +@api.route(before_request=True)
                        +def auth_guard(req, resp):
                        +    if req.url.path in PUBLIC_PATHS:
                        +        return
                        +    # ... check token
                        +
                        +
                        +
                        +
                        +

                        Custom Exception for Auth Errors

                        +

                        For cleaner code, define a custom exception and register a handler:

                        +
                        class AuthError(Exception):
                        +    def __init__(self, message="Unauthorized", status_code=401):
                        +        self.message = message
                        +        self.status_code = status_code
                        +
                        +@api.exception_handler(AuthError)
                        +async def handle_auth_error(req, resp, exc):
                        +    resp.status_code = exc.status_code
                        +    resp.media = {"error": exc.message}
                        +
                        +
                        +

                        Now your auth guard can simply raise:

                        +
                        @api.route(before_request=True)
                        +def auth_guard(req, resp):
                        +    if req.url.path in PUBLIC_PATHS:
                        +        return
                        +    if "Authorization" not in req.headers:
                        +        raise AuthError("Missing authorization header")
                        +
                        +
                        +
                        +
                        +

                        Using Sessions for Web Apps

                        +

                        For traditional web applications (with HTML pages and forms), cookie-based +sessions are simpler than tokens. The browser handles cookies automatically +— no client-side token management needed:

                        +
                        @api.route("/login", methods=["POST"])
                        +async def login(req, resp):
                        +    data = await req.media("form")
                        +    if data["username"] == "admin" and data["password"] == "secret":
                        +        resp.session["user"] = data["username"]
                        +        api.redirect(resp, location="/dashboard")
                        +    else:
                        +        resp.status_code = 401
                        +        resp.html = "<p>Invalid credentials</p>"
                        +
                        +@api.route("/dashboard")
                        +def dashboard(req, resp):
                        +    user = req.session.get("user")
                        +    if not user:
                        +        api.redirect(resp, location="/login")
                        +        return
                        +    resp.html = f"<h1>Welcome, {user}!</h1>"
                        +
                        +@api.route("/logout")
                        +def logout(req, resp):
                        +    resp.session.clear()
                        +    api.redirect(resp, location="/login")
                        +
                        +
                        +

                        Remember to set a proper secret key:

                        +
                        api = responder.API(secret_key="your-production-secret-key")
                        +
                        +
                        +

                        The session data is signed (not encrypted) — users can read it but +can’t tamper with it. Don’t store sensitive data like passwords in +sessions.

                        +
                        +
                        + + +
                        + +
                        +
                        + +
                        +
                        + + + + + + + \ No newline at end of file diff --git a/tutorial-flask.html b/tutorial-flask.html index 1e18b68..43226d6 100644 --- a/tutorial-flask.html +++ b/tutorial-flask.html @@ -5,13 +5,13 @@ - Migrating from Flask — responder 3.2.0 documentation + Migrating from Flask — responder 3.4.1 documentation - + @@ -21,8 +21,8 @@ - - + + diff --git a/tutorial-middleware.html b/tutorial-middleware.html new file mode 100644 index 0000000..1ca3335 --- /dev/null +++ b/tutorial-middleware.html @@ -0,0 +1,222 @@ + + + + + + + + Writing Middleware — responder 3.4.1 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + +
                        +
                        +
                        + + +
                        + +
                        +

                        Writing Middleware

                        +

                        Middleware sits between the server and your route handlers, processing +every request and response that flows through your application. It’s the +right tool for cross-cutting concerns — things that apply to all +requests, not just specific routes.

                        +

                        Common middleware use cases:

                        +
                          +
                        • Request logging and timing

                        • +
                        • Authentication and authorization

                        • +
                        • Adding security headers

                        • +
                        • Request ID generation

                        • +
                        • Rate limiting

                        • +
                        • Response compression (built-in)

                        • +
                        +
                        +

                        Hooks vs. Middleware

                        +

                        Responder gives you two levels of request processing:

                        +

                        Hooks (before_request / after_request) run inside Responder’s +routing layer. They receive Responder’s req and resp objects and +are the simplest way to add behavior:

                        +
                        @api.route(before_request=True)
                        +def add_header(req, resp):
                        +    resp.headers["X-Powered-By"] = "Responder"
                        +
                        +@api.after_request()
                        +def log_request(req, resp):
                        +    print(f"{req.method} {req.url.path} -> {resp.status_code}")
                        +
                        +
                        +

                        Middleware runs at the ASGI level, wrapping the entire application. +It’s more powerful but more complex — you work with raw ASGI scopes +instead of Responder objects. Use middleware when you need to process +requests before they reach Responder’s routing, or when you need to +integrate with Starlette middleware.

                        +
                        +
                        +

                        Using Starlette Middleware

                        +

                        Responder is built on Starlette, so any Starlette middleware works +out of the box:

                        +
                        from starlette.middleware.base import BaseHTTPMiddleware
                        +
                        +class TimingMiddleware(BaseHTTPMiddleware):
                        +    async def dispatch(self, request, call_next):
                        +        import time
                        +        start = time.time()
                        +        response = await call_next(request)
                        +        duration = time.time() - start
                        +        response.headers["X-Response-Time"] = f"{duration:.3f}s"
                        +        return response
                        +
                        +api.add_middleware(TimingMiddleware)
                        +
                        +
                        +

                        The dispatch method receives a Starlette Request and a +call_next function. Call call_next(request) to pass the request +to the next middleware (or to your route handler). The return value is +a Starlette Response that you can modify before it’s sent.

                        +
                        +
                        +

                        Built-in Middleware

                        +

                        Responder configures several middleware components automatically:

                        +
                          +
                        • GZipMiddleware — compresses responses larger than 500 bytes

                        • +
                        • TrustedHostMiddleware — validates the Host header

                        • +
                        • ServerErrorMiddleware — catches unhandled exceptions

                        • +
                        • ExceptionMiddleware — routes exceptions to your handlers

                        • +
                        • SessionMiddleware — manages signed cookie sessions

                        • +
                        +

                        Optional middleware you can enable:

                        +
                          +
                        • CORSMiddlewareapi = responder.API(cors=True)

                        • +
                        • HTTPSRedirectMiddlewareapi = responder.API(enable_hsts=True)

                        • +
                        +
                        +
                        +

                        Adding Third-Party Middleware

                        +

                        Any ASGI middleware can be added with api.add_middleware():

                        +
                        from some_package import SomeMiddleware
                        +
                        +api.add_middleware(SomeMiddleware, option1="value", option2=True)
                        +
                        +
                        +

                        Keyword arguments are passed to the middleware’s constructor.

                        +
                        +
                        +

                        Middleware Order

                        +

                        Middleware wraps your application like layers of an onion. The last +middleware added is the outermost layer — it sees the request first +and the response last.

                        +

                        Responder’s built-in middleware stack (from outermost to innermost):

                        +
                          +
                        1. SessionMiddleware

                        2. +
                        3. ServerErrorMiddleware

                        4. +
                        5. CORSMiddleware (if enabled)

                        6. +
                        7. TrustedHostMiddleware

                        8. +
                        9. HTTPSRedirectMiddleware (if enabled)

                        10. +
                        11. GZipMiddleware

                        12. +
                        13. ExceptionMiddleware

                        14. +
                        15. Your routes

                        16. +
                        +

                        When you call api.add_middleware(), your middleware is added outside +the existing stack. Keep this in mind for ordering dependencies — if +middleware A depends on middleware B having run first, add B before A.

                        +
                        +
                        +

                        When to Use What

                        +
                          +
                        • Simple header additions, logging, auth checks → use hooks

                        • +
                        • Response transformation, timing, third-party integrations → use middleware

                        • +
                        • Rate limiting → use the built-in RateLimiter (it uses hooks internally)

                        • +
                        • Request ID → use api = responder.API(request_id=True)

                        • +
                        +

                        Start with hooks. They’re simpler and cover most cases. Graduate to +middleware when hooks aren’t enough.

                        +
                        +
                        + + +
                        + +
                        +
                        + +
                        +
                        + + + + + + + \ No newline at end of file diff --git a/tutorial-rest.html b/tutorial-rest.html index ebc0b75..3e69c36 100644 --- a/tutorial-rest.html +++ b/tutorial-rest.html @@ -5,13 +5,13 @@ - Building a REST API — responder 3.2.0 documentation + Building a REST API — responder 3.4.1 documentation - + diff --git a/tutorial-sqlalchemy.html b/tutorial-sqlalchemy.html index a5e2747..b4953e7 100644 --- a/tutorial-sqlalchemy.html +++ b/tutorial-sqlalchemy.html @@ -5,13 +5,13 @@ - Using SQLAlchemy — responder 3.2.0 documentation + Using SQLAlchemy — responder 3.4.1 documentation - + @@ -21,7 +21,7 @@ - + diff --git a/tutorial-websockets.html b/tutorial-websockets.html new file mode 100644 index 0000000..451b71c --- /dev/null +++ b/tutorial-websockets.html @@ -0,0 +1,261 @@ + + + + + + + + WebSocket Tutorial — responder 3.4.1 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + +
                        +
                        +
                        + + +
                        + +
                        +

                        WebSocket Tutorial

                        +

                        HTTP is request-response — the client asks, the server answers, and the +connection closes. WebSockets upgrade that into a persistent, bidirectional +channel where both sides can send messages at any time. This is what powers +chat apps, live dashboards, multiplayer games, and collaborative editors.

                        +

                        This tutorial builds a simple chat room to show how WebSockets work in +Responder.

                        +
                        +

                        How WebSockets Work

                        +
                          +
                        1. The client sends a normal HTTP request with an Upgrade: websocket +header.

                        2. +
                        3. The server accepts the upgrade and the connection switches protocols.

                        4. +
                        5. Both sides can now send messages freely — no more request/response.

                        6. +
                        7. Either side can close the connection at any time.

                        8. +
                        +

                        In Responder, WebSocket routes receive a ws object instead of +req and resp. The ws object has methods for accepting the +connection, sending and receiving data, and closing.

                        +
                        +
                        +

                        Echo Server

                        +

                        The simplest WebSocket — echoes everything back:

                        +
                        @api.route("/ws", websocket=True)
                        +async def echo(ws):
                        +    await ws.accept()
                        +    while True:
                        +        data = await ws.receive_text()
                        +        await ws.send_text(f"Echo: {data}")
                        +
                        +
                        +

                        The await ws.accept() call completes the WebSocket handshake. After +that, you’re in a loop — receive a message, send a response.

                        +

                        Test it with a WebSocket client:

                        +
                        $ pip install websocket-client
                        +$ python -c "
                        +import websocket
                        +ws = websocket.create_connection('ws://localhost:5042/ws')
                        +ws.send('hello')
                        +print(ws.recv())  # Echo: hello
                        +ws.close()
                        +"
                        +
                        +
                        +
                        +
                        +

                        Chat Room

                        +

                        A chat room needs to broadcast messages to all connected clients. We keep +a set of active connections and iterate through them when someone sends +a message:

                        +
                        connected = set()
                        +
                        +@api.route("/chat", websocket=True)
                        +async def chat(ws):
                        +    await ws.accept()
                        +    connected.add(ws)
                        +    try:
                        +        while True:
                        +            message = await ws.receive_text()
                        +            # Broadcast to all connected clients
                        +            for client in connected:
                        +                await client.send_text(message)
                        +    except Exception:
                        +        pass
                        +    finally:
                        +        connected.discard(ws)
                        +
                        +
                        +

                        The try/finally block ensures we remove disconnected clients from +the set, even if the connection drops unexpectedly.

                        +
                        +
                        +

                        Data Formats

                        +

                        WebSockets support three data formats:

                        +

                        Text — plain strings:

                        +
                        await ws.send_text("hello")
                        +message = await ws.receive_text()
                        +
                        +
                        +

                        JSON — auto-serialized Python objects:

                        +
                        await ws.send_json({"type": "update", "data": [1, 2, 3]})
                        +message = await ws.receive_json()
                        +
                        +
                        +

                        Binary — raw bytes, useful for images, audio, or custom protocols:

                        +
                        await ws.send_bytes(b"\x00\x01\x02")
                        +data = await ws.receive_bytes()
                        +
                        +
                        +
                        +
                        +

                        HTML Client

                        +

                        Here’s a minimal HTML page that connects to the chat room. The browser’s +built-in WebSocket API handles everything — no libraries needed:

                        +
                        <!DOCTYPE html>
                        +<html>
                        +<body>
                        +  <div id="messages"></div>
                        +  <input id="input" placeholder="Type a message..." />
                        +  <script>
                        +    const ws = new WebSocket("ws://localhost:5042/chat");
                        +    const messages = document.getElementById("messages");
                        +    const input = document.getElementById("input");
                        +
                        +    ws.onmessage = (event) => {
                        +      const p = document.createElement("p");
                        +      p.textContent = event.data;
                        +      messages.appendChild(p);
                        +    };
                        +
                        +    input.addEventListener("keypress", (e) => {
                        +      if (e.key === "Enter") {
                        +        ws.send(input.value);
                        +        input.value = "";
                        +      }
                        +    });
                        +  </script>
                        +</body>
                        +</html>
                        +
                        +
                        +

                        Save this as static/index.html and serve it with Responder’s +built-in static file support.

                        +
                        +
                        +

                        Before-Request Hooks for WebSockets

                        +

                        You can run code before a WebSocket connection is established, just like +HTTP before-request hooks. This is useful for authentication:

                        +
                        @api.before_request(websocket=True)
                        +async def ws_auth(ws):
                        +    # Check for a token in the query string
                        +    # (WebSocket headers are limited in browsers)
                        +    await ws.accept()
                        +
                        +
                        +

                        WebSocket before-request hooks receive the ws object and must call +await ws.accept() if they want the connection to proceed.

                        +
                        +
                        +

                        Testing WebSockets

                        +

                        Use Starlette’s TestClient for WebSocket tests:

                        +
                        from starlette.testclient import TestClient
                        +
                        +def test_echo():
                        +    client = TestClient(api)
                        +    with client.websocket_connect("/ws") as ws:
                        +        ws.send_text("hello")
                        +        assert ws.receive_text() == "Echo: hello"
                        +
                        +
                        +

                        The websocket_connect context manager handles the connection +lifecycle — it connects on enter and disconnects on exit.

                        +
                        +
                        + + +
                        + +
                        +
                        + +
                        +
                        + + + + + + + \ No newline at end of file