mirror of
https://github.com/shuaiplus/nodewarden.git
synced 2026-06-20 21:00:41 +00:00
feat(pagination): add pagination utility functions for handling page size and continuation tokens
- Introduced `PaginationRequest` interface to define pagination parameters. - Implemented `parsePagination` function to extract and validate pagination parameters from a URL. - Added `encodeContinuationToken` and `decodeContinuationToken` functions for managing continuation tokens. - Ensured that pagination respects maximum page size limits defined in configuration.
This commit is contained in:
+69
-14
@@ -1,10 +1,68 @@
|
||||
import { LIMITS } from '../config/limits';
|
||||
|
||||
const CORS_METHODS = 'GET, POST, PUT, DELETE, PATCH, OPTIONS';
|
||||
const CORS_HEADERS = 'Content-Type, Authorization, Accept, Device-Type, Bitwarden-Client-Name, Bitwarden-Client-Version';
|
||||
|
||||
function isTrustedClientOrigin(origin: string): boolean {
|
||||
// Official browser extension / desktop-webview common origins.
|
||||
if (origin === 'null') return true;
|
||||
if (origin.startsWith('chrome-extension://')) return true;
|
||||
if (origin.startsWith('moz-extension://')) return true;
|
||||
if (origin.startsWith('safari-web-extension://')) return true;
|
||||
if (origin.startsWith('app://')) return true;
|
||||
if (origin.startsWith('capacitor://')) return true;
|
||||
if (origin.startsWith('ionic://')) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
function getAllowedOrigin(request: Request): string | null {
|
||||
const origin = request.headers.get('Origin');
|
||||
if (!origin) return null;
|
||||
|
||||
const targetOrigin = new URL(request.url).origin;
|
||||
if (origin === targetOrigin) return origin;
|
||||
if (isTrustedClientOrigin(origin)) return origin;
|
||||
return null;
|
||||
}
|
||||
|
||||
function buildCorsHeaders(request: Request): Record<string, string> {
|
||||
const headers: Record<string, string> = {
|
||||
'Access-Control-Allow-Methods': CORS_METHODS,
|
||||
'Access-Control-Allow-Headers': CORS_HEADERS,
|
||||
'Access-Control-Max-Age': String(LIMITS.cors.preflightMaxAgeSeconds),
|
||||
};
|
||||
|
||||
const allowedOrigin = getAllowedOrigin(request);
|
||||
if (allowedOrigin) {
|
||||
headers['Access-Control-Allow-Origin'] = allowedOrigin;
|
||||
headers['Vary'] = 'Origin';
|
||||
}
|
||||
|
||||
return headers;
|
||||
}
|
||||
|
||||
export function applyCors(
|
||||
request: Request,
|
||||
response: Response
|
||||
): Response {
|
||||
const headers = new Headers(response.headers);
|
||||
const corsHeaders = buildCorsHeaders(request);
|
||||
for (const [k, v] of Object.entries(corsHeaders)) {
|
||||
headers.set(k, v);
|
||||
}
|
||||
return new Response(response.body, {
|
||||
status: response.status,
|
||||
statusText: response.statusText,
|
||||
headers,
|
||||
});
|
||||
}
|
||||
|
||||
// JSON response helper
|
||||
export function jsonResponse(data: any, status: number = 200, headers: Record<string, string> = {}): Response {
|
||||
return new Response(JSON.stringify(data), {
|
||||
status,
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
...getCorsHeaders(),
|
||||
...headers,
|
||||
},
|
||||
});
|
||||
@@ -40,21 +98,19 @@ export function identityErrorResponse(message: string, error: string = 'invalid_
|
||||
);
|
||||
}
|
||||
|
||||
// CORS headers
|
||||
export function getCorsHeaders(): Record<string, string> {
|
||||
return {
|
||||
'Access-Control-Allow-Origin': '*',
|
||||
'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
|
||||
'Access-Control-Allow-Headers': 'Content-Type, Authorization, Accept, Device-Type, Bitwarden-Client-Name, Bitwarden-Client-Version',
|
||||
'Access-Control-Max-Age': '86400',
|
||||
};
|
||||
}
|
||||
|
||||
// Handle CORS preflight
|
||||
export function handleCors(): Response {
|
||||
export function handleCors(request: Request): Response {
|
||||
const origin = request.headers.get('Origin');
|
||||
if (origin) {
|
||||
const allowedOrigin = getAllowedOrigin(request);
|
||||
if (!allowedOrigin) {
|
||||
return new Response(null, { status: 403 });
|
||||
}
|
||||
}
|
||||
|
||||
return new Response(null, {
|
||||
status: 204,
|
||||
headers: getCorsHeaders(),
|
||||
headers: buildCorsHeaders(request),
|
||||
});
|
||||
}
|
||||
|
||||
@@ -64,7 +120,6 @@ export function htmlResponse(html: string, status: number = 200): Response {
|
||||
status,
|
||||
headers: {
|
||||
'Content-Type': 'text/html; charset=utf-8',
|
||||
...getCorsHeaders(),
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user