@@ -13,6 +13,7 @@ use crate::auth::S3Auth;
13
13
use crate :: auth:: S3AuthContext ;
14
14
use crate :: error:: * ;
15
15
use crate :: header;
16
+ use crate :: host:: S3Host ;
16
17
use crate :: http;
17
18
use crate :: http:: Body ;
18
19
use crate :: http:: { OrderedHeaders , OrderedQs } ;
@@ -85,27 +86,16 @@ fn extract_host(req: &Request) -> S3Result<Option<String>> {
85
86
Ok ( Some ( host. into ( ) ) )
86
87
}
87
88
88
- fn is_socket_addr ( host : & str ) -> bool {
89
+ fn is_socket_addr_or_ip_addr ( host : & str ) -> bool {
89
90
host. parse :: < SocketAddr > ( ) . is_ok ( ) || host. parse :: < IpAddr > ( ) . is_ok ( )
90
91
}
91
92
92
- fn extract_s3_path ( host : Option < & str > , uri_path : & str , base_domain : Option < & str > ) -> S3Result < S3Path > {
93
- let result = match ( base_domain, host) {
94
- ( Some ( base_domain) , Some ( host) ) if base_domain != host && !is_socket_addr ( host) => {
95
- debug ! ( ?base_domain, ?host, ?uri_path, "parsing virtual-hosted-style request" ) ;
96
- crate :: path:: parse_virtual_hosted_style ( base_domain, host, uri_path)
97
- }
98
- _ => {
99
- debug ! ( ?uri_path, "parsing path-style request" ) ;
100
- crate :: path:: parse_path_style ( uri_path)
101
- }
102
- } ;
103
-
104
- result. map_err ( |err| match err {
93
+ fn convert_parse_s3_path_error ( err : & ParseS3PathError ) -> S3Error {
94
+ match err {
105
95
ParseS3PathError :: InvalidPath => s3_error ! ( InvalidURI ) ,
106
96
ParseS3PathError :: InvalidBucketName => s3_error ! ( InvalidBucketName ) ,
107
97
ParseS3PathError :: KeyTooLong => s3_error ! ( KeyTooLongError ) ,
108
- } )
98
+ }
109
99
}
110
100
111
101
fn extract_qs ( req_uri : & Uri ) -> S3Result < Option < OrderedQs > > {
@@ -183,9 +173,9 @@ pub async fn call(
183
173
req : & mut Request ,
184
174
s3 : & Arc < dyn S3 > ,
185
175
auth : Option < & dyn S3Auth > ,
186
- base_domain : Option < & str > ,
176
+ host : Option < & dyn S3Host > ,
187
177
) -> S3Result < Response > {
188
- let op = match prepare ( req, auth, base_domain ) . await {
178
+ let op = match prepare ( req, auth, host ) . await {
189
179
Ok ( op) => op,
190
180
Err ( err) => {
191
181
debug ! ( ?err, "failed to prepare" ) ;
@@ -204,18 +194,40 @@ pub async fn call(
204
194
Ok ( resp)
205
195
}
206
196
207
- async fn prepare ( req : & mut Request , auth : Option < & dyn S3Auth > , base_domain : Option < & str > ) -> S3Result < & ' static dyn Operation > {
197
+ #[ allow( clippy:: too_many_lines) ]
198
+ async fn prepare ( req : & mut Request , auth : Option < & dyn S3Auth > , s3_host : Option < & dyn S3Host > ) -> S3Result < & ' static dyn Operation > {
208
199
let s3_path;
209
200
let mut content_length;
210
201
{
211
202
let decoded_uri_path = urlencoding:: decode ( req. uri . path ( ) )
212
203
. map_err ( |_| S3ErrorCode :: InvalidURI ) ?
213
204
. into_owned ( ) ;
214
205
215
- let host = extract_host ( req) ?;
206
+ let host_header = extract_host ( req) ?;
207
+ let vh;
208
+ let vh_bucket;
209
+ {
210
+ let result = ' parse: {
211
+ if let ( Some ( host_header) , Some ( s3_host) ) = ( host_header. as_deref ( ) , s3_host) {
212
+ if !is_socket_addr_or_ip_addr ( host_header) {
213
+ debug ! ( ?host_header, ?decoded_uri_path, "parsing virtual-hosted-style request" ) ;
214
+
215
+ vh = s3_host. parse_host_header ( host_header) ?;
216
+ debug ! ( ?vh) ;
216
217
217
- req. s3ext . s3_path = Some ( extract_s3_path ( host. as_deref ( ) , & decoded_uri_path, base_domain) ?) ;
218
- s3_path = req. s3ext . s3_path . as_ref ( ) . unwrap ( ) ;
218
+ vh_bucket = vh. bucket ( ) ;
219
+ break ' parse crate :: path:: parse_virtual_hosted_style ( vh_bucket, & decoded_uri_path) ;
220
+ }
221
+ }
222
+
223
+ debug ! ( ?decoded_uri_path, "parsing path-style request" ) ;
224
+ vh_bucket = None ;
225
+ crate :: path:: parse_path_style ( & decoded_uri_path)
226
+ } ;
227
+
228
+ req. s3ext . s3_path = Some ( result. map_err ( |err| convert_parse_s3_path_error ( & err) ) ?) ;
229
+ s3_path = req. s3ext . s3_path . as_ref ( ) . unwrap ( ) ;
230
+ }
219
231
220
232
req. s3ext . qs = extract_qs ( & req. uri ) ?;
221
233
content_length = extract_content_length ( req) ;
@@ -229,7 +241,6 @@ async fn prepare(req: &mut Request, auth: Option<&dyn S3Auth>, base_domain: Opti
229
241
{
230
242
let mut scx = SignatureContext {
231
243
auth,
232
- base_domain,
233
244
234
245
req_method : & req. method ,
235
246
req_uri : & req. uri ,
@@ -239,9 +250,8 @@ async fn prepare(req: &mut Request, auth: Option<&dyn S3Auth>, base_domain: Opti
239
250
hs,
240
251
241
252
decoded_uri_path,
242
- s3_path ,
253
+ vh_bucket ,
243
254
244
- host : host. as_deref ( ) ,
245
255
content_length,
246
256
decoded_content_length,
247
257
mime,
0 commit comments