Use Scope
Overview¶
use_scope is a ReactPy hook that returns the ASGI connection scope behind the current websocket.
scope = use_scope()
Use it for what the server knows about the connection: who the peer is, which headers arrived, which server accepted the request. For the page the visitor is looking at, use use_location instead.
Reference¶
use_scope()¶
Call it at the top level of a component. It takes no arguments.
from reactpy import use_scope
Returns¶
The dict at use_connection().scope — the raw ASGI scope, with the same shape as any other ASGI app's scope. It is a live dictionary: nothing copies it for you.
Read ASGI: Websockets for the specification; the keys below are what uvicorn's websocket implementation actually delivered, captured from a live Chrome session against ReactPy:
| Key | What it holds |
|---|---|
"type" | "websocket" for these connections. |
"path" | The ReactPy websocket endpoint, e.g. "/reactpy/". Not the page. |
"headers" | A list of (bytes, bytes) pairs, lower-cased by the server. |
"client" | (ip, port) of the peer, or None if unknown. |
"server" | (host, port) that accepted the connection. |
"scheme" | "ws" or "wss". |
"query_string" | The websocket URL's query string, as bytes — this carries ReactPy's own path/qs parameters. |
"raw_path" | The request path, as bytes, un-decoded. |
"root_path" | The ASGI root path, normally "". |
"http_version" | e.g. "1.1". |
"asgi" | {"version": ..., "spec_version": ...}. |
"subprotocols" | Requested websocket subprotocols, usually []. |
"state" | A dict shared across the connection's tasks; empty unless something put values in it. |
"extensions" | Server-specific extras, e.g. {"websocket.http.response": {}} under uvicorn. |
Which extras appear depends on the server: "state" and that "extensions" entry are uvicorn/websockets additions. Read them defensively, with scope.get(...).
Caveats¶
"path"is not the page. For every component in the app it is the websocket endpoint —"/reactpy/"under the defaultpath_prefix. Verified: on the page/some/deep/page?tab=2&user=ada, the scope still says"/reactpy/". Useuse_location().pathfor the page.- Headers are bytes. Both halves of each pair are
bytesand lower-cased, so compare againstb"user-agent"and.decode()the value before using it. There is no dict of headers; see the example. "query_string"is the websocket's, not the page's. It contains ReactPy's ownpath=andqs=parameters. Parse the page's query withuse_location().Noneis possible."client"can be absent orNonebehind a proxy or in-process transport.scope["client"][0]will raise onNone; check first.- It needs a live connection. In a plain
Layoutrender it raisesRuntimeError: No backend established a connection. - It does not exist under client-side rendering. With
ReactPyCsrthere is no connection object, so the hook raises the sameRuntimeError. - Like every hook, call it only at the top level.
Usage¶
Reading the peer and a header¶
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | |
1 | |
header() exists because the ASGI scope hands you raw bytes: it lower-cases the name, matches on bytes, and decodes the value. The component reads scope["client"] defensively because a proxy can leave it unset.
What belongs here and what does not¶
| You want | Use |
|---|---|
| The visitor's IP address | use_scope()["client"] |
| A request header | use_scope()["headers"] |
| The page the visitor is on | use_location |
| The query string | use_location |
| The object mediating the connection | use_connection |
Troubleshooting¶
My header lookups always return None¶
You compared against a str. The keys are bytes and lower-cased: (b"user-agent", b"Mozilla/5.0 ...").
It raises in my tests¶
A bare Layout render establishes no connection. Wrap the call in try/except RuntimeError, or inject a connection — see use_connection.
Every page shows /reactpy/¶
That is the scope's "path": the websocket endpoint, identical for all components. Use use_location().path.
I need the request path before the websocket opens¶
use_scope only exists inside a component, which means inside an established websocket. For pre-connection decisions, handle it in ASGI middleware in front of the ReactPy app — see ReactPyMiddleware.