@@ -42,80 +42,97 @@ export function proxyRoute(options: ProxyRouteOptions): HTTPMiddleware {
4242
4343 if ( [ 301 , 302 , 307 , 308 ] . includes ( response . status ) ) {
4444 let location = response . headers . get ( "location" ) ;
45- if ( location ?. startsWith ( String ( website ) ) ) {
46- let headers = copyHeaders ( response ) ;
47-
48- let url = new URL ( request . url ) ;
45+ if ( location ) {
46+ // Resolve relative Location headers against the upstream website
47+ // - Netlify returns relative redirects like "/search/""
48+ // - Deno Deploy returns absolute ones like "https://host/search/"
49+ let loc = location . startsWith ( "http" )
50+ ? new URL ( location )
51+ : new URL ( location , website ) ;
52+
53+ if ( loc . origin === website . origin ) {
54+ let headers = copyHeaders ( response ) ;
55+ let url = new URL ( request . url ) ;
56+
57+ if ( ! options . root ) {
58+ loc . pathname = `${ options . prefix } ${ loc . pathname } ` ;
59+ }
60+ headers . location = loc . toString ( ) . replace ( target . origin , url . origin ) ;
4961
50- let loc = new URL ( location ) ;
51- if ( ! options . root ) {
52- loc . pathname = `${ options . prefix } ${ loc . pathname } ` ;
62+ response = new Response ( null , {
63+ status : response . status ,
64+ statusText : response . statusText ,
65+ headers,
66+ } ) ;
5367 }
54- headers . location = loc . toString ( ) . replace ( target . origin , url . origin ) ;
55-
56- response = new Response ( null , {
57- status : response . status ,
58- statusText : response . statusText ,
59- headers,
60- } ) ;
6168 }
6269 } else if (
6370 response . headers . get ( "Content-Type" ) ?. match ( / h t m l / ) && ! options . root
6471 ) {
65- let body = yield * call ( ( ) => response . text ( ) ) ;
66- let tree = fromHtml ( body ) ;
72+ try {
73+ let body = yield * call ( ( ) => response . text ( ) ) ;
74+ let tree = fromHtml ( body ) ;
6775
68- yield * injectPlausible ( tree ) ;
69- yield * injectUmami ( tree ) ;
70- yield * injectMatomo ( tree ) ;
76+ yield * injectPlausible ( tree ) ;
77+ yield * injectUmami ( tree ) ;
78+ yield * injectMatomo ( tree ) ;
7179
72- let elements = selectAll (
73- '[href^="/"],[src^="/"],form[action],meta[content]' ,
74- tree ,
75- ) ;
80+ let elements = selectAll (
81+ '[href^="/"],[src^="/"],form[action],meta[content]' ,
82+ tree ,
83+ ) ;
7684
77- for ( let element of elements ) {
78- let properties = element . properties ! ;
85+ for ( let element of elements ) {
86+ let properties = element . properties ! ;
7987
80- if ( properties . href ) {
81- properties . href = posixNormalize (
82- `${ base . pathname } ${ properties . href } ` ,
83- ) ;
84- }
85- if ( properties . src ) {
86- properties . src = posixNormalize ( `${ base . pathname } ${ properties . src } ` ) ;
87- }
88- if ( properties . action ) {
89- properties . action = posixNormalize (
90- `${ base . pathname } ${ properties . action } ` ,
91- ) ;
92- }
93- if ( properties . content ) {
94- if ( typeof properties . content === "string" ) {
95- const parts = properties . content . match ( / \d ; \s * u r l = ( .* ) / ) ;
96- if ( parts ) {
97- const [ , url ] = parts ;
98- properties . content = properties . content . replace (
99- url ,
100- posixNormalize ( `${ base . pathname } ${ url } ` ) ,
101- ) ;
102- } else if ( properties . content . startsWith ( "http" ) ) {
103- properties . content = properties . content . replace (
104- target . origin ,
105- base . href . replace ( / \/ ? $ / , "" ) ,
106- ) ;
88+ if ( properties . href ) {
89+ properties . href = posixNormalize (
90+ `${ base . pathname } ${ properties . href } ` ,
91+ ) ;
92+ }
93+ if ( properties . src ) {
94+ properties . src = posixNormalize (
95+ `${ base . pathname } ${ properties . src } ` ,
96+ ) ;
97+ }
98+ if ( properties . action ) {
99+ properties . action = posixNormalize (
100+ `${ base . pathname } ${ properties . action } ` ,
101+ ) ;
102+ }
103+ if ( properties . content ) {
104+ if ( typeof properties . content === "string" ) {
105+ const parts = properties . content . match ( / \d ; \s * u r l = ( .* ) / ) ;
106+ if ( parts ) {
107+ const [ , url ] = parts ;
108+ properties . content = properties . content . replace (
109+ url ,
110+ posixNormalize ( `${ base . pathname } ${ url } ` ) ,
111+ ) ;
112+ } else if ( properties . content . startsWith ( "http" ) ) {
113+ properties . content = properties . content . replace (
114+ target . origin ,
115+ base . href . replace ( / \/ ? $ / , "" ) ,
116+ ) ;
117+ }
107118 }
108119 }
109120 }
121+ response = new Response ( toHtml ( tree ) , {
122+ status : response . status ,
123+ statusText : response . statusText ,
124+ headers : copyHeaders ( response ) ,
125+ } ) ;
126+ } catch ( error ) {
127+ console . error ( `Proxy HTML rewrite failed for ${ request . url } :` , error ) ;
110128 }
111- response = new Response ( toHtml ( tree ) , {
112- status : response . status ,
113- statusText : response . statusText ,
114- headers : copyHeaders ( response ) ,
115- } ) ;
116129 }
117130
118- return response ;
131+ return new Response ( response . body , {
132+ status : response . status ,
133+ statusText : response . statusText ,
134+ headers : copyHeaders ( response ) ,
135+ } ) ;
119136 } ;
120137
121138 if ( options . prefix ) {
@@ -135,17 +152,15 @@ export function proxyRoute(options: ProxyRouteOptions): HTTPMiddleware {
135152 } ;
136153 }
137154
138- if ( options . pattern ) {
139- let handler = revolutionRoute ( options . pattern , middleware ) ;
140- if ( middleware . sitemapExtension ) {
141- Object . defineProperty ( handler , "sitemapExtension" , {
142- value : middleware . sitemapExtension ,
143- } ) ;
144- }
145- return handler ;
146- }
155+ let pattern = options . pattern ?? `/${ options . prefix } (.*)` ;
147156
148- return middleware ;
157+ let handler = revolutionRoute ( pattern , middleware ) ;
158+ if ( middleware . sitemapExtension ) {
159+ Object . defineProperty ( handler , "sitemapExtension" , {
160+ value : middleware . sitemapExtension ,
161+ } ) ;
162+ }
163+ return handler ;
149164}
150165
151166// Copy an upstream response's headers, dropping the ones that describe how the
0 commit comments