refactor: Unify polling endpoint and remove AUTH_SECRET

BREAKING CHANGES:
- Renamed /offers/poll to /poll (generic polling endpoint)
- Removed /offers/answered endpoint (use /poll instead)
- Removed AUTH_SECRET environment variable (Ed25519 auth only)
- Updated auth message format from 'pollOffers' to 'poll'
This commit is contained in:
2025-12-12 19:13:11 +01:00
parent 01b751afc3
commit 1612bd78b7
3 changed files with 6 additions and 69 deletions

View File

@@ -309,37 +309,13 @@ Get answer SDP (offerer polls this)
Returns 404 if not yet answered. Returns 404 if not yet answered.
#### `GET /offers/answered` #### `GET /poll`
Get all answered offers (efficient batch polling for offerer) Combined polling endpoint for answers and ICE candidates
**Query Parameters:** **Query Parameters:**
- `username` - Your username - `username` - Your username
- `signature` - Base64-encoded Ed25519 signature - `signature` - Base64-encoded Ed25519 signature
- `message` - Signed message (format: `getAnsweredOffers:{username}:{timestamp}`) - `message` - Signed message (format: `poll:{username}:{timestamp}`)
- `since` - Optional timestamp to get only new answers
**Response:**
```json
{
"offers": [
{
"offerId": "offer-hash",
"serviceId": "service-uuid",
"answererUsername": "bob",
"sdp": "v=0...",
"answeredAt": 1733404800000
}
]
}
```
#### `GET /offers/poll`
Combined polling for answers and ICE candidates (offerer)
**Query Parameters:**
- `username` - Your username
- `signature` - Base64-encoded Ed25519 signature
- `message` - Signed message (format: `pollOffers:{username}:{timestamp}`)
- `since` - Optional timestamp to get only new data - `since` - Optional timestamp to get only new data
**Response:** **Response:**
@@ -367,8 +343,6 @@ Combined polling for answers and ICE candidates (offerer)
} }
``` ```
More efficient than polling answers and ICE separately - reduces HTTP requests by 50%.
#### `POST /services/:fqn/offers/:offerId/ice-candidates` #### `POST /services/:fqn/offers/:offerId/ice-candidates`
Add ICE candidates to specific offer Add ICE candidates to specific offer
@@ -517,7 +491,7 @@ See [MIGRATION.md](../MIGRATION.md) for detailed migration guide.
- Removed UUID privacy layer - direct FQN-based access - Removed UUID privacy layer - direct FQN-based access
- Removed public/private service distinction - Removed public/private service distinction
- Added service discovery (random and paginated) - Added service discovery (random and paginated)
- Added combined polling endpoint (/offers/poll) - Unified polling endpoint (/poll replaces /offers/answered and /offers/poll)
- ICE candidate endpoints moved to offer-specific routes - ICE candidate endpoints moved to offer-specific routes
## License ## License

View File

@@ -507,43 +507,11 @@ export function createApp(storage: Storage, config: Config) {
}); });
/** /**
* GET /offers/answered * GET /poll
* Get all answered offers for the authenticated peer (efficient batch polling)
*/
app.get('/offers/answered', authMiddleware, async (c) => {
try {
const username = getAuthenticatedUsername(c);
const since = c.req.query('since');
const sinceTimestamp = since ? parseInt(since, 10) : 0;
const offers = await storage.getAnsweredOffers(username);
// Filter by timestamp if provided
const filteredOffers = since
? offers.filter(offer => offer.answeredAt && offer.answeredAt > sinceTimestamp)
: offers;
return c.json({
offers: filteredOffers.map(offer => ({
offerId: offer.id,
serviceId: offer.serviceId,
answererId: offer.answererUsername,
sdp: offer.answerSdp,
answeredAt: offer.answeredAt
}))
}, 200);
} catch (err) {
console.error('Error getting answered offers:', err);
return c.json({ error: 'Internal server error' }, 500);
}
});
/**
* GET /offers/poll
* Combined efficient polling endpoint for answers and ICE candidates * Combined efficient polling endpoint for answers and ICE candidates
* Returns all answered offers and ICE candidates for all peer's offers since timestamp * Returns all answered offers and ICE candidates for all peer's offers since timestamp
*/ */
app.get('/offers/poll', authMiddleware, async (c) => { app.get('/poll', authMiddleware, async (c) => {
try { try {
const username = getAuthenticatedUsername(c); const username = getAuthenticatedUsername(c);
const since = c.req.query('since'); const since = c.req.query('since');

View File

@@ -1,6 +1,5 @@
import { createApp } from './app.ts'; import { createApp } from './app.ts';
import { D1Storage } from './storage/d1.ts'; import { D1Storage } from './storage/d1.ts';
import { generateSecretKey } from './crypto.ts';
import { Config } from './config.ts'; import { Config } from './config.ts';
/** /**
@@ -8,7 +7,6 @@ import { Config } from './config.ts';
*/ */
export interface Env { export interface Env {
DB: D1Database; DB: D1Database;
AUTH_SECRET?: string;
OFFER_DEFAULT_TTL?: string; OFFER_DEFAULT_TTL?: string;
OFFER_MAX_TTL?: string; OFFER_MAX_TTL?: string;
OFFER_MIN_TTL?: string; OFFER_MIN_TTL?: string;
@@ -25,9 +23,6 @@ export default {
// Initialize D1 storage // Initialize D1 storage
const storage = new D1Storage(env.DB); const storage = new D1Storage(env.DB);
// Generate or use provided auth secret
const authSecret = env.AUTH_SECRET || generateSecretKey();
// Build config from environment // Build config from environment
const config: Config = { const config: Config = {
port: 0, // Not used in Workers port: 0, // Not used in Workers