s3_website 2.8.3 → 2.8.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 3ef96125c6a73593af5f5fad43964ec7f968511f
4
- data.tar.gz: 883d27f9ee3ae528c4d3e76478740c66f56734c5
3
+ metadata.gz: 3eb61e148cba2a736188f4722ffe0f83c880c3e6
4
+ data.tar.gz: 18d990870b6d1f84c41517ee3fdc84e3cb2d8d8f
5
5
  SHA512:
6
- metadata.gz: 183d2e3a0644fc60ca90b045bd74101601e5e6b182a348e5e55b68d3df6090ed81671cf921126e97659ee6fc81b6f384bd861cd160f4d9b1b82403d1e6b220e5
7
- data.tar.gz: 2580cfc91f7a99ec584d826b1677b87afcb2f90407074a318b02568ae7ed55153849d35d554bb981fba4ea6fdc6ad04d0600cda235753ba7157da8e4af7f11ba
6
+ metadata.gz: d9b477c47017a4c3d53c06201f473f595ece6bd1e656405907b3c4cbb1f79475e02c397ffae1d67c92a2b6770d7b68cf8e3eecbc2d7a9726e48ee974f4b8b41d
7
+ data.tar.gz: e97b944a26585749bef90578ec657d9dff4b40835cdfa1cdb177f937ef5cc0e029a9905ccc965111b78a42a7637e3f1e2e2f4d4f49dc4b4426f1c48cda81b9bf
data/changelog.md CHANGED
@@ -2,6 +2,14 @@
2
2
 
