@@ -41,20 +41,24 @@ const LANG_NAMES: Record<string, string> = {
4141function corsHeaders ( origin : string ) : Record < string , string > {
4242 return {
4343 "Access-Control-Allow-Origin" : origin ,
44- "Access-Control-Allow-Methods" : "GET, OPTIONS" ,
44+ "Access-Control-Allow-Methods" : "GET, HEAD, OPTIONS" ,
4545 "Access-Control-Allow-Headers" : "Content-Type" ,
4646 } ;
4747}
4848
49- function json ( data : unknown , status : number , origin : string , cacheSeconds = 0 ) : Response {
49+ function jsonHeaders ( origin : string , cacheSeconds = 0 ) : HeadersInit {
5050 const headers : Record < string , string > = {
5151 "Content-Type" : "application/json" ,
5252 ...corsHeaders ( origin ) ,
5353 } ;
5454 if ( cacheSeconds > 0 ) {
5555 headers [ "Cache-Control" ] = `public, max-age=${ cacheSeconds } ` ;
5656 }
57- return new Response ( JSON . stringify ( data ) , { status, headers } ) ;
57+ return headers ;
58+ }
59+
60+ function json ( data : unknown , status : number , origin : string , cacheSeconds = 0 ) : Response {
61+ return new Response ( JSON . stringify ( data ) , { status, headers : jsonHeaders ( origin , cacheSeconds ) } ) ;
5862}
5963
6064export default {
@@ -67,18 +71,24 @@ export default {
6771 return new Response ( null , { status : 204 , headers : corsHeaders ( origin ) } ) ;
6872 }
6973
70- if ( request . method !== "GET" ) {
74+ const isHead = request . method === "HEAD" ;
75+
76+ if ( request . method !== "GET" && ! isHead ) {
7177 return json ( { error : "Method not allowed" } , 405 , origin ) ;
7278 }
7379
7480 switch ( url . pathname ) {
7581 case "/stats" :
82+ if ( isHead ) return new Response ( null , { status : 200 , headers : jsonHeaders ( origin , 300 ) } ) ;
7683 return handleStats ( env , origin ) ;
7784 case "/documents" :
85+ if ( isHead ) return new Response ( null , { status : 200 , headers : jsonHeaders ( origin ) } ) ;
7886 return handleDocuments ( url , env , origin ) ;
7987 case "/manifest" :
88+ if ( isHead ) return headManifest ( url , origin ) ;
8089 return handleManifest ( url , env , origin ) ;
8190 default :
91+ if ( isHead ) return new Response ( null , { status : 404 , headers : jsonHeaders ( origin ) } ) ;
8292 return json ( { error : "Not found" } , 404 , origin ) ;
8393 }
8494 } ,
@@ -296,6 +306,32 @@ async function handleDocuments(url: URL, env: Env, origin: string): Promise<Resp
296306
297307const R2_BASE = "https://docxcorp.us/documents/" ;
298308
309+ function manifestFilename ( url : URL ) : string {
310+ const parts = [ "docx-corpus" ] ;
311+ const type = url . searchParams . get ( "type" ) ;
312+ const topic = url . searchParams . get ( "topic" ) ;
313+ const lang = url . searchParams . get ( "lang" ) ;
314+ if ( type ) parts . push ( type ) ;
315+ if ( topic ) parts . push ( topic ) ;
316+ if ( lang ) parts . push ( lang ) ;
317+ return `${ parts . join ( "-" ) } -manifest.txt` ;
318+ }
319+
320+ function manifestHeaders ( url : URL , origin : string ) : HeadersInit {
321+ return {
322+ "Content-Type" : "text/plain; charset=utf-8" ,
323+ "Content-Disposition" : `attachment; filename="${ manifestFilename ( url ) } "` ,
324+ ...corsHeaders ( origin ) ,
325+ } ;
326+ }
327+
328+ function headManifest ( url : URL , origin : string ) : Response {
329+ return new Response ( null , {
330+ status : 200 ,
331+ headers : manifestHeaders ( url , origin ) ,
332+ } ) ;
333+ }
334+
299335async function handleManifest ( url : URL , env : Env , origin : string ) : Promise < Response > {
300336 try {
301337 const sql = neon ( env . DATABASE_URL ) ;
@@ -307,23 +343,9 @@ async function handleManifest(url: URL, env: Env, origin: string): Promise<Respo
307343
308344 const body = rows . map ( ( r ) => `${ R2_BASE } ${ r . id } .docx` ) . join ( "\n" ) + "\n" ;
309345
310- // Build a descriptive filename
311- const parts = [ "docx-corpus" ] ;
312- const type = url . searchParams . get ( "type" ) ;
313- const topic = url . searchParams . get ( "topic" ) ;
314- const lang = url . searchParams . get ( "lang" ) ;
315- if ( type ) parts . push ( type ) ;
316- if ( topic ) parts . push ( topic ) ;
317- if ( lang ) parts . push ( lang ) ;
318- const filename = `${ parts . join ( "-" ) } -manifest.txt` ;
319-
320346 return new Response ( body , {
321347 status : 200 ,
322- headers : {
323- "Content-Type" : "text/plain; charset=utf-8" ,
324- "Content-Disposition" : `attachment; filename="${ filename } "` ,
325- ...corsHeaders ( origin ) ,
326- } ,
348+ headers : manifestHeaders ( url , origin ) ,
327349 } ) ;
328350 } catch ( err ) {
329351 const message = err instanceof Error ? err . message : String ( err ) ;
0 commit comments