wiki: add Routes Reference page
69
Routes-Reference.md
Normal file
69
Routes-Reference.md
Normal file
@@ -0,0 +1,69 @@
|
||||
# Routes Reference
|
||||
|
||||
`service.router()` registers exactly these routes:
|
||||
|
||||
| Method | Path | Description |
|
||||
|--------|------|-------------|
|
||||
| `POST` | `/inbox` | Shared inbox — HTTP sig verification + dispatch, 1 MB limit |
|
||||
| `POST` | `/users/{id}/inbox` | Per-user inbox — same |
|
||||
| `GET` | `/users/{id}/outbox` | Cursor-based `OrderedCollection` |
|
||||
| `GET` | `/users/{id}/featured` | Pinned posts `OrderedCollection` |
|
||||
| `GET` | `/.well-known/webfinger` | JRD with `aliases` field |
|
||||
| `GET` | `/.well-known/nodeinfo` | Redirect to `/nodeinfo/2.0` |
|
||||
| `GET` | `/nodeinfo/2.0` | NodeInfo 2.0 document |
|
||||
|
||||
---
|
||||
|
||||
## Routes NOT registered
|
||||
|
||||
`GET /users/{id}`, `GET /users/{id}/followers`, and `GET /users/{id}/following` are **not** registered by `service.router()`.
|
||||
|
||||
These paths must serve both AP JSON (for federation) and your UI JSON (for your frontend) based on the `Accept` header. k-ap can't do the UI half, so your application owns the route and calls k-ap's helper methods for the AP half.
|
||||
|
||||
---
|
||||
|
||||
## Content negotiation pattern
|
||||
|
||||
```rust
|
||||
use axum::{extract::{Path, State}, http::HeaderMap, response::IntoResponse, Json};
|
||||
|
||||
async fn actor_handler(
|
||||
Path(username): Path<String>,
|
||||
headers: HeaderMap,
|
||||
State(state): State<AppState>,
|
||||
) -> impl IntoResponse {
|
||||
let user = state.db.find_user_by_username(&username).await?;
|
||||
|
||||
if wants_ap_json(&headers) {
|
||||
// actor_json takes a UUID as a string
|
||||
let json = state.service.actor_json(&user.id.to_string()).await?;
|
||||
return (
|
||||
[(axum::http::header::CONTENT_TYPE, "application/activity+json")],
|
||||
json,
|
||||
).into_response();
|
||||
}
|
||||
|
||||
// Return your UI JSON or HTML
|
||||
Json(MyUserResponse::from(user)).into_response()
|
||||
}
|
||||
|
||||
fn wants_ap_json(headers: &HeaderMap) -> bool {
|
||||
headers
|
||||
.get("accept")
|
||||
.and_then(|v| v.to_str().ok())
|
||||
.map(|v| v.contains("application/activity+json") || v.contains("application/ld+json"))
|
||||
.unwrap_or(false)
|
||||
}
|
||||
```
|
||||
|
||||
The same pattern for followers and following. `page` is `Option<u32>` — pass `None` for the collection root, `Some(n)` for a page:
|
||||
|
||||
```rust
|
||||
// In your followers handler:
|
||||
let json = state.service.followers_collection_json(user.id, page).await?;
|
||||
|
||||
// In your following handler:
|
||||
let json = state.service.following_collection_json(user.id, page).await?;
|
||||
```
|
||||
|
||||
Both return JSON strings with the correct `@context` and `OrderedCollection` structure.
|
||||
Reference in New Issue
Block a user