diff --git a/server/src/main/java/com/adobe/testing/s3mock/BucketController.java b/server/src/main/java/com/adobe/testing/s3mock/BucketController.java index 91c1751f9..658df6f55 100644 --- a/server/src/main/java/com/adobe/testing/s3mock/BucketController.java +++ b/server/src/main/java/com/adobe/testing/s3mock/BucketController.java @@ -16,6 +16,7 @@ package com.adobe.testing.s3mock; +import static com.adobe.testing.s3mock.BucketNameFilter.BUCKET_ATTRIBUTE; import static com.adobe.testing.s3mock.util.AwsHttpHeaders.X_AMZ_BUCKET_OBJECT_LOCK_ENABLED; import static com.adobe.testing.s3mock.util.AwsHttpParameters.CONTINUATION_TOKEN; import static com.adobe.testing.s3mock.util.AwsHttpParameters.ENCODING_TYPE; @@ -31,6 +32,7 @@ import static org.springframework.http.MediaType.APPLICATION_XML_VALUE; import com.adobe.testing.s3mock.dto.BucketLifecycleConfiguration; +import com.adobe.testing.s3mock.dto.BucketName; import com.adobe.testing.s3mock.dto.ListAllMyBucketsResult; import com.adobe.testing.s3mock.dto.ListBucketResult; import com.adobe.testing.s3mock.dto.ListBucketResultV2; @@ -39,6 +41,7 @@ import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.CrossOrigin; import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestAttribute; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestHeader; import org.springframework.web.bind.annotation.RequestMapping; @@ -105,7 +108,10 @@ public ResponseEntity listBuckets() { ) public ResponseEntity createBucket(@PathVariable final String bucketName, @RequestHeader(value = X_AMZ_BUCKET_OBJECT_LOCK_ENABLED, - required = false, defaultValue = "false") boolean objectLockEnabled) { + required = false, defaultValue = "false") boolean objectLockEnabled, + @RequestAttribute(BUCKET_ATTRIBUTE) BucketName bucket) { + //TODO: does subdomain access work for #createBucket in S3? + assert bucketName.equals(bucket.getName()); bucketService.verifyBucketNameIsAllowed(bucketName); bucketService.verifyBucketDoesNotExist(bucketName); bucketService.createBucket(bucketName, objectLockEnabled); @@ -124,7 +130,9 @@ public ResponseEntity createBucket(@PathVariable final String bucketName, value = "/{bucketName:[a-z0-9.-]+}", method = RequestMethod.HEAD ) - public ResponseEntity headBucket(@PathVariable final String bucketName) { + public ResponseEntity headBucket(@PathVariable final String bucketName, + @RequestAttribute(BUCKET_ATTRIBUTE) BucketName bucket) { + assert bucketName.equals(bucket.getName()); bucketService.verifyBucketExists(bucketName); return ResponseEntity.ok().build(); } @@ -144,7 +152,9 @@ public ResponseEntity headBucket(@PathVariable final String bucketName) { }, method = RequestMethod.DELETE ) - public ResponseEntity deleteBucket(@PathVariable String bucketName) { + public ResponseEntity deleteBucket(@PathVariable String bucketName, + @RequestAttribute(BUCKET_ATTRIBUTE) BucketName bucket) { + assert bucketName.equals(bucket.getName()); bucketService.verifyBucketExists(bucketName); bucketService.verifyBucketIsEmpty(bucketName); bucketService.deleteBucket(bucketName); @@ -171,7 +181,9 @@ public ResponseEntity deleteBucket(@PathVariable String bucketName) { } ) public ResponseEntity getObjectLockConfiguration( - @PathVariable String bucketName) { + @PathVariable String bucketName, + @RequestAttribute(BUCKET_ATTRIBUTE) BucketName bucket) { + assert bucketName.equals(bucket.getName()); bucketService.verifyBucketExists(bucketName); ObjectLockConfiguration configuration = bucketService.getObjectLockConfiguration(bucketName); return ResponseEntity.ok(configuration); @@ -195,7 +207,9 @@ public ResponseEntity getObjectLockConfiguration( ) public ResponseEntity putObjectLockConfiguration( @PathVariable String bucketName, - @RequestBody ObjectLockConfiguration configuration) { + @RequestBody ObjectLockConfiguration configuration, + @RequestAttribute(BUCKET_ATTRIBUTE) BucketName bucket) { + assert bucketName.equals(bucket.getName()); bucketService.verifyBucketExists(bucketName); bucketService.setObjectLockConfiguration(bucketName, configuration); return ResponseEntity.ok().build(); @@ -221,7 +235,9 @@ public ResponseEntity putObjectLockConfiguration( } ) public ResponseEntity getBucketLifecycleConfiguration( - @PathVariable String bucketName) { + @PathVariable String bucketName, + @RequestAttribute(BUCKET_ATTRIBUTE) BucketName bucket) { + assert bucketName.equals(bucket.getName()); bucketService.verifyBucketExists(bucketName); BucketLifecycleConfiguration configuration = bucketService.getBucketLifecycleConfiguration(bucketName); @@ -246,7 +262,9 @@ public ResponseEntity getBucketLifecycleConfigurat ) public ResponseEntity putBucketLifecycleConfiguration( @PathVariable String bucketName, - @RequestBody BucketLifecycleConfiguration configuration) { + @RequestBody BucketLifecycleConfiguration configuration, + @RequestAttribute(BUCKET_ATTRIBUTE) BucketName bucket) { + assert bucketName.equals(bucket.getName()); bucketService.verifyBucketExists(bucketName); bucketService.setBucketLifecycleConfiguration(bucketName, configuration); return ResponseEntity.ok().build(); @@ -268,7 +286,9 @@ public ResponseEntity putBucketLifecycleConfiguration( method = RequestMethod.DELETE ) public ResponseEntity deleteBucketLifecycleConfiguration( - @PathVariable String bucketName) { + @PathVariable String bucketName, + @RequestAttribute(BUCKET_ATTRIBUTE) BucketName bucket) { + assert bucketName.equals(bucket.getName()); bucketService.verifyBucketExists(bucketName); bucketService.deleteBucketLifecycleConfiguration(bucketName); return ResponseEntity.noContent().build(); @@ -305,7 +325,9 @@ public ResponseEntity listObjects( @RequestParam(required = false) String delimiter, @RequestParam(required = false) String marker, @RequestParam(name = ENCODING_TYPE, required = false) String encodingType, - @RequestParam(name = MAX_KEYS, defaultValue = "1000", required = false) Integer maxKeys) { + @RequestParam(name = MAX_KEYS, defaultValue = "1000", required = false) Integer maxKeys, + @RequestAttribute(BUCKET_ATTRIBUTE) BucketName bucket) { + assert bucketName.equals(bucket.getName()); bucketService.verifyBucketExists(bucketName); bucketService.verifyMaxKeys(maxKeys); bucketService.verifyEncodingType(encodingType); @@ -343,7 +365,9 @@ public ResponseEntity listObjectsV2( @RequestParam(name = ENCODING_TYPE, required = false) String encodingType, @RequestParam(name = START_AFTER, required = false) String startAfter, @RequestParam(name = MAX_KEYS, defaultValue = "1000", required = false) Integer maxKeys, - @RequestParam(name = CONTINUATION_TOKEN, required = false) String continuationToken) { + @RequestParam(name = CONTINUATION_TOKEN, required = false) String continuationToken, + @RequestAttribute(BUCKET_ATTRIBUTE) BucketName bucket) { + assert bucketName.equals(bucket.getName()); bucketService.verifyBucketExists(bucketName); bucketService.verifyMaxKeys(maxKeys); bucketService.verifyEncodingType(encodingType); diff --git a/server/src/main/java/com/adobe/testing/s3mock/BucketNameFilter.java b/server/src/main/java/com/adobe/testing/s3mock/BucketNameFilter.java index 36acd559f..99e262d60 100644 --- a/server/src/main/java/com/adobe/testing/s3mock/BucketNameFilter.java +++ b/server/src/main/java/com/adobe/testing/s3mock/BucketNameFilter.java @@ -32,8 +32,8 @@ class BucketNameFilter extends OncePerRequestFilter { private static final Logger LOG = LoggerFactory.getLogger(BucketNameFilter.class); - private static final Pattern BUCKET_AND_KEY_PATTERN = Pattern.compile("/[a-z0-9.-]+/.*"); - private static final Pattern BUCKET_PATTERN = Pattern.compile("/[a-z0-9.-]+/?"); + private static final Pattern BUCKET_AND_KEY_PATTERN = Pattern.compile("/.+/.*"); + private static final Pattern BUCKET_PATTERN = Pattern.compile("/.+/?"); static final String BUCKET_ATTRIBUTE = "bucketName"; @Override