src/main/scala/s3/website/S3.scala in s3_website-2.10.0 vs src/main/scala/s3/website/S3.scala in s3_website-2.11.0

- old
+ new

@@ -50,11 +50,11 @@ def delete(s3Key: S3Key, a: Attempt = 1) (implicit config: Config, s3Settings: S3Setting, pushOptions: PushOptions, executor: ExecutionContextExecutor, logger: Logger): Future[Either[FailedDelete, SuccessfulDelete]] = Future { - if (!pushOptions.dryRun) s3Settings.s3Client(config) deleteObject(config.s3_bucket, s3Key) + if (!pushOptions.dryRun) s3Settings.s3Client(config) deleteObject(config.s3_bucket, s3Key.key) val report = SuccessfulDelete(s3Key) logger.info(report) Right(report) } recoverWith retry(a)( createFailureReport = error => FailedDelete(s3Key, error), @@ -84,17 +84,17 @@ case seconds => s"max-age=$seconds" }) case (None, None) => None } cacheControl foreach { md.setCacheControl } - val req = new PutObjectRequest(config.s3_bucket, upload.s3Key, new FileInputStream(uploadFile), md) + val req = new PutObjectRequest(config.s3_bucket, upload.s3Key.key, new FileInputStream(uploadFile), md) config.s3_reduced_redundancy.filter(_ == true) foreach (_ => req setStorageClass ReducedRedundancy) req } , redirect => { - val req = new PutObjectRequest(config.s3_bucket, redirect.s3Key, redirect.redirectTarget) + val req = new PutObjectRequest(config.s3_bucket, redirect.s3Key.key, redirect.redirectTarget) req.setMetadata({ val md = new ObjectMetadata() md.setContentLength(0) // Otherwise the AWS SDK will log a warning /* * Instruct HTTP clients to always re-check the redirect. The 301 status code may override this, though. @@ -114,25 +114,32 @@ } def awsS3Client(config: Config) = new AmazonS3Client(awsCredentials(config)) def resolveS3Files(nextMarker: Option[String] = None, alreadyResolved: Seq[S3File] = Nil, attempt: Attempt = 1) - (implicit config: Config, s3Settings: S3Setting, ec: ExecutionContextExecutor, logger: Logger, pushOptions: PushOptions): + (implicit site: Site, s3Settings: S3Setting, ec: ExecutionContextExecutor, logger: Logger, pushOptions: PushOptions): Future[Either[ErrorReport, Seq[S3File]]] = Future { logger.debug(nextMarker.fold ("Querying S3 files") {m => s"Querying more S3 files (starting from $m)"} ) - val objects: ObjectListing = s3Settings.s3Client(config).listObjects({ + val objects: ObjectListing = s3Settings.s3Client(site.config).listObjects({ val req = new ListObjectsRequest() - req.setBucketName(config.s3_bucket) + req.setBucketName(site.config.s3_bucket) nextMarker.foreach(req.setMarker) req }) objects } flatMap { (objects: ObjectListing) => - val s3Files = alreadyResolved ++ (objects.getObjectSummaries.toIndexedSeq.toSeq map (S3File(_))) + + /** + * We could filter the keys by prefix already on S3, but unfortunately s3_website test infrastructure does not currently support testing of that. + * Hence fetch all the keys from S3 and then filter by s3_key_prefix. + */ + def matchesPrefix(os: S3ObjectSummary) = site.config.s3_key_prefix.fold(true)(prefix => os.getKey.startsWith(prefix)) + + val s3Files = alreadyResolved ++ (objects.getObjectSummaries.filter(matchesPrefix).toIndexedSeq.toSeq map (S3File(_))) Option(objects.getNextMarker) .fold(Future(Right(s3Files)): Future[Either[ErrorReport, Seq[S3File]]]) // We've received all the S3 keys from the bucket { nextMarker => // There are more S3 keys on the bucket. Fetch them. resolveS3Files(Some(nextMarker), s3Files, attempt = attempt) } @@ -147,11 +154,11 @@ type UpdateFutures = Seq[Either[ErrorReport, Future[PushErrorOrSuccess]]] type ErrorOrS3Files = Either[ErrorReport, Seq[S3File]] sealed trait PushFailureReport extends ErrorReport sealed trait PushSuccessReport extends SuccessReport { - def s3Key: String + def s3Key: S3Key } case class SuccessfulRedirectDetails(uploadType: UploadType, redirectTarget: String) case class SuccessfulNewOrCreatedDetails(uploadType: UploadType, uploadSize: Long, uploadDuration: Option[Long]) @@ -209,18 +216,18 @@ None } } } - case class SuccessfulDelete(s3Key: String)(implicit pushOptions: PushOptions) extends PushSuccessReport { + case class SuccessfulDelete(s3Key: S3Key)(implicit pushOptions: PushOptions) extends PushSuccessReport { def reportMessage = s"${Deleted.renderVerb} $s3Key" } - case class FailedUpload(s3Key: String, error: Throwable)(implicit logger: Logger) extends PushFailureReport { + case class FailedUpload(s3Key: S3Key, error: Throwable)(implicit logger: Logger) extends PushFailureReport { def reportMessage = errorMessage(s"Failed to upload $s3Key", error) } - case class FailedDelete(s3Key: String, error: Throwable)(implicit logger: Logger) extends PushFailureReport { + case class FailedDelete(s3Key: S3Key, error: Throwable)(implicit logger: Logger) extends PushFailureReport { def reportMessage = errorMessage(s"Failed to delete $s3Key", error) } type S3ClientProvider = (Config) => AmazonS3