Add snapshot management to API and enhance user-agent validation for v2 routes

This commit is contained in:
ImBenji
2026-01-02 18:09:29 +00:00
parent 469eea4e2f
commit 1d51b9a341
5 changed files with 273 additions and 13 deletions

View File

@@ -15,6 +15,7 @@ Generate Twitter-style quote images programmatically. Perfect for creating socia
- Base64 image support
- Docker-ready
- v2 API with stateful sessions for incremental updates
- Persistent snapshot links (48-hour TTL, immutable, shareable)
## API Endpoints
@@ -323,6 +324,47 @@ curl -X DELETE https://quotes.imbenji.net/v2/quote/a1b2c3d4-e5f6-7890-abcd-ef123
Returns `204 No Content` on success.
### POST /v2/quote/:id/snapshot-link
Create a persistent snapshot link. This captures the current state of your session and generates a shareable URL that persists for 48 hours (refreshing on each access).
Unlike the regular `/image` endpoint, snapshots are immutable - they always show the image as it was when the snapshot was created, even if you update the session afterwards.
**Request:**
```bash
curl -X POST https://quotes.imbenji.net/v2/quote/a1b2c3d4-e5f6-7890-abcd-ef1234567890/snapshot-link
```
**Response (201):**
```json
{
"token": "xY9pQmN3kL8vFw2jRtZ7",
"url": "https://quotes.imbenji.net/v2/snapshot/xY9pQmN3kL8vFw2jRtZ7",
"sessionId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"createdAt": 1735600000,
"expiresAt": 1735772800
}
```
### GET /v2/snapshot/:token
Retrieve a snapshot image using its token.
```bash
curl https://quotes.imbenji.net/v2/snapshot/xY9pQmN3kL8vFw2jRtZ7 --output snapshot.png
```
**Response headers:**
- `Content-Type: image/png`
- `X-Snapshot-Token: <token>`
- `X-Cache: HIT` or `MISS`
**Snapshot behavior:**
- **Immutable:** Shows the session state when the snapshot was created
- **TTL:** 48 hours from last access (resets on each view)
- **Cascade delete:** Deleted automatically when parent session is deleted
- **Shareable:** Token can be shared with anyone
### v2 Example Workflow
```javascript
@@ -360,6 +402,14 @@ await fetch(`https://quotes.imbenji.net/v2/quote/${sessionId}`, {
// 4. Generate the final image
const imgRes = await fetch(`https://quotes.imbenji.net/v2/quote/${sessionId}/image`);
const blob = await imgRes.blob();
// 5. (Optional) Create a shareable snapshot link
const snapshotRes = await fetch(`https://quotes.imbenji.net/v2/quote/${sessionId}/snapshot-link`, {
method: 'POST'
});
const snapshot = await snapshotRes.json();
console.log('Shareable URL:', snapshot.url);
// Anyone can access: https://quotes.imbenji.net/v2/snapshot/<token>
```
### v2 Parameters
@@ -468,8 +518,9 @@ Response:
- **Max tweet width:** 450px (auto-scaled to fit)
- **Cache TTL:** 24 hours from last access
- **Session TTL:** 24 hours from last update (v2 API)
- **Snapshot TTL:** 48 hours from last access (v2 API)
- **Cleanup interval:** Every hour
- **Database:** SQLite (for v2 sessions)
- **Database:** SQLite (for v2 sessions and snapshots)
## Limitations