88 decodePathFragment ,
99} from "@webstudio-is/sdk" ;
1010import { fileUploadPath } from "~/shared/asset-client" ;
11+ import env from "~/env/env.server" ;
1112
1213// This route serves generic assets without processing
1314export const loader = async ( { request } : LoaderFunctionArgs ) => {
@@ -25,6 +26,38 @@ export const loader = async ({ request }: LoaderFunctionArgs) => {
2526 } ) ;
2627 }
2728
29+ // In production, proxy to the storage origin (R2/S3)
30+ if ( env . RESIZE_ORIGIN !== undefined ) {
31+ const assetUrl = new URL ( env . RESIZE_ORIGIN + url . pathname ) ;
32+
33+ const response = await fetch ( assetUrl . href , {
34+ headers : {
35+ accept : request . headers . get ( "accept" ) ?? "" ,
36+ "accept-encoding" : request . headers . get ( "accept-encoding" ) ?? "" ,
37+ } ,
38+ } ) ;
39+
40+ if ( ! response . ok ) {
41+ console . error (
42+ `Request to asset url ${ assetUrl . href } responded with status = ${ response . status } `
43+ ) ;
44+ throw new Response ( "Not found" , {
45+ status : response . status ,
46+ } ) ;
47+ }
48+
49+ // Override content-type from storage with correct MIME type based on filename
50+ const contentType = getMimeTypeByFilename ( name ) ;
51+ const responseHeaders = new Headers ( response . headers ) ;
52+ responseHeaders . set ( "content-type" , contentType ) ;
53+ responseHeaders . set ( "Access-Control-Allow-Origin" , url . origin ) ;
54+
55+ return new Response ( response . body , {
56+ status : response . status ,
57+ headers : responseHeaders ,
58+ } ) ;
59+ }
60+
2861 // Support absolute urls locally
2962 if ( URL . canParse ( name ) ) {
3063 return fetch ( name ) ;
0 commit comments