Add content negotiation for /users and /objects endpoints

- /users/{username}: Redirects to /ui/user/{username} for browsers (Accept: text/html)
- /objects/{hash}: Redirects to /ui/asset/{name} for browsers
- APIs still get JSON (application/activity+json) as before

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
gilesb
2026-01-07 22:01:22 +00:00
parent 6c59ac0cbc
commit f1aea5a5f3

View File

@@ -1383,10 +1383,19 @@ async def webfinger(resource: str):
@app.get("/users/{username}")
async def get_actor(username: str, request: Request):
"""Get actor profile for any registered user."""
"""Get actor profile for any registered user. Content negotiation: HTML for browsers, JSON for APIs."""
if not user_exists(username):
raise HTTPException(404, f"Unknown user: {username}")
# Check Accept header for content negotiation
accept = request.headers.get("accept", "")
wants_html = "text/html" in accept and "application/json" not in accept and "application/activity+json" not in accept
if wants_html:
# Redirect to UI page for browsers
from fastapi.responses import RedirectResponse
return RedirectResponse(url=f"/ui/user/{username}", status_code=303)
actor = load_actor(username)
# Add ActivityPub context
@@ -1774,13 +1783,22 @@ async def get_activities():
@app.get("/objects/{content_hash}")
async def get_object(content_hash: str):
"""Get object by content hash."""
async def get_object(content_hash: str, request: Request):
"""Get object by content hash. Content negotiation: HTML for browsers, JSON for APIs."""
registry = load_registry()
# Find asset by hash
for name, asset in registry.get("assets", {}).items():
if asset.get("content_hash") == content_hash:
# Check Accept header for content negotiation
accept = request.headers.get("accept", "")
wants_html = "text/html" in accept and "application/json" not in accept and "application/activity+json" not in accept
if wants_html:
# Redirect to UI page for browsers
from fastapi.responses import RedirectResponse
return RedirectResponse(url=f"/ui/asset/{name}", status_code=303)
owner = asset.get("owner", "unknown")
return JSONResponse(
content={