Skip to content

Commit 452e6df

Browse files
committed
Merge pull request #362 from authchir/master
Refactor `AssetHandler` according to issue #356
2 parents 64e4c5a + e3a7648 commit 452e6df

10 files changed

Lines changed: 107 additions & 94 deletions

File tree

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
package org.jooby.issues;
2+
3+
import java.time.Duration;
4+
5+
import org.jooby.handlers.AssetHandler;
6+
import org.jooby.test.ServerFeature;
7+
8+
import static org.junit.Assert.assertNotNull;
9+
import static org.junit.Assert.assertNull;
10+
import static org.junit.Assert.assertTrue;
11+
12+
import org.junit.Assert;
13+
import org.junit.Test;
14+
15+
public class Issue356 extends ServerFeature {
16+
{
17+
assets("/assets/file.css", new AssetHandler("/")
18+
.etag(false).lastModified(false).maxAge(Duration.ofDays(1)));
19+
20+
assets("/assets/favicon.ico", new AssetHandler("/")
21+
.etag(false).lastModified(true).maxAge(Duration.ofDays(14)));
22+
23+
assets("/assets/file.js", new AssetHandler("/")
24+
.etag(true).lastModified(false).maxAge(Duration.ofDays(2)));
25+
26+
assets("/assets/empty.css", new AssetHandler("/")
27+
.etag(true).lastModified(true).maxAge(Duration.ofDays(7)));
28+
}
29+
30+
@Test
31+
public void etag() throws Exception {
32+
request().get("/assets/file.css").execute().header("ETag", Assert::assertNull);
33+
request().get("/assets/favicon.ico").execute().header("ETag", Assert::assertNull);
34+
request().get("/assets/file.js").execute().header("ETag", Assert::assertNotNull);
35+
request().get("/assets/empty.css").execute().header("ETag", Assert::assertNotNull);
36+
}
37+
38+
@Test
39+
public void lastModified() throws Exception {
40+
request().get("/assets/file.css").execute().header("Last-Modified", Assert::assertNull);
41+
request().get("/assets/favicon.ico").execute().header("Last-Modified", Assert::assertNotNull);
42+
request().get("/assets/file.js").execute().header("Last-Modified", Assert::assertNull);
43+
request().get("/assets/empty.css").execute().header("Last-Modified", Assert::assertNotNull);
44+
}
45+
46+
@Test
47+
public void maxAge() throws Exception {
48+
request().get("/assets/file.css").execute().header("Cache-Control", value -> {
49+
assertNotNull(value);
50+
assertTrue(value.contains("max-age=86400"));
51+
});
52+
request().get("/assets/favicon.ico").execute().header("Cache-Control", value -> {
53+
assertNotNull(value);
54+
assertTrue(value.contains("max-age=1209600"));
55+
});
56+
request().get("/assets/file.js").execute().header("Cache-Control", value -> {
57+
assertNotNull(value);
58+
assertTrue(value.contains("max-age=172800"));
59+
});
60+
request().get("/assets/empty.css").execute().header("Cache-Control", value -> {
61+
assertNotNull(value);
62+
assertTrue(value.contains("max-age=604800"));
63+
});
64+
}
65+
}

jooby-assets/src/main/java/org/jooby/assets/Assets.java

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@
1818
*/
1919
package org.jooby.assets;
2020

21-
import java.util.concurrent.TimeUnit;
21+
import java.time.Duration;
22+
import java.util.Optional;
2223

2324
import org.jooby.Env;
2425
import org.jooby.Jooby;
@@ -266,8 +267,11 @@ public void configure(final Env env, final Config config, final Binder binder) {
266267
: new AssetHandler("/")
267268
.etag(conf.getBoolean("assets.etag"))
268269
.cdn(conf.getString("assets.cdn"))
269-
.lastModified(conf.getBoolean("assets.lastModified"))
270-
.maxAge(conf.getDuration("assets.cache.maxAge", TimeUnit.SECONDS));
270+
.lastModified(conf.getBoolean("assets.lastModified"));
271+
272+
if (conf.hasPath("assets.cache.maxAge")) {
273+
handler.maxAge(Duration.parse(conf.getString("assets.cache.maxAge")));
274+
}
271275

272276
compiler.patterns().forEach(
273277
pattern -> routes.addBinding()

jooby-assets/src/test/java/org/jooby/assets/AssetsTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ public void configuredist() throws Exception {
182182
.withValue("assets.etag", ConfigValueFactory.fromAnyRef(true))
183183
.withValue("application.path", ConfigValueFactory.fromAnyRef("/"))
184184
.withValue("assets.cdn", ConfigValueFactory.fromAnyRef(""))
185-
.withValue("assets.cache.maxAge", ConfigValueFactory.fromAnyRef("365d"))
185+
.withValue("assets.cache.maxAge", ConfigValueFactory.fromAnyRef("P365D"))
186186
.withValue("assets.lastModified", ConfigValueFactory.fromAnyRef(true))
187187
.withValue("assets.watch", ConfigValueFactory.fromAnyRef(false));
188188
new MockUnit(Env.class, Config.class, Binder.class, Request.class, Response.class,

jooby/src/main/java/org/jooby/Jooby.java

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,6 @@
9191
import org.jooby.Session.Store;
9292
import org.jooby.handlers.AssetHandler;
9393
import org.jooby.internal.AppPrinter;
94-
import org.jooby.internal.AssetProxy;
9594
import org.jooby.internal.BuiltinParser;
9695
import org.jooby.internal.BuiltinRenderer;
9796
import org.jooby.internal.DefaulErrRenderer;
@@ -3033,7 +3032,14 @@ public Route.Definition assets(final String path) {
30333032
*/
30343033
@Override
30353034
public Route.Definition assets(final String path, final String location) {
3036-
return assets(path, new AssetHandler(location));
3035+
AssetHandler handler = new AssetHandler(location);
3036+
on("*", conf -> {
3037+
handler
3038+
.cdn(conf.getString("assets.cdn"))
3039+
.lastModified(conf.getBoolean("assets.lastModified"))
3040+
.etag(conf.getBoolean("assets.etag"));
3041+
});
3042+
return assets(path, handler);
30373043
}
30383044

30393045
/**
@@ -3080,16 +3086,7 @@ public Route.Definition assets(final String path, final String location) {
30803086
*/
30813087
@Override
30823088
public Route.Definition assets(final String path, final AssetHandler handler) {
3083-
3084-
AssetProxy router = new AssetProxy();
3085-
Route.Definition asset = new Route.Definition("GET", path, router);
3086-
on("*", conf -> {
3087-
router.fwd(handler
3088-
.cdn(conf.getString("assets.cdn"))
3089-
.lastModified(conf.getBoolean("assets.lastModified"))
3090-
.etag(conf.getBoolean("assets.etag")));
3091-
});
3092-
return appendDefinition(asset);
3089+
return appendDefinition(new Route.Definition("GET", path, handler));
30933090
}
30943091

30953092
/**

jooby/src/main/java/org/jooby/Route.java

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@
3636
import java.util.Set;
3737
import java.util.stream.Collectors;
3838

39-
import org.jooby.internal.AssetProxy;
4039
import org.jooby.internal.DeferredExecution;
4140
import org.jooby.internal.RouteImpl;
4241
import org.jooby.internal.RouteMatcher;
@@ -1333,11 +1332,8 @@ public String toString() {
13331332
*/
13341333
private Route asRoute(final String method, final RouteMatcher matcher,
13351334
final List<MediaType> produces) {
1336-
Route.Filter filter = this.filter;
1337-
if (filter instanceof AssetProxy) {
1338-
filter = ((AssetProxy) filter).delegate();
1339-
}
1340-
return new RouteImpl(filter, this, method, matcher.path(), produces, matcher.vars(), mapper);
1335+
return new RouteImpl(filter, this, method, matcher.path(), produces,
1336+
matcher.vars(), mapper);
13411337
}
13421338

13431339
}

jooby/src/main/java/org/jooby/handlers/AssetHandler.java

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,10 @@
2525
import java.net.URL;
2626
import java.net.URLClassLoader;
2727
import java.text.MessageFormat;
28+
import java.time.Duration;
2829
import java.util.Date;
2930
import java.util.Map;
31+
import java.util.Optional;
3032

3133
import org.jooby.Asset;
3234
import org.jooby.Jooby;
@@ -92,7 +94,7 @@ public class AssetHandler implements Route.Handler {
9294

9395
private boolean etag = true;
9496

95-
private long maxAge = -1;
97+
private Optional<Duration> maxAgeOpt = Optional.empty();
9698

9799
private boolean lastModified = true;
98100

@@ -184,12 +186,21 @@ public AssetHandler cdn(final String cdn) {
184186
return this;
185187
}
186188

189+
/**
190+
* @param maxAge Set the cache header max-age value.
191+
* @return This handler.
192+
*/
193+
public AssetHandler maxAge(final Duration maxAge) {
194+
this.maxAgeOpt = Optional.of(maxAge);
195+
return this;
196+
}
197+
187198
/**
188199
* @param maxAge Set the cache header max-age value in seconds.
189200
* @return This handler.
190201
*/
191202
public AssetHandler maxAge(final long maxAge) {
192-
this.maxAge = maxAge;
203+
this.maxAgeOpt = Optional.of(Duration.ofSeconds(maxAge));
193204
return this;
194205
}
195206

@@ -253,9 +264,9 @@ private void doHandle(final Request req, final Response rsp, final Asset asset)
253264
}
254265

255266
// cache max-age
256-
if (maxAge > 0) {
257-
rsp.header("Cache-Control", "max-age=" + maxAge);
258-
}
267+
maxAgeOpt.ifPresent(d -> {
268+
rsp.header("Cache-Control", "max-age=" + d.getSeconds());
269+
});
259270

260271
send(req, rsp, asset);
261272
}

jooby/src/main/java/org/jooby/internal/AssetProxy.java

Lines changed: 0 additions & 44 deletions
This file was deleted.

jooby/src/main/resources/org/jooby/jooby.conf

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,8 @@ assets {
153153

154154
charset = ${application.charset}
155155

156-
cache.maxAge = -1
156+
# Either null or a string in the ISO 8601 format according to `java.time.Duration.parse(CharSequence)`.
157+
cache.maxAge = null
157158

158159
}
159160

jooby/src/test/java/org/jooby/internal/AssetProxyTest.java

Lines changed: 0 additions & 20 deletions
This file was deleted.

jooby/src/test/java/org/jooby/test/Client.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ public Request(final Client server, final Executor executor,
7272
this.req = req;
7373
}
7474

75-
private Response execute() throws Exception {
75+
public Response execute() throws Exception {
7676
this.rsp = executor.execute(req).returnResponse();
7777
return new Response(server, rsp);
7878
}
@@ -252,7 +252,10 @@ public Response header(final String headerName, final Optional<Object> headerVal
252252
}
253253

254254
public Response header(final String headerName, final Callback callback) throws Exception {
255-
callback.execute(rsp.getFirstHeader(headerName).getValue());
255+
callback.execute(
256+
Optional.ofNullable(rsp.getFirstHeader(headerName))
257+
.map(Header::getValue)
258+
.orElse(null));
256259
return this;
257260
}
258261

0 commit comments

Comments
 (0)