@@ -213,28 +213,49 @@ func (g *S3Getter) parseUrl(u *url.URL) (region, bucket, path, version string, c
213
213
// any other S3 compliant service. S3 has a predictable
214
214
// url as others do not
215
215
if strings .Contains (u .Host , "amazonaws.com" ) {
216
- // Expected host style: s3.amazonaws.com. They always have 3 parts,
217
- // although the first may differ if we're accessing a specific region.
216
+ // Amazon S3 supports both virtual-hosted–style and path-style URLs to access a bucket, although path-style is deprecated
217
+ // In both cases few older regions supports dash-style region indication (s3-Region) even if AWS discourages their use.
218
+ // The same bucket could be reached with:
219
+ // bucket.s3.region.amazonaws.com/path
220
+ // bucket.s3-region.amazonaws.com/path
221
+ // s3.amazonaws.com/bucket/path
222
+ // s3-region.amazonaws.com/bucket/path
223
+
218
224
hostParts := strings .Split (u .Host , "." )
219
- if len (hostParts ) != 3 {
220
- err = fmt .Errorf ("URL is not a valid S3 URL" )
221
- return
222
- }
225
+ switch len (hostParts ) {
226
+ // path-style
227
+ case 3 :
228
+ // Parse the region out of the first part of the host
229
+ region = strings .TrimPrefix (strings .TrimPrefix (hostParts [0 ], "s3-" ), "s3" )
230
+ if region == "" {
231
+ region = "us-east-1"
232
+ }
233
+ pathParts := strings .SplitN (u .Path , "/" , 3 )
234
+ bucket = pathParts [1 ]
235
+ path = pathParts [2 ]
236
+ // vhost-style, dash region indication
237
+ case 4 :
238
+ // Parse the region out of the first part of the host
239
+ region = strings .TrimPrefix (strings .TrimPrefix (hostParts [1 ], "s3-" ), "s3" )
240
+ if region == "" {
241
+ err = fmt .Errorf ("URL is not a valid S3 URL" )
242
+ return
243
+ }
244
+ pathParts := strings .SplitN (u .Path , "/" , 2 )
245
+ bucket = hostParts [0 ]
246
+ path = pathParts [1 ]
247
+ //vhost-style, dot region indication
248
+ case 5 :
249
+ region = hostParts [2 ]
250
+ pathParts := strings .SplitN (u .Path , "/" , 2 )
251
+ bucket = hostParts [0 ]
252
+ path = pathParts [1 ]
223
253
224
- // Parse the region out of the first part of the host
225
- region = strings .TrimPrefix (strings .TrimPrefix (hostParts [0 ], "s3-" ), "s3" )
226
- if region == "" {
227
- region = "us-east-1"
228
254
}
229
-
230
- pathParts := strings .SplitN (u .Path , "/" , 3 )
231
- if len (pathParts ) != 3 {
255
+ if len (hostParts ) < 3 && len (hostParts ) > 5 {
232
256
err = fmt .Errorf ("URL is not a valid S3 URL" )
233
257
return
234
258
}
235
-
236
- bucket = pathParts [1 ]
237
- path = pathParts [2 ]
238
259
version = u .Query ().Get ("version" )
239
260
240
261
} else {
0 commit comments