3
3
  This project uses [Semantic Versioning](http://semver.org).
4
4
 
5
+ ## 2.8.4
6
+
7
+ * URL encude ' in invalidation path
8
+
9
+ See <https://github.com/laurilehmijoki/s3_website/issues/63> for discussion.
10
+
11
+ * Accept ' in `exclude_from_upload` and `ignore_on_server`
12
+
5
13
  ## 2.8.3
6
14
 
7
15
  * Fix bug where the setting `cloudfront_invalidate_root: true` resulted in a
@@ -1,3 +1,3 @@
1
1
  module S3Website
2
- VERSION = '2.8.3'
2
+ VERSION = '2.8.4'
3
3
  end
@@ -8,7 +8,7 @@ import scala.collection.JavaConversions._
8
8
  import scala.concurrent.duration._
9
9
  import s3.website.S3.{SuccessfulDelete, PushSuccessReport, SuccessfulUpload}
10
10
  import com.amazonaws.auth.BasicAWSCredentials
11
- import java.net.URI
11
+ import java.net.{URLEncoder, URI}
12
12
  import scala.concurrent.{ExecutionContextExecutor, Future}
13
13
  import s3.website.model.Config.awsCredentials
14
14
 
@@ -68,29 +68,34 @@ object CloudFront {
68
68
  def awsCloudFrontClient(config: Config) = new AmazonCloudFrontClient(awsCredentials(config))
69
69
 
70
70
  def toInvalidationBatches(pushSuccessReports: Seq[PushSuccessReport])(implicit config: Config): Seq[InvalidationBatch] = {
71
+ def defaultPath(paths: Seq[String]): Option[String] = {
72
+ // This is how we support the Default Root Object @ CloudFront (http://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/DefaultRootObject.html)
73
+ // We could do this more accurately by fetching the distribution config (http://docs.aws.amazon.com/AmazonCloudFront/latest/APIReference/GetConfig.html)
74
+ // and reading the Default Root Object from there.
75
+ val containsPotentialDefaultRootObject = paths
76
+ .exists(
77
+ _
78
+ .replaceFirst("^/", "") // S3 keys do not begin with a slash
79
+ .contains("/") == false // See if the S3 key is a top-level key (i.e., it is not within a directory)
80
+ )
81
+ if (containsPotentialDefaultRootObject) Some("/") else None
82
+ }
83
+ val indexPath = config.cloudfront_invalidate_root collect {
84
+ case true if pushSuccessReports.nonEmpty => "/index.html"
85
+ }
86
+
71
87
  val invalidationPaths: Seq[String] = {
72
- def withDefaultPathIfNeeded(paths: Seq[String]) = {
73
- // This is how we support the Default Root Object @ CloudFront (http://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/DefaultRootObject.html)
74
- // We do this more accurately by fetching the distribution config (http://docs.aws.amazon.com/AmazonCloudFront/latest/APIReference/GetConfig.html)
75
- // and reading the Default Root Object from there.
76
- val containsPotentialDefaultRootObject = paths
77
- .exists(
78
- _
79
- .replaceFirst("^/", "") // S3 keys do not begin with a slash
80
- .contains("/") == false // See if the S3 key is a top-level key (i.e., it is not within a directory)
81
- )
82
- if (containsPotentialDefaultRootObject) paths :+ "/" else paths
83
- }
84
- def withIndexPathIfNeeded(paths: Seq[String]) =
85
- if (config.cloudfront_invalidate_root.contains(true) && pushSuccessReports.nonEmpty)
86
- paths :+ "/index.html"
87
- else
88
- paths
89
88
  val paths = pushSuccessReports
90
- .filter(needsInvalidation) // Assume that redirect objects are never cached.
89
+ .filter(needsInvalidation)
91
90
  .map(toInvalidationPath)
91
+ .map(encodeUnsafeChars)
92
92
  .map(applyInvalidateRootSetting)
93
- withIndexPathIfNeeded(withDefaultPathIfNeeded(paths))
93
+
94
+ val extraPathItems = defaultPath(paths) :: indexPath :: Nil collect {
95
+ case Some(path) => path
96
+ }
97
+
98
+ paths ++ extraPathItems
94
99
  }
95
100
 
96
101
  invalidationPaths
@@ -109,17 +114,11 @@ object CloudFront {
109
114
  else
110
115
  path
111
116
 
112
- def toInvalidationPath(report: PushSuccessReport) = {
113
- def encodeUnsafeChars(path: String) =
114
- new URI(
115
- "http",
116
- "cloudfront", // We want to use the encoder in the URI class. These must be passed in.
117
- "/" + report.s3Key, // CloudFront keys have the slash in front
118
- path
119
- ).toURL.getPath // The URL class encodes the unsafe characters
120
- val invalidationPath = "/" + report.s3Key // CloudFront keys have the slash in front
121
- encodeUnsafeChars(invalidationPath)
122
- }
117
+ def toInvalidationPath(report: PushSuccessReport) = "/" + report.s3Key
118
+
119
+ def encodeUnsafeChars(invalidationPath: String) =
120
+ new URI("http", "cloudfront", invalidationPath, "").toURL.getPath
121
+ .replaceAll("'", URLEncoder.encode("'", "UTF-8")) // CloudFront does not accept ' in invalidation path
123
122
 
124
123
 
125
124
  def needsInvalidation: PartialFunction[PushSuccessReport, Boolean] = {
@@ -6,7 +6,7 @@ object Ruby {
6
6
  def rubyRegexMatches(text: String, regex: String) = {
7
7
  val z = rubyRuntime.evalScriptlet(
8
8
  s"""# encoding: utf-8
9
- !!Regexp.new('$regex').match('$text')"""
9
+ !!Regexp.new("$regex").match("$text")"""
10
10
  )
11
11
  z.toJava(classOf[Boolean]).asInstanceOf[Boolean]
12
12
  }
@@ -204,7 +204,7 @@ class S3WebsiteSpec extends Specification {
204
204
  setLocalFile("articles/arnold's file.html")
205
205
  setOutdatedS3Keys("articles/arnold's file.html")
206
206
  push()
207
- sentInvalidationRequest.getInvalidationBatch.getPaths.getItems.toSeq.sorted must equalTo(("/articles/arnold's%20file.html" :: Nil).sorted)
207
+ sentInvalidationRequest.getInvalidationBatch.getPaths.getItems.toSeq.sorted must equalTo(("/articles/arnold%27s%20file.html" :: Nil).sorted)
208
208
  }
209
209
 
210
210
  "invalidate the root object '/' if a top-level object is updated or deleted" in new BasicSetup {
@@ -0,0 +1,11 @@
1
+ package s3.website
2
+
3
+ import org.specs2.mutable.Specification
4
+
5
+ class UnitTest extends Specification {
6
+ "rubyRegexMatches" should {
7
+ "accept valid URL characters" in {
8
+ Ruby.rubyRegexMatches("arnold's file.txt", ".txt") must beTrue
9
+ }
10
+ }
11
+ }
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: s3_website
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.8.3
4
+ version: 2.8.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Lauri Lehmijoki
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-02-22 00:00:00.000000000 Z
11
+ date: 2015-03-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: thor
@@ -142,6 +142,7 @@ files:
142
142
  - src/main/scala/s3/website/package.scala
143
143
  - src/test/scala/s3/website/AwsSdkSpec.scala
144
144
  - src/test/scala/s3/website/S3WebsiteSpec.scala
145
+ - src/test/scala/s3/website/UnitTest.scala
145
146
  - vagrant/Vagrantfile
146
147
  homepage: https://github.com/laurilehmijoki/s3_website
147
148
  licenses:
@@ -170,3 +171,4 @@ summary: Manage your S3 website
170
171
  test_files:
171
172
  - src/test/scala/s3/website/AwsSdkSpec.scala
172
173
  - src/test/scala/s3/website/S3WebsiteSpec.scala
174
+ - src/test/scala/s3/website/UnitTest.scala