Skip to content

Commit bd51fd8

Browse files
authored
Update index.ts
1 parent 16a0e75 commit bd51fd8

1 file changed

Lines changed: 59 additions & 10 deletions

File tree

src/index.ts

Lines changed: 59 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,7 @@
77
import { OpenAPIHono } from '@hono/zod-openapi'
88
import type { MiddlewareHandler } from 'hono'
99
import { swaggerUI } from '@hono/swagger-ui'
10-
// 'app' is the Hono app that handles all our API routes
11-
import { app, Bindings } from './utils/hono'
10+
import { app, Bindings } from './utils/hono' // Main 'app' for RUNTIME
1211
import { GitHubWorkerRPC } from './rpc'
1312
import { convertOpenAPIToYAML, buildCompleteOpenAPIDocument } from './utils/openapi'
1413
import { MCP_TOOLS, getToolStats, getTool, MCPExecuteRequest, TOOL_ROUTES, serializeTools } from './mcp/tools'
@@ -94,7 +93,6 @@ app.use('*', async (c, next) => {
9493
}
9594
})
9695

97-
// API Key Auth Middleware
9896
const requireApiKey: MiddlewareHandler<{ Bindings: Bindings }> = async (c, next) => {
9997
if (c.req.method === 'OPTIONS') {
10098
await next()
@@ -120,7 +118,6 @@ const requireApiKey: MiddlewareHandler<{ Bindings: Bindings }> = async (c, next)
120118
await next()
121119
}
122120

123-
// Apply auth middleware to all API routes
124121
app.use('/api/*', requireApiKey)
125122
app.use('/mcp/*', requireApiKey)
126123
app.use('/a2a/*', requireApiKey)
@@ -137,15 +134,17 @@ app.post('/webhook', webhookHandler)
137134

138135
// --- 3. API Spec Generation Apps ---
139136

140-
// App 1: Full Spec (for /openapi.json)
137+
// --- App 1: Full Spec (for /openapi.json) ---
138+
// This app contains *all* API routes for a complete spec.
141139
const fullSpecApp = new OpenAPIHono<{ Bindings: Bindings }>()
142140
fullSpecApp.route('/octokit', octokitApi)
143141
fullSpecApp.route('/tools', toolsApi)
144142
fullSpecApp.route('/agents', agentsApi)
145143
fullSpecApp.route('/retrofit', retrofitApi)
146144
fullSpecApp.route('/flows', flowsApi)
147145

148-
// App 2: GPT-Specific Spec (for /gpt/openapi.json)
146+
// --- App 2: GPT-Specific Spec (for /gpt/openapi.json) ---
147+
// This app contains *only* the 7 methods you requested.
149148
const gptSpecApp = new OpenAPIHono<{ Bindings: Bindings }>()
150149
gptSpecApp.route('/octokit', octokitApi) // 3 methods
151150
gptSpecApp.route('/agents', agentsApi) // 2 methods
@@ -167,7 +166,9 @@ const getEnhancedApiSpec = async (
167166
const openApiJson = await honoApp.getOpenAPIDocument({
168167
openapi: '3.0.0', // Base doc is 3.0.0, will be enhanced
169168
info: { version: '1.0.0', title, description },
170-
servers: [{ url: '/api' }], // Placeholder, will be overwritten
169+
// This 'servers' block is a placeholder.
170+
// buildCompleteOpenAPIDocument will overwrite it with the correct, single, absolute URL.
171+
servers: [{ url: '/api' }],
171172
})
172173

173174
// This function adds 3.1.0, single security scheme, and a single absolute server URL
@@ -271,9 +272,23 @@ app.post('/mcp-execute', async (c) => {
271272
const startTime = Date.now()
272273

273274
try {
274-
// ... (rest of mcp-execute handler is unchanged) ...
275+
// Validate request size (DoS prevention)
276+
const contentLength = c.req.header('content-length')
277+
const MAX_REQUEST_SIZE = 1024 * 1024 // 1MB
278+
if (contentLength && parseInt(contentLength) > MAX_REQUEST_SIZE) {
279+
return c.json({
280+
success: false,
281+
error: 'Request too large',
282+
maxSize: MAX_REQUEST_SIZE,
283+
}, 413)
284+
}
285+
275286
const body = await c.req.json()
287+
288+
// Validate JSON structure
276289
const parsed = MCPExecuteRequest.parse(body)
290+
291+
// Get the tool
277292
const tool = getTool(parsed.tool)
278293
if (!tool) {
279294
return c.json({
@@ -282,6 +297,8 @@ app.post('/mcp-execute', async (c) => {
282297
availableTools: MCP_TOOLS.map(t => t.name),
283298
}, 404)
284299
}
300+
301+
// Validate params against the tool's Zod schema
285302
const paramsValidation = tool.inputSchema.safeParse(parsed.params)
286303
if (!paramsValidation.success) {
287304
return c.json({
@@ -291,7 +308,11 @@ app.post('/mcp-execute', async (c) => {
291308
details: paramsValidation.error.errors,
292309
}, 400)
293310
}
311+
312+
// Use validated params
294313
const validatedParams = paramsValidation.data
314+
315+
// Get the route configuration for this tool
295316
const route = TOOL_ROUTES[parsed.tool];
296317
if (!route) {
297318
return c.json({
@@ -300,27 +321,39 @@ app.post('/mcp-execute', async (c) => {
300321
availableTools: MCP_TOOLS.map(t => t.name),
301322
}, 501);
302323
}
324+
325+
// Create an internal request to the appropriate endpoint
303326
const baseUrl = new URL(c.req.url).origin;
304327
const apiKey = c.req.header('x-api-key') || c.req.header('authorization')?.replace('Bearer ', '');
328+
329+
// Build the path (use custom path builder if available)
305330
const path = route.pathBuilder ? route.pathBuilder(validatedParams) : route.path;
306331
const url = `${baseUrl}${path}`;
332+
333+
// Build request headers
307334
const headers: Record<string, string> = {
308335
'x-api-key': apiKey || '',
309336
};
310337
if (route.method === 'POST') {
311338
headers['Content-Type'] = 'application/json';
312339
}
340+
341+
// Create and execute the request
313342
const internalReq = new Request(url, {
314343
method: route.method,
315344
headers,
316345
body: route.method === 'POST' ? JSON.stringify(validatedParams) : undefined,
317346
});
347+
348+
// We must use the main 'app' to fetch, as it has the runtime routes
318349
const response = await app.fetch(internalReq, c.env, c.executionCtx);
319350
if (!response.ok) {
320-
return response;
351+
return response; // Forward the error response
321352
}
322353
const result = await response.json();
354+
323355
const durationMs = Date.now() - startTime
356+
324357
return c.json({
325358
success: true,
326359
tool: parsed.tool,
@@ -518,9 +551,25 @@ export default {
518551
async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> {
519552

520553
// This is the correct "SPA Mode" pattern
554+
const url = new URL(request.url);
555+
if (url.pathname === '/') {
556+
// This is a request for the root.
557+
// Manually create a new request for /index.html
558+
const indexRequest = new Request(
559+
new URL('/index.html', request.url),
560+
request
561+
);
562+
try {
563+
return await env.ASSETS.fetch(indexRequest);
564+
} catch (e) {
565+
// Fallback if index.html doesn't exist, just in case
566+
return app.fetch(request, env, ctx);
567+
}
568+
}
569+
521570
try {
522571
// 1. First, try to fetch the request as a static asset.
523-
// This will serve public/index.html at /
572+
// This will serve public/landing.html at /landing.html
524573
return await env.ASSETS.fetch(request);
525574
} catch (e) {
526575
// 2. If it's not a static asset (e.g., 404), fall back to the Hono API app.

0 commit comments

Comments
 (0)