- 가격표 섹션을 페이지 하단에서 히어로 바로 아래로 이동 - 상단 패딩 축소 (py-24 → pt-12 pb-24) - 서브탭(서울/글로벌 타입) 스타일을 메인탭과 동일하게 통일 - Pages Functions API 프록시 추가 (functions/) - wrangler.toml 및 TypeScript 설정 추가 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
103 lines
2.2 KiB
TypeScript
103 lines
2.2 KiB
TypeScript
/**
|
|
* Shared proxy utilities for Cloudflare Pages Functions
|
|
* Handles CORS, error responses, and Worker API forwarding
|
|
*/
|
|
|
|
export interface Env {
|
|
WORKER_API_KEY: string;
|
|
WORKER_API_URL: string;
|
|
DB: D1Database;
|
|
}
|
|
|
|
export interface ErrorResponse {
|
|
success: false;
|
|
error: string;
|
|
details?: any;
|
|
}
|
|
|
|
const CORS_HEADERS = {
|
|
'Access-Control-Allow-Origin': 'https://hosting.anvil.it.com',
|
|
'Access-Control-Allow-Methods': 'GET, POST, OPTIONS',
|
|
'Access-Control-Allow-Headers': 'Content-Type',
|
|
} as const;
|
|
|
|
/**
|
|
* Create CORS preflight response
|
|
*/
|
|
export function createCorsPreflightResponse(): Response {
|
|
return new Response(null, {
|
|
status: 204,
|
|
headers: CORS_HEADERS,
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Create error response with CORS headers
|
|
*/
|
|
export function createErrorResponse(
|
|
error: string,
|
|
status: number = 500,
|
|
details?: any
|
|
): Response {
|
|
const body: ErrorResponse = {
|
|
success: false,
|
|
error,
|
|
...(details && { details }),
|
|
};
|
|
|
|
return new Response(JSON.stringify(body), {
|
|
status,
|
|
headers: {
|
|
...CORS_HEADERS,
|
|
'Content-Type': 'application/json',
|
|
},
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Proxy request to Worker API with authentication
|
|
*/
|
|
export async function proxyToWorker(
|
|
env: Env,
|
|
path: string,
|
|
options: RequestInit = {}
|
|
): Promise<Response> {
|
|
const workerUrl = `${env.WORKER_API_URL}${path}`;
|
|
|
|
try {
|
|
const response = await fetch(workerUrl, {
|
|
...options,
|
|
headers: {
|
|
...options.headers,
|
|
'X-API-Key': env.WORKER_API_KEY,
|
|
},
|
|
});
|
|
|
|
// Clone response to add CORS headers
|
|
const body = await response.text();
|
|
return new Response(body, {
|
|
status: response.status,
|
|
statusText: response.statusText,
|
|
headers: {
|
|
...CORS_HEADERS,
|
|
'Content-Type': response.headers.get('Content-Type') || 'application/json',
|
|
},
|
|
});
|
|
} catch (error) {
|
|
console.error(`[Proxy] Failed to fetch ${workerUrl}:`, error);
|
|
return createErrorResponse(
|
|
'Failed to connect to API server',
|
|
503,
|
|
error instanceof Error ? error.message : String(error)
|
|
);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Build query string from URL search params
|
|
*/
|
|
export function buildQueryString(searchParams: URLSearchParams): string {
|
|
const params = searchParams.toString();
|
|
return params ? `?${params}` : '';
|
|
}
|