Spaces:
Sleeping
Sleeping
| # app.py | |
| from fastapi import FastAPI, HTTPException, Request | |
| from fastapi.responses import StreamingResponse | |
| import qrcode | |
| import io | |
| from functools import lru_cache | |
| app = FastAPI() | |
| # --------------------------------------------------------------------------- | |
| # QR‑code generation helper (cached) | |
| # --------------------------------------------------------------------------- | |
| def _qr_png(text: str) -> bytes: | |
| """Return PNG bytes for *text*. | |
| * Uses `qrcode.make`, which is faster than constructing a `QRCode` object | |
| manually. | |
| * Memoised with `lru_cache` so repeated requests for the same text are | |
| served from memory (~10× faster, avoids QR code re‑creation and pillow | |
| image encoding). | |
| """ | |
| img = qrcode.make(text) # Fast 1‑liner QR generation | |
| buf = io.BytesIO() | |
| img.save(buf, format="PNG") | |
| return buf.getvalue() | |
| # --------------------------------------------------------------------------- | |
| # API endpoint | |
| # --------------------------------------------------------------------------- | |
| async def echo(request: Request): | |
| """Generate a QR‑code for the given JSON body. | |
| Accepted payloads: | |
| • Plain JSON string → "Hello" | |
| • Object with `text` → {"text": "Hello"} | |
| Any other JSON types are stringified via `str(payload)`. | |
| """ | |
| # --------------------------------------------------------------------- | |
| # 1. Extract JSON body | |
| # --------------------------------------------------------------------- | |
| try: | |
| payload = await request.json() | |
| except Exception: | |
| raise HTTPException(status_code=400, detail="Expected a JSON body") | |
| if payload in (None, "", []): | |
| raise HTTPException(status_code=400, detail="Payload cannot be empty") | |
| # Normalise to string | |
| text = payload["text"] if isinstance(payload, dict) and "text" in payload else str(payload) | |
| # --------------------------------------------------------------------- | |
| # 2. Build / fetch QR code PNG (cached) | |
| # --------------------------------------------------------------------- | |
| png_bytes = _qr_png(text) | |
| # --------------------------------------------------------------------- | |
| # 3. Return as stream (new BytesIO per request so multiple clients can read) | |
| # --------------------------------------------------------------------- | |
| return StreamingResponse(io.BytesIO(png_bytes), media_type="image/png") | |