Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/allow-header-405.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@chatcops/server": patch
---

405 responses now include `Allow: POST, OPTIONS`.
1 change: 1 addition & 0 deletions packages/server/src/adapters/express.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ export function chatcopsMiddleware(config: ChatCopsServerConfig) {
}

if (req.method !== 'POST') {
res.setHeader('Allow', 'POST, OPTIONS');
sendError(405, 'Method not allowed');
return;
}
Expand Down
2 changes: 1 addition & 1 deletion packages/server/src/http.ts
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,7 @@ export async function fetchChatResponse(
if (request.method === 'OPTIONS') {
return new Response(null, { status: 204, headers: origins.preflightHeaders(origin) });
}
if (request.method !== 'POST') return json(405, { error: 'Method not allowed' });
if (request.method !== 'POST') return json(405, { error: 'Method not allowed' }, { Allow: 'POST, OPTIONS' });
if (!origins.allows(origin)) return json(403, { error: 'origin_not_allowed' });

if (isSessionPath(new URL(request.url).pathname)) {
Expand Down
1 change: 1 addition & 0 deletions packages/server/tests/adapters/cloudflare.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ describe('chatcopsCloudflareHandler', () => {
const res = await handler(req);
expect(res.status).toBe(405);
expect(res.headers.get('Access-Control-Allow-Origin')).toBe('*');
expect(res.headers.get('Allow')).toBe('POST, OPTIONS');
const body = await res.json();
expect(body.error).toBe('Method not allowed');
});
Expand Down
1 change: 1 addition & 0 deletions packages/server/tests/adapters/express.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,7 @@ describe('express analytics sharing', () => {

expect(fake.statusCode).toBe(405);
expect(fake.headers['Access-Control-Allow-Origin']).toBe('*');
expect(fake.headers.Allow).toBe('POST, OPTIONS');
expect(fake.body).toEqual({ error: 'Method not allowed' });
expect(fake.chunks).toEqual([]);
expect(fake.ended).toBe(false);
Expand Down
1 change: 1 addition & 0 deletions packages/server/tests/adapters/vercel.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ describe('chatcopsVercelHandler', () => {
const res = await handler(req);
expect(res.status).toBe(405);
expect(res.headers.get('Access-Control-Allow-Origin')).toBe('*');
expect(res.headers.get('Allow')).toBe('POST, OPTIONS');
const body = await res.json();
expect(body.error).toBe('Method not allowed');
});
Expand Down
2 changes: 1 addition & 1 deletion website/src/content/docs/server/protocol.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -345,7 +345,7 @@ Access-Control-Expose-Headers: Retry-After, X-ChatCops-Protocol
| `401` | `conversation_mismatch` | The session token is valid but was issued for a different conversation. | Obtain a token for the current conversation from `<chat url>/session`. |
| `401` | `turnstile_failed` | `/session` endpoint only: Cloudflare Turnstile verification failed or was missing. | Returned when bot protection challenge fails. |
| `403` | `origin_not_allowed` | The `Origin` header is not permitted by `allowedOrigins`. | Answered before the request body is parsed. Returns legacy format `{"error":"origin_not_allowed"}`. |
| `405` | `Method not allowed` | An HTTP method other than `POST` or `OPTIONS` was used on the chat endpoint. | Answered before the request body is parsed. Returns legacy format `{"error":"Method not allowed"}`. |
| `405` | `Method not allowed` | An HTTP method other than `POST` or `OPTIONS` was used on the chat endpoint. | Answered before the request body is parsed, with `Allow: POST, OPTIONS`. Returns legacy format `{"error":"Method not allowed"}`. |
| `409` | `conversation_busy` | Another reply is currently being generated for this `conversationId`. | The server locks conversation turns to prevent state races. |
| `413` | `payload_too_large` | The request body exceeds the maximum permitted size (default 256 KB). | Prevents excessive memory allocation. |
| `429` | `rate_limited` | The client IP has exceeded the configured request rate limit. | Includes `retryAfterMs` in body and `Retry-After` in HTTP headers. |
Expand Down
Loading