@@ -187,28 +187,24 @@ impl Service<Request<Incoming>> for WrappingService {
187187 }
188188 } ;
189189
190- if let ( Some ( origin) , Some ( requested_method) , Some ( config) ) = (
191- origin. as_deref ( ) ,
192- preflight_requested_method. as_deref ( ) ,
193- cors_configuration. as_ref ( ) ,
194- )
195- && method == Method :: OPTIONS
190+ if let Some ( config) = cors_configuration. as_ref ( )
191+ && let Some ( response) = handle_cors_preflight (
192+ config,
193+ & method,
194+ origin. as_deref ( ) ,
195+ preflight_requested_method. as_deref ( ) ,
196+ & requested_headers,
197+ )
196198 {
197- let response = match match_preflight_rule ( config, origin, requested_method, & requested_headers) {
198- Some ( matched_rule) => build_preflight_response ( matched_rule) ,
199- None => build_preflight_forbidden_response ( )
200- } ;
201199 emit_request_completed ( & span, "s3" , response. status ( ) . as_u16 ( ) , started) ;
202200 return Ok ( response) ;
203201 }
204202
205203 let result = shared. call ( s3s_request) . instrument ( span. clone ( ) ) . await ;
206204 match result {
207205 Ok ( mut response) => {
208- if let ( Some ( origin) , Some ( config) ) = ( origin. as_deref ( ) , cors_configuration. as_ref ( ) ) {
209- if let Some ( matched_rule) = match_actual_rule ( config, origin, & method) {
210- inject_actual_cors_headers ( & mut response, matched_rule) ;
211- }
206+ if let Some ( config) = cors_configuration. as_ref ( ) {
207+ apply_cors_to_response ( & mut response, config, origin. as_deref ( ) , & method) ;
212208 }
213209 emit_request_completed ( & span, "s3" , response. status ( ) . as_u16 ( ) , started) ;
214210 Ok ( response)
@@ -250,6 +246,40 @@ fn virtual_hosted_bucket(host: &str, domain: &str) -> Option<String> {
250246 ( !prefix. is_empty ( ) ) . then ( || prefix. to_owned ( ) )
251247}
252248
249+ fn handle_cors_preflight (
250+ config : & BucketCorsConfiguration ,
251+ method : & Method ,
252+ origin : Option < & str > ,
253+ requested_method : Option < & str > ,
254+ requested_headers : & [ String ] ,
255+ ) -> Option < HttpResponse > {
256+ if * method != Method :: OPTIONS {
257+ return None ;
258+ }
259+ let origin = origin?;
260+ let requested_method = requested_method?;
261+
262+ Some (
263+ match match_preflight_rule ( config, origin, requested_method, requested_headers) {
264+ Some ( matched_rule) => build_preflight_response ( matched_rule) ,
265+ None => build_preflight_forbidden_response ( ) ,
266+ } ,
267+ )
268+ }
269+
270+ fn apply_cors_to_response (
271+ response : & mut HttpResponse ,
272+ config : & BucketCorsConfiguration ,
273+ origin : Option < & str > ,
274+ method : & Method ,
275+ ) {
276+ if let Some ( origin) = origin
277+ && let Some ( matched_rule) = match_actual_rule ( config, origin, method)
278+ {
279+ inject_actual_cors_headers ( response, matched_rule) ;
280+ }
281+ }
282+
253283async fn load_bucket_cors_config (
254284 driver_ctx : Arc < DriverContext > ,
255285 bucket : Option < String > ,
@@ -272,16 +302,6 @@ async fn load_bucket_cors_config(
272302mod tests {
273303 use super :: * ;
274304
275- fn matched_rule ( ) -> super :: super :: cors:: MatchedCorsRule {
276- super :: super :: cors:: MatchedCorsRule {
277- allow_origin : "https://example.org" . to_string ( ) ,
278- allow_methods : vec ! [ "GET" . to_string( ) , "PUT" . to_string( ) ] ,
279- allow_headers : vec ! [ "content-type" . to_string( ) , "x-test" . to_string( ) ] ,
280- expose_headers : vec ! [ "etag" . to_string( ) ] ,
281- max_age_seconds : Some ( 60 ) ,
282- }
283- }
284-
285305 #[ test]
286306 fn extracts_bucket_name_from_path_style_request ( ) {
287307 assert_eq ! (
0 commit comments