@@ -77,23 +77,74 @@ export default {
7777
7878 const maybeSecondRequest = request . clone ( ) ;
7979
80- let shouldBlockNonImageResponse = false ;
81- if ( url . pathname === "/_next/image" ) {
82- // is a next image
83- const queryURLParam = url . searchParams . get ( "url" ) ;
84- if ( queryURLParam && ! queryURLParam . startsWith ( "/" ) ) {
85- // that's a remote resource
86- if (
87- maybeSecondRequest . method !== "GET" ||
88- maybeSecondRequest . headers . get ( "sec-fetch-dest" ) !== "image"
89- ) {
90- // that was not loaded via a browser's <img> tag
91- shouldBlockNonImageResponse = true ;
92- analytics . setData ( { abuseMitigationURLHost : queryURLParam } ) ;
93- }
94- // otherwise, we're good
80+ const routeToUserWorker = async ( {
81+ asset,
82+ } : {
83+ asset : "static_routing" | "none" ;
84+ } ) => {
85+ if ( ! config . has_user_worker ) {
86+ throw new Error (
87+ "Fetch for user worker without having a user worker binding"
88+ ) ;
9589 }
96- }
90+ analytics . setData ( { dispatchtype : DISPATCH_TYPE . WORKER } ) ;
91+ userWorkerInvocation = true ;
92+ return env . JAEGER . enterSpan ( "dispatch_worker" , async ( span ) => {
93+ span . setTags ( {
94+ hasUserWorker : true ,
95+ asset : asset ,
96+ dispatchType : DISPATCH_TYPE . WORKER ,
97+ } ) ;
98+
99+ let shouldBlockNonImageResponse = false ;
100+ if ( url . pathname === "/_next/image" ) {
101+ // is a next image
102+ const queryURLParam = url . searchParams . get ( "url" ) ;
103+ if ( queryURLParam && ! queryURLParam . startsWith ( "/" ) ) {
104+ // that's a remote resource
105+ if (
106+ maybeSecondRequest . method !== "GET" ||
107+ maybeSecondRequest . headers . get ( "sec-fetch-dest" ) !== "image"
108+ ) {
109+ // that was not loaded via a browser's <img> tag
110+ shouldBlockNonImageResponse = true ;
111+ analytics . setData ( { abuseMitigationURLHost : queryURLParam } ) ;
112+ }
113+ // otherwise, we're good
114+ }
115+ }
116+
117+ if ( shouldBlockNonImageResponse ) {
118+ const resp = await env . USER_WORKER . fetch ( maybeSecondRequest ) ;
119+ if (
120+ ! resp . headers . get ( "content-type" ) ?. startsWith ( "image/" ) &&
121+ resp . status !== 304
122+ ) {
123+ analytics . setData ( { abuseMitigationBlocked : true } ) ;
124+ return new Response ( "Blocked" , { status : 403 } ) ;
125+ }
126+ return resp ;
127+ }
128+ return env . USER_WORKER . fetch ( maybeSecondRequest ) ;
129+ } ) ;
130+ } ;
131+
132+ const routeToAssets = async ( {
133+ asset,
134+ } : {
135+ asset : "static_routing" | "found" | "none" ;
136+ } ) => {
137+ analytics . setData ( { dispatchtype : DISPATCH_TYPE . ASSETS } ) ;
138+ return await env . JAEGER . enterSpan ( "dispatch_assets" , async ( span ) => {
139+ span . setTags ( {
140+ hasUserWorker : config . has_user_worker ,
141+ asset : asset ,
142+ dispatchType : DISPATCH_TYPE . ASSETS ,
143+ } ) ;
144+
145+ return env . ASSET_WORKER . fetch ( maybeSecondRequest ) ;
146+ } ) ;
147+ } ;
97148
98149 if ( config . static_routing ) {
99150 // evaluate "exclude" rules
@@ -107,18 +158,9 @@ export default {
107158 ) {
108159 // direct to asset worker
109160 analytics . setData ( {
110- dispatchtype : DISPATCH_TYPE . ASSETS ,
111161 staticRoutingDecision : STATIC_ROUTING_DECISION . ROUTED ,
112162 } ) ;
113- return await env . JAEGER . enterSpan ( "dispatch_assets" , async ( span ) => {
114- span . setTags ( {
115- hasUserWorker : config . has_user_worker ,
116- asset : "static_routing" ,
117- dispatchType : DISPATCH_TYPE . ASSETS ,
118- } ) ;
119-
120- return env . ASSET_WORKER . fetch ( maybeSecondRequest ) ;
121- } ) ;
163+ return await routeToAssets ( { asset : "static_routing" } ) ;
122164 }
123165 // evaluate "include" rules
124166 const includeRulesMatcher = generateStaticRoutingRuleMatcher (
@@ -136,30 +178,9 @@ export default {
136178 }
137179 // direct to user worker
138180 analytics . setData ( {
139- dispatchtype : DISPATCH_TYPE . WORKER ,
140181 staticRoutingDecision : STATIC_ROUTING_DECISION . ROUTED ,
141182 } ) ;
142- return await env . JAEGER . enterSpan ( "dispatch_worker" , async ( span ) => {
143- span . setTags ( {
144- hasUserWorker : true ,
145- asset : "static_routing" ,
146- dispatchType : DISPATCH_TYPE . WORKER ,
147- } ) ;
148-
149- userWorkerInvocation = true ;
150- if ( shouldBlockNonImageResponse ) {
151- const resp = await env . USER_WORKER . fetch ( maybeSecondRequest ) ;
152- if (
153- ! resp . headers . get ( "content-type" ) ?. startsWith ( "image/" ) &&
154- resp . status !== 304
155- ) {
156- analytics . setData ( { abuseMitigationBlocked : true } ) ;
157- return new Response ( "Blocked" , { status : 403 } ) ;
158- }
159- return resp ;
160- }
161- return env . USER_WORKER . fetch ( maybeSecondRequest ) ;
162- } ) ;
183+ return await routeToUserWorker ( { asset : "static_routing" } ) ;
163184 }
164185
165186 analytics . setData ( {
@@ -172,75 +193,17 @@ export default {
172193 // User's configuration indicates they want user-Worker to run ahead of any
173194 // assets. Do not provide any fallback logic.
174195 if ( config . invoke_user_worker_ahead_of_assets ) {
175- if ( ! config . has_user_worker ) {
176- throw new Error (
177- "Fetch for user worker without having a user worker binding"
178- ) ;
179- }
180-
181- analytics . setData ( { dispatchtype : DISPATCH_TYPE . WORKER } ) ;
182- return await env . JAEGER . enterSpan ( "dispatch_worker" , async ( span ) => {
183- span . setTags ( {
184- hasUserWorker : true ,
185- asset : "ignored" ,
186- dispatchType : DISPATCH_TYPE . WORKER ,
187- } ) ;
188-
189- userWorkerInvocation = true ;
190- if ( shouldBlockNonImageResponse ) {
191- const resp = await env . USER_WORKER . fetch ( maybeSecondRequest ) ;
192- if (
193- ! resp . headers . get ( "content-type" ) ?. startsWith ( "image/" ) &&
194- resp . status !== 304
195- ) {
196- analytics . setData ( { abuseMitigationBlocked : true } ) ;
197- return new Response ( "Blocked" , { status : 403 } ) ;
198- }
199- return resp ;
200- }
201- return env . USER_WORKER . fetch ( maybeSecondRequest ) ;
202- } ) ;
196+ return await routeToUserWorker ( { asset : "static_routing" } ) ;
203197 }
204198
205199 // If we have a user-Worker, but no assets, dispatch to Worker script
206200 const assetsExist = await env . ASSET_WORKER . unstable_canFetch ( request ) ;
207201 if ( config . has_user_worker && ! assetsExist ) {
208- analytics . setData ( { dispatchtype : DISPATCH_TYPE . WORKER } ) ;
209-
210- return await env . JAEGER . enterSpan ( "dispatch_worker" , async ( span ) => {
211- span . setTags ( {
212- hasUserWorker : config . has_user_worker ,
213- asset : assetsExist ,
214- dispatchType : DISPATCH_TYPE . WORKER ,
215- } ) ;
216-
217- userWorkerInvocation = true ;
218- if ( shouldBlockNonImageResponse ) {
219- const resp = await env . USER_WORKER . fetch ( maybeSecondRequest ) ;
220- if (
221- ! resp . headers . get ( "content-type" ) ?. startsWith ( "image/" ) &&
222- resp . status !== 304
223- ) {
224- analytics . setData ( { abuseMitigationBlocked : true } ) ;
225- return new Response ( "Blocked" , { status : 403 } ) ;
226- }
227- return resp ;
228- }
229- return env . USER_WORKER . fetch ( maybeSecondRequest ) ;
230- } ) ;
202+ return await routeToUserWorker ( { asset : "none" } ) ;
231203 }
232204
233205 // Otherwise, we either don't have a user worker, OR we have matching assets and should fetch from the assets binding
234- analytics . setData ( { dispatchtype : DISPATCH_TYPE . ASSETS } ) ;
235- return await env . JAEGER . enterSpan ( "dispatch_assets" , async ( span ) => {
236- span . setTags ( {
237- hasUserWorker : config . has_user_worker ,
238- asset : assetsExist ,
239- dispatchType : DISPATCH_TYPE . ASSETS ,
240- } ) ;
241-
242- return env . ASSET_WORKER . fetch ( maybeSecondRequest ) ;
243- } ) ;
206+ return await routeToAssets ( { asset : assetsExist ? "found" : "none" } ) ;
244207 } catch ( err ) {
245208 if ( userWorkerInvocation ) {
246209 // Don't send user Worker errors to sentry; we have no way to distinguish between
0 commit comments