All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.findify.s3mock.route.PutObject.scala Maven / Gradle / Ivy

The newest version!
package io.findify.s3mock.route

import akka.http.scaladsl.model.{HttpRequest, HttpResponse, StatusCodes}
import akka.http.scaladsl.server.Directives._
import akka.stream.Materializer
import akka.stream.scaladsl.Sink
import akka.util.ByteString
import com.amazonaws.services.s3.model.ObjectMetadata
import com.typesafe.scalalogging.LazyLogging
import io.findify.s3mock.S3ChunkedProtocolStage
import io.findify.s3mock.error.{InternalErrorException, NoSuchBucketException}
import io.findify.s3mock.provider.Provider
import org.apache.commons.codec.digest.DigestUtils

import scala.util.{Failure, Success, Try}

/**
  * Created by shutty on 8/20/16.
  */
case class PutObject()(implicit provider:Provider, mat:Materializer) extends LazyLogging {
  def route(bucket:String, path:String) = put {
    extractRequest { request =>
      headerValueByName("x-amz-decoded-content-length") { _ =>
        completeSigned(bucket, path)
      } ~ completePlain(bucket, path)
    }
  } ~ post {
    completePlain(bucket, path)
  }


  def completeSigned(bucket:String, path:String) = extractRequest { request =>
    complete {


      logger.info(s"put object $bucket/$path (signed)")
      val result = request.entity.dataBytes
        .via(new S3ChunkedProtocolStage)
        .fold(ByteString(""))(_ ++ _)
        .map(data => {
          val bytes = data.toArray
          val metadata = populateObjectMetadata(request, bytes)
          Try(provider.putObject(bucket, path, bytes, metadata)) match {
            case Success(()) => HttpResponse(StatusCodes.OK)
            case Failure(e: NoSuchBucketException) =>
              HttpResponse(
                StatusCodes.NotFound,
                entity = e.toXML.toString()
              )
            case Failure(t) =>
              HttpResponse(
                StatusCodes.InternalServerError,
                entity = InternalErrorException(t).toXML.toString()
              )
          }
        }).runWith(Sink.head[HttpResponse])
      result
    }
  }

  def completePlain(bucket:String, path:String) = extractRequest { request =>
    complete {

      logger.info(s"put object $bucket/$path (unsigned)")
      val result = request.entity.dataBytes
        .fold(ByteString(""))(_ ++ _)
        .map(data => {
          val bytes = data.toArray
          val metadata = populateObjectMetadata(request, bytes)
          Try(provider.putObject(bucket, path, bytes, metadata)) match {
            case Success(()) => HttpResponse(StatusCodes.OK)
            case Failure(e: NoSuchBucketException) =>
              HttpResponse(
                StatusCodes.NotFound,
                entity = e.toXML.toString()
              )
            case Failure(t) =>
              HttpResponse(
                StatusCodes.InternalServerError,
                entity = InternalErrorException(t).toXML.toString()
              )
          }
        }).runWith(Sink.head[HttpResponse])
      result
    }
  }

  private def populateObjectMetadata(request: HttpRequest, bytes: Array[Byte]): ObjectMetadata = {
    val metadata = MetadataUtil.populateObjectMetadata(request)
    metadata.setContentMD5(DigestUtils.md5Hex(bytes))
    metadata
  }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy