s3_website 2.9.0 → 2.10.0
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 +4 -4
- data/README.md +9 -0
- data/changelog.md +4 -0
- data/lib/s3_website/version.rb +1 -1
- data/src/main/scala/s3/website/S3.scala +1 -1
- data/src/main/scala/s3/website/model/Config.scala +15 -1
- data/src/main/scala/s3/website/model/Site.scala +1 -1
- data/src/main/scala/s3/website/model/push.scala +23 -0
- data/src/test/scala/s3/website/S3WebsiteSpec.scala +50 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a869e0bbb5276a123020d7ae96f52d729d56b166
|
4
|
+
data.tar.gz: b6b51944723aaf3f1c22f949a56261137cc74dcc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2f3705e5c621c1b44225e8b3f7070496d59d258780f268b3d4183d709e5d988041d26d47a9a8bffdaac89d6f86c5b8e3caff99afafd18d1cfaa1f3cceb7ea99b
|
7
|
+
data.tar.gz: d13a8bd0492c4cc10e92bc4bd08ecf71eded8f0bac47ffa7bee15b9bd4909de2dcae7ce3e92d80aead594fcbe0eb13d747dc0fdf11517beb4f5b62397a5351f9
|
data/README.md
CHANGED
@@ -126,6 +126,15 @@ Here's an example:
|
|
126
126
|
cache_control: public, no-transform, max-age=1200, s-maxage=1200
|
127
127
|
```
|
128
128
|
|
129
|
+
You can also specify a hash of globs, and all files matching those globs will have
|
130
|
+
the specified cache-control string:
|
131
|
+
|
132
|
+
```yaml
|
133
|
+
cache_control:
|
134
|
+
"assets/*": public, max-age=3600
|
135
|
+
"*": no-cache, no-store
|
136
|
+
```
|
137
|
+
|
129
138
|
After changing the `cache_control` setting, push with the `--force` option.
|
130
139
|
Force-pushing allows you to update the S3 object metadata of existing files.
|
131
140
|
|
data/changelog.md
CHANGED
data/lib/s3_website/version.rb
CHANGED
@@ -72,7 +72,7 @@ object S3 {
|
|
72
72
|
md setContentLength uploadFile.length
|
73
73
|
md setContentType contentType
|
74
74
|
upload.encodingOnS3.map(_ => "gzip") foreach md.setContentEncoding
|
75
|
-
val cacheControl: Option[String] = (upload.maxAge,
|
75
|
+
val cacheControl: Option[String] = (upload.maxAge, upload.cacheControl) match {
|
76
76
|
case (maxAge: Some[Int], cacheCtrl: Some[String]) =>
|
77
77
|
logger.warn("Overriding the max_age setting with the cache_control setting")
|
78
78
|
cacheCtrl
|
@@ -15,7 +15,7 @@ case class Config(
|
|
15
15
|
s3_endpoint: S3Endpoint,
|
16
16
|
site: Option[String],
|
17
17
|
max_age: Option[Either[Int, Map[String, Int]]],
|
18
|
-
cache_control: Option[String],
|
18
|
+
cache_control: Option[Either[String, Map[String, String]]],
|
19
19
|
gzip: Option[Either[Boolean, Seq[String]]],
|
20
20
|
gzip_zopfli: Option[Boolean],
|
21
21
|
ignore_on_server: Option[Either[String, Seq[String]]],
|
@@ -83,6 +83,20 @@ object Config {
|
|
83
83
|
yamlValue getOrElse Left(ErrorReport(s"The key $key has to have an int or (string -> int) value"))
|
84
84
|
}
|
85
85
|
|
86
|
+
def loadCacheControl(implicit unsafeYaml: UnsafeYaml): Either[ErrorReport, Option[Either[String, Map[String, String]]]] = {
|
87
|
+
val key = "cache_control"
|
88
|
+
val yamlValue = for {
|
89
|
+
cacheControlOption <- loadOptionalValue(key)
|
90
|
+
} yield {
|
91
|
+
Right(cacheControlOption.map {
|
92
|
+
case cacheControl if cacheControl.isInstanceOf[String] => Left(cacheControl.asInstanceOf[String])
|
93
|
+
case cacheControl if cacheControl.isInstanceOf[java.util.Map[_,_]] => Right(cacheControl.asInstanceOf[java.util.Map[String,String]].toMap) // TODO an unsafe call to asInstanceOf
|
94
|
+
})
|
95
|
+
}
|
96
|
+
|
97
|
+
yamlValue getOrElse Left(ErrorReport(s"The key $key has to have a string or (string -> string) value"))
|
98
|
+
}
|
99
|
+
|
86
100
|
def loadEndpoint(implicit unsafeYaml: UnsafeYaml): Either[ErrorReport, Option[S3Endpoint]] =
|
87
101
|
loadOptionalString("s3_endpoint").right flatMap { endpointString =>
|
88
102
|
endpointString.map(S3Endpoint.forString) match {
|
@@ -40,7 +40,7 @@ object Site {
|
|
40
40
|
s3_endpoint <- loadEndpoint.right
|
41
41
|
site <- loadOptionalString("site").right
|
42
42
|
max_age <- loadMaxAge.right
|
43
|
-
cache_control <-
|
43
|
+
cache_control <- loadCacheControl.right
|
44
44
|
gzip <- loadOptionalBooleanOrStringSeq("gzip").right
|
45
45
|
gzip_zopfli <- loadOptionalBoolean("gzip_zopfli").right
|
46
46
|
extensionless_mime_type <- loadOptionalString("extensionless_mime_type").right
|
@@ -94,6 +94,29 @@ case class Upload(originalFile: File, uploadType: UploadType)(implicit site: Sit
|
|
94
94
|
}
|
95
95
|
}
|
96
96
|
|
97
|
+
lazy val cacheControl: Option[String] = {
|
98
|
+
type GlobsMap = Map[String, String]
|
99
|
+
site.config.cache_control.flatMap { (intOrGlobs: Either[String, GlobsMap]) =>
|
100
|
+
type GlobsSeq = Seq[(String, String)]
|
101
|
+
def respectMostSpecific(globs: GlobsMap): GlobsSeq = globs.toSeq.sortBy(_._1.length).reverse
|
102
|
+
intOrGlobs
|
103
|
+
.right.map(respectMostSpecific)
|
104
|
+
.fold(
|
105
|
+
(cacheCtrl: String) => Some(cacheCtrl),
|
106
|
+
(globs: GlobsSeq) => {
|
107
|
+
val matchingCacheControl = (glob: String, cacheControl: String) =>
|
108
|
+
rubyRuntime.evalScriptlet(
|
109
|
+
s"""|# encoding: utf-8
|
110
|
+
|File.fnmatch('$glob', "$s3Key")""".stripMargin)
|
111
|
+
.toJava(classOf[Boolean])
|
112
|
+
.asInstanceOf[Boolean]
|
113
|
+
val fileGlobMatch = globs find Function.tupled(matchingCacheControl)
|
114
|
+
fileGlobMatch map (_._2)
|
115
|
+
}
|
116
|
+
)
|
117
|
+
}
|
118
|
+
}
|
119
|
+
|
97
120
|
/**
|
98
121
|
* May throw an exception, so remember to call this in a Try or Future monad
|
99
122
|
*/
|
@@ -507,6 +507,56 @@ class S3WebsiteSpec extends Specification {
|
|
507
507
|
))
|
508
508
|
logEntries must contain("[\u001B[33mwarn\u001B[0m] Overriding the max_age setting with the cache_control settin")
|
509
509
|
}
|
510
|
+
|
511
|
+
"supports all valid URI characters in the glob setting" in new BasicSetup {
|
512
|
+
config = """
|
513
|
+
|cache_control:
|
514
|
+
| "*.html": public, max-age=120
|
515
|
+
""".stripMargin
|
516
|
+
val allValidUrlCharacters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~:/?#[]@!$&'()*+,;=" // See http://stackoverflow.com/a/1547940/990356 for discussion
|
517
|
+
setLocalFile(s"$allValidUrlCharacters.html")
|
518
|
+
push()
|
519
|
+
sentPutObjectRequest.getMetadata.getCacheControl must equalTo("public, max-age=120")
|
520
|
+
}
|
521
|
+
|
522
|
+
"be applied to files that match the glob" in new BasicSetup {
|
523
|
+
config = """
|
524
|
+
|cache_control:
|
525
|
+
| "*.html": no-store
|
526
|
+
""".stripMargin
|
527
|
+
setLocalFile("index.html")
|
528
|
+
push()
|
529
|
+
sentPutObjectRequest.getMetadata.getCacheControl must equalTo("no-store")
|
530
|
+
}
|
531
|
+
|
532
|
+
"be applied to directories that match the glob" in new BasicSetup {
|
533
|
+
config = """
|
534
|
+
|cache_control:
|
535
|
+
| "assets/**/*.js": no-cache, no-store
|
536
|
+
""".stripMargin
|
537
|
+
setLocalFile("assets/lib/jquery.js")
|
538
|
+
push()
|
539
|
+
sentPutObjectRequest.getMetadata.getCacheControl must equalTo("no-cache, no-store")
|
540
|
+
}
|
541
|
+
|
542
|
+
"not be applied if the glob doesn't match" in new BasicSetup {
|
543
|
+
config = """
|
544
|
+
|cache_control:
|
545
|
+
| "*.js": max-age=120
|
546
|
+
""".stripMargin
|
547
|
+
setLocalFile("index.html")
|
548
|
+
push()
|
549
|
+
sentPutObjectRequest.getMetadata.getCacheControl must beNull
|
550
|
+
}
|
551
|
+
|
552
|
+
"support non-US-ASCII directory names" in new BasicSetup {
|
553
|
+
config = """
|
554
|
+
|cache_control:
|
555
|
+
| "*": no-cache
|
556
|
+
""".stripMargin
|
557
|
+
setLocalFile("tags/笔记/index.html")
|
558
|
+
push() must equalTo(0)
|
559
|
+
}
|
510
560
|
}
|
511
561
|
|
512
562
|
"cache control" can {
|
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.
|
4
|
+
version: 2.10.0
|
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-06-
|
11
|
+
date: 2015-06-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: thor
|