Skip to content
This repository was archived by the owner on Dec 4, 2023. It is now read-only.

Commit 2d4f49e

Browse files
committed
Merge branch 'master' of github.com:findify/s3mock
2 parents 487843c + 2cc0e4e commit 2d4f49e

14 files changed

Lines changed: 153 additions & 26 deletions

File tree

CHANGELOG.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,13 @@
1+
0.2.4 (not yet released)
2+
=======
3+
* pom -> jar dependency type doc fix
4+
* support alpakka multipart uploads
5+
* support alpakka listObjects ([#66](https://github.com/findify/s3mock/issues/66))
6+
* fix bug with etag on FileProvider being alsays "0" ([#70](https://github.com/findify/s3mock/issues/70))
7+
* fix last-modified header always being equal to "1970-01-01 00:00:00"([65](https://github.com/findify/s3mock/issues/70))
8+
* wrong content-type for listObjects ([#60](https://github.com/findify/s3mock/issues/60))
9+
* deleteObjects broken on aws s3 sdk 2.0 ([#71](https://github.com/findify/s3mock/issues/60))
10+
111
0.2.3
212
=======
313
* windows compatibility in FileProvider ([#28](https://github.com/findify/s3mock/issues/28))

README.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@ On maven, update your `pom.xml` in the following way:
3737
<groupId>io.findify</groupId>
3838
<artifactId>s3mock_2.12</artifactId>
3939
<version>0.2.3</version>
40-
<type>pom</type>
4140
<scope>test</scope>
4241
</dependency>
4342
```

build.sbt

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,11 @@ version := "0.2.3"
44

55
organization := "io.findify"
66

7-
scalaVersion := "2.12.3"
7+
scalaVersion := "2.12.4"
88

9-
crossScalaVersions := Seq("2.11.11", "2.12.2")
9+
crossScalaVersions := Seq("2.11.11", "2.12.4")
1010

11-
val akkaVersion = "2.5.4"
11+
val akkaVersion = "2.5.6"
1212

1313
licenses := Seq("MIT" -> url("https://opensource.org/licenses/MIT"))
1414

@@ -21,11 +21,11 @@ libraryDependencies ++= Seq(
2121
"org.scala-lang.modules" %% "scala-xml" % "1.0.6",
2222
"com.github.pathikrit" %% "better-files" % "2.17.1",
2323
"com.typesafe.scala-logging" %% "scala-logging" % "3.7.2",
24-
"com.amazonaws" % "aws-java-sdk-s3" % "1.11.192",
24+
"com.amazonaws" % "aws-java-sdk-s3" % "1.11.224",
2525
"org.scalatest" %% "scalatest" % "3.0.4" % "test",
2626
"ch.qos.logback" % "logback-classic" % "1.2.3" % "test",
2727
"org.iq80.leveldb" % "leveldb" % "0.9",
28-
"com.lightbend.akka" %% "akka-stream-alpakka-s3" % "0.11" % "test"
28+
"com.lightbend.akka" %% "akka-stream-alpakka-s3" % "0.14" % "test"
2929
)
3030

3131
parallelExecution in Test := false
@@ -51,4 +51,13 @@ pomExtra := (
5151
<name>Roman Grebennikov</name>
5252
<url>http://www.dfdx.me</url>
5353
</developer>
54-
</developers>)
54+
</developers>)
55+
56+
/*enablePlugins(JavaAppPackaging)
57+
58+
maintainer in Docker := "S3mock"
59+
packageSummary in Docker := "S3Mock"
60+
packageDescription := "Mock Service For S3"
61+
dockerUpdateLatest := true
62+
dockerExposedPorts := Seq(8001)
63+
*/

project/plugins.sbt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,5 @@ addSbtPlugin("com.timushev.sbt" % "sbt-updates" % "0.3.0")
44
addSbtPlugin("net.virtual-void" % "sbt-dependency-graph" % "0.8.2")
55
addSbtPlugin("org.xerial.sbt" % "sbt-sonatype" % "1.1")
66
addSbtPlugin("com.jsuereth" % "sbt-pgp" % "1.0.1")
7-
addSbtPlugin("com.github.gseitz" % "sbt-release" % "1.0.4")
7+
addSbtPlugin("com.github.gseitz" % "sbt-release" % "1.0.4")
8+
addSbtPlugin("com.typesafe.sbt" % "sbt-native-packager" % "1.2.2")

src/main/scala/io/findify/s3mock/S3Mock.scala

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,8 @@ class S3Mock(port:Int, provider:Provider)(implicit system:ActorSystem = ActorSys
3737
concat(
3838
ListBucket().route(bucket),
3939
CreateBucket().route(bucket),
40-
DeleteBucket().route(bucket)
40+
DeleteBucket().route(bucket),
41+
DeleteObjects().route(bucket)
4142
)
4243
} ~ parameterMap { params =>
4344
path(RemainingPath) { key =>
@@ -59,7 +60,7 @@ class S3Mock(port:Int, provider:Provider)(implicit system:ActorSystem = ActorSys
5960
}
6061
}
6162

62-
bind = Await.result(http.bindAndHandle(route, "localhost", port), Duration.Inf)
63+
bind = Await.result(http.bindAndHandle(route, "0.0.0.0", port), Duration.Inf)
6364
bind
6465
}
6566

src/main/scala/io/findify/s3mock/provider/FileProvider.scala

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
package io.findify.s3mock.provider
22
import java.util.UUID
3-
import java.io.{File => JFile}
3+
import java.io.{FileInputStream, File => JFile}
44

55
import akka.http.scaladsl.model.DateTime
66
import better.files.File
@@ -11,6 +11,7 @@ import io.findify.s3mock.error.{NoSuchBucketException, NoSuchKeyException}
1111
import io.findify.s3mock.provider.metadata.{MapMetadataStore, MetadataStore}
1212
import io.findify.s3mock.request.{CompleteMultipartUpload, CreateBucketConfiguration}
1313
import io.findify.s3mock.response._
14+
import org.apache.commons.codec.digest.DigestUtils
1415

1516
import scala.util.Random
1617

@@ -46,7 +47,11 @@ class FileProvider(dir:String) extends Provider with LazyLogging {
4647
val fString = fromOs(f.toString).drop(bucketFileString.length).dropWhile(_ == '/')
4748
fString.startsWith(prefixNoLeadingSlash) && !f.isDirectory
4849
})
49-
val files = bucketFiles.map(f => {Content(fromOs(f.toString).drop(bucketFileString.length+1).dropWhile(_ == '/'), DateTime(f.lastModifiedTime.toEpochMilli), "0", f.size, "STANDARD")}).toList
50+
val files = bucketFiles.map(f => {
51+
val stream = new FileInputStream(f.toJava)
52+
val md5 = DigestUtils.md5Hex(stream)
53+
Content(fromOs(f.toString).drop(bucketFileString.length+1).dropWhile(_ == '/'), DateTime(f.lastModifiedTime.toEpochMilli), md5, f.size, "STANDARD")
54+
}).toList
5055
logger.debug(s"listing bucket contents: ${files.map(_.key)}")
5156
val commonPrefixes = delimiter match {
5257
case Some(del) => files.flatMap(f => commonPrefix(f.key, prefixNoLeadingSlash, del)).distinct.sorted
@@ -71,6 +76,7 @@ class FileProvider(dir:String) extends Provider with LazyLogging {
7176
file.createIfNotExists(createParents = true)
7277
logger.debug(s"writing file for s3://$bucket/$key to $dir/$bucket/$key, bytes = ${data.length}")
7378
file.writeByteArray(data)(OpenOptions.default)
79+
objectMetadata.setLastModified(org.joda.time.DateTime.now().toDate)
7480
metadataStore.put(bucket, key, objectMetadata)
7581
}
7682
override def getObject(bucket:String, key:String): GetObjectData = {

src/main/scala/io/findify/s3mock/provider/InMemoryProvider.scala

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package io.findify.s3mock.provider
22

3-
import java.util.UUID
3+
import java.time.Instant
4+
import java.util.{Date, UUID}
45

56
import akka.http.scaladsl.model.DateTime
67
import com.amazonaws.services.s3.model.ObjectMetadata
@@ -75,6 +76,7 @@ class InMemoryProvider extends Provider with LazyLogging {
7576
case Some(bucketContent) =>
7677
logger.debug(s"putting object for s3://$bucket/$key, bytes = ${data.length}")
7778
bucketContent.keysInBucket.put(key, KeyContents(DateTime.now, data))
79+
objectMetadata.setLastModified(org.joda.time.DateTime.now().toDate)
7880
metadataStore.put(bucket, key, objectMetadata)
7981
case None => throw NoSuchBucketException(bucket)
8082
}

src/main/scala/io/findify/s3mock/route/GetObject.scala

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package io.findify.s3mock.route
22

33
import java.io.StringWriter
44
import java.net.URLDecoder
5+
import java.util.Date
56

67
import akka.http.scaladsl.model.HttpEntity.Strict
78
import akka.http.scaladsl.model._
@@ -118,10 +119,15 @@ case class GetObject(implicit provider: Provider) extends LazyLogging {
118119
}
119120

120121
val headerBlacklist = Set("content-type", "connection")
121-
protected def metadataToHeaderList(metadata: ObjectMetadata): List[RawHeader] = {
122+
protected def metadataToHeaderList(metadata: ObjectMetadata): List[HttpHeader] = {
122123
val headers = Option(metadata.getRawMetadata)
123124
.map(_.asScala.toMap)
124-
.map(_.map { case (key, value) => RawHeader(key, value.toString)}.toList)
125+
.map(_.map {
126+
case (_, date: Date) =>
127+
`Last-Modified`(DateTime(new org.joda.time.DateTime(date).getMillis))
128+
case (key, value) =>
129+
RawHeader(key, value.toString)
130+
}.toList)
125131
.toList.flatten
126132
.filterNot(header => headerBlacklist.contains(header.lowercaseName))
127133

src/main/scala/io/findify/s3mock/route/ListBucket.scala

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
package io.findify.s3mock.route
22

3-
import akka.http.scaladsl.model.{HttpResponse, StatusCodes}
3+
import akka.http.scaladsl.model._
44
import akka.http.scaladsl.server.Directives._
55
import com.typesafe.scalalogging.LazyLogging
66
import io.findify.s3mock.error.{InternalErrorException, NoSuchBucketException}
@@ -17,16 +17,19 @@ case class ListBucket(implicit provider:Provider) extends LazyLogging {
1717
complete {
1818
logger.info(s"listing bucket $bucket with prefix=$prefix, delimiter=$delimiter")
1919
Try(provider.listBucket(bucket, prefix, delimiter, maxkeys.map(_.toInt))) match {
20-
case Success(l) => HttpResponse(StatusCodes.OK, entity = l.toXML.toString)
20+
case Success(l) => HttpResponse(
21+
StatusCodes.OK,
22+
entity = HttpEntity(ContentType(MediaTypes.`application/xml`, HttpCharsets.`UTF-8`), l.toXML.toString)
23+
)
2124
case Failure(e: NoSuchBucketException) =>
2225
HttpResponse(
2326
StatusCodes.NotFound,
24-
entity = e.toXML.toString()
27+
entity = HttpEntity(ContentType(MediaTypes.`application/xml`, HttpCharsets.`UTF-8`), e.toXML.toString)
2528
)
2629
case Failure(t) =>
2730
HttpResponse(
2831
StatusCodes.InternalServerError,
29-
entity = InternalErrorException(t).toXML.toString()
32+
entity = HttpEntity(ContentType(MediaTypes.`application/xml`, HttpCharsets.`UTF-8`), InternalErrorException(t).toXML.toString)
3033
)
3134
}
3235
}

src/main/scala/io/findify/s3mock/route/ListBuckets.scala

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
package io.findify.s3mock.route
22

3-
import akka.http.scaladsl.model.{HttpResponse, StatusCodes}
3+
import akka.http.scaladsl.model._
44
import akka.http.scaladsl.server.Directives._
55
import com.typesafe.scalalogging.LazyLogging
66
import io.findify.s3mock.provider.Provider
@@ -12,7 +12,10 @@ case class ListBuckets(implicit provider:Provider) extends LazyLogging {
1212
def route() = get {
1313
complete {
1414
logger.debug("listing all buckets")
15-
HttpResponse(StatusCodes.OK, entity = provider.listBuckets.toXML.toString)
15+
HttpResponse(
16+
StatusCodes.OK,
17+
entity = HttpEntity(ContentType(MediaTypes.`application/xml`, HttpCharsets.`UTF-8`), provider.listBuckets.toXML.toString)
18+
)
1619
}
1720
}
1821
}

0 commit comments

Comments
 (0)