s3_website 2.8.3 → 2.8.4

Sign up to get free protection for your applications and to get access to all the features.
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