refactor: migrate API routes to Hono sub-router
- Create Hono router in api.ts
- Convert 6 API endpoints to Hono format:
- GET /api/deposit/balance
- POST /api/deposit/deduct
- POST /api/test
- POST /api/chat
- POST /api/contact
- GET /api/metrics
- Use Hono CORS middleware for /contact
- Remove manual handleApiRequest and handleContactPreflight
- Integrate with main app via app.route('/api', apiRouter)
Benefits:
- Cleaner declarative routing (44 insertions, 48 deletions)
- Built-in CORS middleware
- Better code organization
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
import { Env, EmailMessage, ProvisionMessage, MessageBatch } from './types';
|
||||
import { sendMessage, setWebhook, getWebhookInfo } from './telegram';
|
||||
import { handleWebhook } from './routes/webhook';
|
||||
import { handleApiRequest } from './routes/api';
|
||||
import { apiRouter } from './routes/api';
|
||||
import { handleHealthCheck } from './routes/health';
|
||||
import { parseBankSMS } from './services/bank-sms-parser';
|
||||
import { matchPendingDeposit } from './services/deposit-matcher';
|
||||
@@ -69,8 +69,8 @@ app.get('/webhook-info', async (c) => {
|
||||
return c.json(result);
|
||||
});
|
||||
|
||||
// API routes
|
||||
app.all('/api/*', (c) => handleApiRequest(c.req.raw, c.env, new URL(c.req.url)));
|
||||
// API routes - use Hono router
|
||||
app.route('/api', apiRouter);
|
||||
|
||||
// Telegram Webhook
|
||||
app.post('/webhook', (c) => handleWebhook(c.req.raw, c.env));
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
import { z } from 'zod';
|
||||
import { Hono } from 'hono';
|
||||
import { cors } from 'hono/cors';
|
||||
import { Env } from '../types';
|
||||
import { sendMessage } from '../telegram';
|
||||
import {
|
||||
@@ -762,18 +764,6 @@ async function handleContactForm(request: Request, env: Env): Promise<Response>
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* OPTIONS /api/contact - CORS preflight for contact API
|
||||
*
|
||||
* @param env - Environment bindings
|
||||
* @returns Response with CORS headers
|
||||
*/
|
||||
async function handleContactPreflight(env: Env): Promise<Response> {
|
||||
return new Response(null, {
|
||||
headers: getCorsHeaders(env),
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* GET /api/metrics - Circuit Breaker 상태 조회 (관리자 전용)
|
||||
*
|
||||
@@ -837,7 +827,7 @@ async function handleMetrics(request: Request, env: Env): Promise<Response> {
|
||||
}
|
||||
|
||||
/**
|
||||
* API 엔드포인트 처리 (라우터)
|
||||
* API Router (Hono)
|
||||
*
|
||||
* Manual Test:
|
||||
* 1. wrangler dev
|
||||
@@ -867,41 +857,47 @@ async function handleMetrics(request: Request, env: Env): Promise<Response> {
|
||||
* curl http://localhost:8787/api/metrics \
|
||||
* -H "Authorization: Bearer your-webhook-secret"
|
||||
*/
|
||||
export async function handleApiRequest(request: Request, env: Env, url: URL): Promise<Response> {
|
||||
// Deposit API - 잔액 조회 (namecheap-api 전용)
|
||||
if (url.pathname === '/api/deposit/balance' && request.method === 'GET') {
|
||||
return handleDepositBalance(request, env, url);
|
||||
}
|
||||
const api = new Hono<{ Bindings: Env }>();
|
||||
|
||||
// Deposit API - 잔액 차감 (namecheap-api 전용)
|
||||
if (url.pathname === '/api/deposit/deduct' && request.method === 'POST') {
|
||||
return handleDepositDeduct(request, env);
|
||||
}
|
||||
// CORS middleware for /contact endpoint
|
||||
api.use('/contact', cors({
|
||||
origin: (origin, c) => {
|
||||
const allowedOrigin = c.env.HOSTING_SITE_URL || 'https://hosting.anvil.it.com';
|
||||
return origin === allowedOrigin ? origin : null;
|
||||
},
|
||||
allowMethods: ['POST', 'OPTIONS'],
|
||||
allowHeaders: ['Content-Type'],
|
||||
}));
|
||||
|
||||
// 테스트 API - 메시지 처리 후 응답 직접 반환
|
||||
if (url.pathname === '/api/test' && request.method === 'POST') {
|
||||
return handleTestApi(request, env);
|
||||
}
|
||||
// GET /deposit/balance - 잔액 조회 (namecheap-api 전용)
|
||||
api.get('/deposit/balance', async (c) => {
|
||||
const url = new URL(c.req.url);
|
||||
return await handleDepositBalance(c.req.raw, c.env, url);
|
||||
});
|
||||
|
||||
// Chat API - 인증된 채팅 API (프로덕션 활성화)
|
||||
if (url.pathname === '/api/chat' && request.method === 'POST') {
|
||||
return handleChatApi(request, env);
|
||||
}
|
||||
// POST /deposit/deduct - 잔액 차감 (namecheap-api 전용)
|
||||
api.post('/deposit/deduct', async (c) => {
|
||||
return await handleDepositDeduct(c.req.raw, c.env);
|
||||
});
|
||||
|
||||
// 문의 폼 API (웹사이트용)
|
||||
if (url.pathname === '/api/contact' && request.method === 'POST') {
|
||||
return handleContactForm(request, env);
|
||||
}
|
||||
// POST /test - 테스트 API (개발 환경 전용)
|
||||
api.post('/test', async (c) => {
|
||||
return await handleTestApi(c.req.raw, c.env);
|
||||
});
|
||||
|
||||
// CORS preflight for contact API
|
||||
if (url.pathname === '/api/contact' && request.method === 'OPTIONS') {
|
||||
return handleContactPreflight(env);
|
||||
}
|
||||
// POST /chat - 인증된 채팅 API (프로덕션)
|
||||
api.post('/chat', async (c) => {
|
||||
return await handleChatApi(c.req.raw, c.env);
|
||||
});
|
||||
|
||||
// Metrics API - Circuit Breaker 상태 조회 (관리자 전용)
|
||||
if (url.pathname === '/api/metrics' && request.method === 'GET') {
|
||||
return handleMetrics(request, env);
|
||||
}
|
||||
// POST /contact - 문의 폼 API (웹사이트용)
|
||||
api.post('/contact', async (c) => {
|
||||
return await handleContactForm(c.req.raw, c.env);
|
||||
});
|
||||
|
||||
return new Response('Not Found', { status: 404 });
|
||||
}
|
||||
// GET /metrics - Circuit Breaker 상태 조회 (관리자 전용)
|
||||
api.get('/metrics', async (c) => {
|
||||
return await handleMetrics(c.req.raw, c.env);
|
||||
});
|
||||
|
||||
export { api as apiRouter };
|
||||
|
||||
Reference in New Issue
Block a user