Frequently asked questions
The questions that usually arrive just after the first successful curl request, when optimism starts acquiring requirements.
What does Wred deliberately leave out?
Authentication, sessions, database integration, schemas, templates, multipart/form parsing, CORS, CSRF protection, dependency injection, generated API docs, background jobs, WebSockets, and built-in static or streaming responses. The tutorial shows how to compose several of these from application code and ASGI libraries.
The API reference describes what the core does. A feature’s absence is permission to choose a component, not an invitation to pretend the feature is unnecessary.
Do I have to use Weft?
No. wred[server] is a convenience extra for Weft. Install the base package and your preferred ASGI server if you want something else. Wred is ASGI, not a WSGI application; use the correct interface when a server supports both.
Can I use Starlette’s Request APIs on a Wred request?
Wrapping an application with Starlette middleware does not replace the request object Wred creates. Read middleware data through request.scope, or add your own application adapter. See Request’s attributes.
request.query is a synchronous cached property. request.body() and request.json() must be awaited. Python will not reinterpret this distinction as a stylistic preference.
Why does POST or HEAD return 404?
A route defaults to GET. Register methods explicitly. Wred uses the same 404 fallback for unknown paths and unsupported methods; it does not supply automatic HEAD, OPTIONS, or 405 behavior. CORS middleware can handle browser preflights.
Why can I parse JSON null but not return None?
Input parsing accepts any JSON value. Wred’s direct response handling supports dicts, lists, and bytes, plus the documented tuple forms. Return a callable JSON response object when you need a JSON scalar, or return b"", "application/json", 204 for no content.
How do I handle forms or uploaded files?
Wred has no form or multipart parser. Choose a parser or ASGI component deliberately, install its dependencies, and arrange who reads the receive stream. A second consumer cannot reread events already consumed by the first. Enforce body and file limits before buffering uploads.
Where do startup tasks and database cleanup go?
In a lifespan-aware outer ASGI app. The notebook’s NotebookApp initializes and closes its database there. A bare Wred instance rejects lifespan. See the actual wrapper and protocol configuration.
Can Wred stream or handle WebSockets?
A handler can return a callable ASGI response such as Starlette’s StreamingResponse for HTTP streaming or SSE. WebSocket scopes are rejected by Wred itself; route them to a separate ASGI app with an outer router if you need them.
Can handlers call blocking code or launch background jobs?
Handlers are awaited on the event loop. Calling a blocking database client or doing expensive CPU work directly there blocks other requests in that worker. Use an async client, an appropriate thread for blocking I/O, or separate workers for expensive work.
A detached task is not a durable job queue. If work must survive a restart, use a durable queue and workers that own it. The operating system is unimpressed by how important your untracked task felt.
Are the notebook’s rate limits global?
No. They are per app instance and per worker. Database sessions are persistent; the in-memory timestamp buckets are not. Use shared application storage or an edge limiter for a shared policy. See the Nginx example.
Will my app get the README’s benchmark numbers?
Those numbers describe one workload on one machine with a specific server configuration. Database calls, passwords, middleware, payload size, concurrency, and client behavior all change throughput and latency. Measure the work your application actually does. A hello-world benchmark remains impressively good at saying hello.
