@@ -26,55 +26,111 @@ const PART_DESCRIPTIONS: Record<number, string> = {
2626 4 : "Transitional Migration Features" ,
2727} ;
2828
29+ // CORS allowed origins
30+ const ALLOWED_ORIGINS = [ "https://ooxml.dev" , "https://www.ooxml.dev" ] ;
31+ const DEV_ORIGINS = [ "http://localhost:5173" , "http://127.0.0.1:5173" ] ;
32+
33+ function getCorsHeaders ( request : Request , env : Env ) : Record < string , string > {
34+ const origin = request . headers . get ( "Origin" ) ;
35+ if ( ! origin ) return { } ;
36+
37+ // Check if origin is allowed
38+ const isProduction = ! env . DATABASE_URL . includes ( "localhost" ) ;
39+ const allowedOrigins = isProduction ? ALLOWED_ORIGINS : [ ...ALLOWED_ORIGINS , ...DEV_ORIGINS ] ;
40+
41+ if ( allowedOrigins . includes ( origin ) ) {
42+ return {
43+ "Access-Control-Allow-Origin" : origin ,
44+ "Access-Control-Allow-Methods" : "GET, POST, OPTIONS" ,
45+ "Access-Control-Allow-Headers" : "Content-Type" ,
46+ } ;
47+ }
48+
49+ return { } ;
50+ }
51+
52+ function addCorsHeaders ( response : Response , corsHeaders : Record < string , string > ) : Response {
53+ if ( Object . keys ( corsHeaders ) . length === 0 ) return response ;
54+
55+ const newHeaders = new Headers ( response . headers ) ;
56+ for ( const [ key , value ] of Object . entries ( corsHeaders ) ) {
57+ newHeaders . set ( key , value ) ;
58+ }
59+ return new Response ( response . body , {
60+ status : response . status ,
61+ statusText : response . statusText ,
62+ headers : newHeaders ,
63+ } ) ;
64+ }
65+
2966export default {
3067 async fetch ( request : Request , env : Env , _ctx : ExecutionContext ) : Promise < Response > {
3168 const url = new URL ( request . url ) ;
69+ const corsHeaders = getCorsHeaders ( request , env ) ;
70+
71+ // Handle CORS preflight
72+ if ( request . method === "OPTIONS" ) {
73+ return new Response ( null , {
74+ status : 204 ,
75+ headers : corsHeaders ,
76+ } ) ;
77+ }
3278
3379 // Health check
3480 if ( url . pathname === "/health" ) {
35- return new Response ( JSON . stringify ( { status : "ok" } ) , {
36- headers : { "Content-Type" : "application/json" } ,
37- } ) ;
81+ return addCorsHeaders (
82+ new Response ( JSON . stringify ( { status : "ok" } ) , {
83+ headers : { "Content-Type" : "application/json" } ,
84+ } ) ,
85+ corsHeaders ,
86+ ) ;
3887 }
3988
4089 // MCP endpoint
4190 if ( url . pathname === "/mcp" || url . pathname === "/sse" ) {
4291 if ( request . method === "POST" ) {
4392 // MCP protocol (JSON-RPC)
44- return handleMcpRequest ( request , env ) ;
93+ const response = await handleMcpRequest ( request , env ) ;
94+ return addCorsHeaders ( response , corsHeaders ) ;
4595 }
4696 // GET returns server info for debugging
47- return handleMcpInfo ( ) ;
97+ return addCorsHeaders ( handleMcpInfo ( ) , corsHeaders ) ;
4898 }
4999
50100 // REST API endpoints
51101 if ( url . pathname === "/search" && request . method === "POST" ) {
52- return handleSearch ( request , env ) ;
102+ const response = await handleSearch ( request , env ) ;
103+ return addCorsHeaders ( response , corsHeaders ) ;
53104 }
54105
55106 if ( url . pathname === "/section" && request . method === "GET" ) {
56- return handleGetSection ( request , env ) ;
107+ const response = await handleGetSection ( request , env ) ;
108+ return addCorsHeaders ( response , corsHeaders ) ;
57109 }
58110
59111 if ( url . pathname === "/stats" ) {
60- return handleStats ( env ) ;
112+ const response = await handleStats ( env ) ;
113+ return addCorsHeaders ( response , corsHeaders ) ;
61114 }
62115
63- return new Response (
64- JSON . stringify ( {
65- name : "ECMA-376 Spec MCP Server" ,
66- version : "0.1.0" ,
67- endpoints : {
68- mcp : "/mcp" ,
69- health : "/health" ,
70- search : "POST /search" ,
71- section : "GET /section?id=17.3.2&part=1" ,
72- stats : "/stats" ,
116+ return addCorsHeaders (
117+ new Response (
118+ JSON . stringify ( {
119+ name : "ECMA-376 Spec MCP Server" ,
120+ version : "0.1.0" ,
121+ endpoints : {
122+ mcp : "/mcp" ,
123+ health : "/health" ,
124+ search : "POST /search" ,
125+ section : "GET /section?id=17.3.2&part=1" ,
126+ stats : "/stats" ,
127+ } ,
128+ } ) ,
129+ {
130+ headers : { "Content-Type" : "application/json" } ,
73131 } ,
74- } ) ,
75- {
76- headers : { "Content-Type" : "application/json" } ,
77- } ,
132+ ) ,
133+ corsHeaders ,
78134 ) ;
79135 } ,
80136} ;
0 commit comments