Changeset 13778 in josm
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/org/openstreetmap/josm/data/cache/JCSCachedTileLoaderJob.java
r13733 r13778 437 437 CacheEntryAttributes ret = new CacheEntryAttributes(); 438 438 439 Long lng = urlConn.getExpiration(); 440 if (lng.equals(0L)) { 441 try { 442 String str = urlConn.getHeaderField("Cache-Control"); 443 if (str != null) { 444 for (String token: str.split(",")) { 445 if (token.startsWith("max-age=")) { 446 lng = TimeUnit.SECONDS.toMillis(Long.parseLong(token.substring(8))) + System.currentTimeMillis(); 447 } 439 /* 440 * according to https://www.ietf.org/rfc/rfc2616.txt Cache-Control takes precedence over max-age 441 * max-age is for private caches, s-max-age is for shared caches. We take any value that is larger 442 */ 443 Long expiration = 0L; 444 String cacheControl = urlConn.getHeaderField("Cache-Control"); 445 if (cacheControl != null) { 446 for (String token: cacheControl.split(",")) { 447 try { 448 if (token.startsWith("max-age=")) { 449 expiration = Math.max(expiration, 450 TimeUnit.SECONDS.toMillis(Long.parseLong(token.substring("max-age=".length()))) 451 + System.currentTimeMillis() 452 ); 448 453 } 454 if (token.startsWith("s-max-age=")) { 455 expiration = Math.max(expiration, 456 TimeUnit.SECONDS.toMillis(Long.parseLong(token.substring("s-max-age=".length()))) 457 + System.currentTimeMillis() 458 ); 459 } 460 } catch (NumberFormatException e) { 461 // ignore malformed Cache-Control headers 462 Logging.trace(e); 449 463 } 450 } catch (NumberFormatException e) { 451 // ignore malformed Cache-Control headers 452 Logging.trace(e); 453 } 454 if (lng.equals(0L)) { 455 lng = System.currentTimeMillis() + DEFAULT_EXPIRE_TIME; 456 } 457 } 458 459 ret.setExpirationTime(Math.max(minimumExpiryTime + System.currentTimeMillis(), lng)); 464 } 465 } 466 467 if (expiration.equals(0L)) { 468 expiration = urlConn.getExpiration(); 469 } 470 471 // if nothing is found - set default 472 if (expiration.equals(0L)) { 473 expiration = System.currentTimeMillis() + DEFAULT_EXPIRE_TIME; 474 } 475 476 ret.setExpirationTime(Math.max(minimumExpiryTime + System.currentTimeMillis(), expiration)); 460 477 ret.setLastModification(now); 461 478 ret.setEtag(urlConn.getHeaderField("ETag")); -
trunk/test/unit/org/openstreetmap/josm/data/cache/JCSCachedTileLoaderJobTest.java
r13742 r13778 353 353 354 354 /** 355 * Check if Cache-Control takes precedence over max-age 356 * Expires is lower - JCSCachedTileLoaderJob.DEFAULT_EXPIRE_TIME / 10 357 * Cache control : JCSCachedTileLoaderJob.DEFAULT_EXPIRE_TIME / 2 358 * 359 * Both are smaller than DEFAULT_EXPIRE_TIME, so we can test, that it's not DEFAULT_EXPIRE_TIME that extended 360 * expiration 361 * 362 * @throws IOException exception 363 */ 364 365 @Test 366 public void testCacheControlVsExpires() throws IOException { 367 long testStart = System.currentTimeMillis(); 368 int minimumExpiryTimeSeconds = 0; 369 370 tileServer.stubFor( 371 WireMock.get(WireMock.urlEqualTo("/test")) 372 .willReturn(WireMock.aResponse() 373 .withHeader("Expires", TestUtils.getHTTPDate(testStart + (JCSCachedTileLoaderJob.DEFAULT_EXPIRE_TIME / 10))) 374 .withHeader("Cache-Control", "max-age=" + TimeUnit.MILLISECONDS.toSeconds((JCSCachedTileLoaderJob.DEFAULT_EXPIRE_TIME / 2))) 375 .withBody("mock entry") 376 ) 377 ); 378 tileServer.stubFor( 379 WireMock.head(WireMock.urlEqualTo("/test")) 380 .willReturn(WireMock.aResponse() 381 .withHeader("Expires", TestUtils.getHTTPDate(testStart + (JCSCachedTileLoaderJob.DEFAULT_EXPIRE_TIME / 10))) 382 .withHeader("Cache-Control", "max-age=" + TimeUnit.MILLISECONDS.toSeconds((JCSCachedTileLoaderJob.DEFAULT_EXPIRE_TIME / 2))) 383 ) 384 ); 385 TestCachedTileLoaderJob job = new TestCachedTileLoaderJob(tileServer.url("/test"), "test", minimumExpiryTimeSeconds); 386 Listener listener = submitJob(job, false); 387 tileServer.verify(1, WireMock.getRequestedFor(WireMock.urlEqualTo("/test"))); 388 assertArrayEquals("mock entry".getBytes(StandardCharsets.UTF_8), listener.data); 389 390 391 assertTrue("Cache entry expiration is " + (listener.attributes.getExpirationTime() - testStart) + " which is not larger than " + 392 (JCSCachedTileLoaderJob.DEFAULT_EXPIRE_TIME / 10) + " (Expires header)", 393 listener.attributes.getExpirationTime() >= testStart + (JCSCachedTileLoaderJob.DEFAULT_EXPIRE_TIME / 10)); 394 395 assertTrue("Cache entry expiration is " + 396 (listener.attributes.getExpirationTime() - System.currentTimeMillis()) + 397 " which is not less than " + 398 (JCSCachedTileLoaderJob.DEFAULT_EXPIRE_TIME / 2) + " (Cache-Control: max-age=)", 399 listener.attributes.getExpirationTime() <= System.currentTimeMillis() + (JCSCachedTileLoaderJob.DEFAULT_EXPIRE_TIME / 2) 400 ); 401 } 402 403 /** 404 * Check if Cache-Control s-max-age is honored 405 * mock returns expiration: JCSCachedTileLoaderJob.DEFAULT_EXPIRE_TIME / 10 406 * minimum expire time: JCSCachedTileLoaderJob.DEFAULT_EXPIRE_TIME * 2 407 * 408 * @throws IOException exception 409 */ 410 411 @Test 412 public void testMaxAgeVsSMaxAge() throws IOException { 413 long testStart = System.currentTimeMillis(); 414 int minimumExpiryTimeSeconds = 0; 415 416 417 tileServer.stubFor( 418 WireMock.get(WireMock.urlEqualTo("/test")) 419 .willReturn(WireMock.aResponse() 420 .withHeader("Cache-Control", "" + 421 "max-age=" + TimeUnit.MILLISECONDS.toSeconds((JCSCachedTileLoaderJob.DEFAULT_EXPIRE_TIME / 10)) + "," + 422 "s-max-age=" + TimeUnit.MILLISECONDS.toSeconds((JCSCachedTileLoaderJob.DEFAULT_EXPIRE_TIME / 2)) 423 ) 424 .withBody("mock entry") 425 ) 426 ); 427 tileServer.stubFor( 428 WireMock.head(WireMock.urlEqualTo("/test")) 429 .willReturn(WireMock.aResponse() 430 .withHeader("Cache-Control", "" + 431 "max-age=" + TimeUnit.MILLISECONDS.toSeconds((JCSCachedTileLoaderJob.DEFAULT_EXPIRE_TIME / 10)) + "," + 432 "s-max-age=" + TimeUnit.MILLISECONDS.toSeconds((JCSCachedTileLoaderJob.DEFAULT_EXPIRE_TIME / 2)) 433 ) 434 )); 435 TestCachedTileLoaderJob job = new TestCachedTileLoaderJob(tileServer.url("/test"), "test", minimumExpiryTimeSeconds); 436 Listener listener = submitJob(job, false); 437 tileServer.verify(1, WireMock.getRequestedFor(WireMock.urlEqualTo("/test"))); 438 assertArrayEquals("mock entry".getBytes(StandardCharsets.UTF_8), listener.data); 439 440 441 assertTrue("Cache entry expiration is " + (listener.attributes.getExpirationTime() - testStart) + " which is not larger than " + 442 (JCSCachedTileLoaderJob.DEFAULT_EXPIRE_TIME / 10) + " (Cache-Control: max-age)", 443 listener.attributes.getExpirationTime() >= testStart + (JCSCachedTileLoaderJob.DEFAULT_EXPIRE_TIME / 10)); 444 445 assertTrue("Cache entry expiration is " + 446 (listener.attributes.getExpirationTime() - System.currentTimeMillis()) + 447 " which is not less than " + 448 (JCSCachedTileLoaderJob.DEFAULT_EXPIRE_TIME / 2) + " (Cache-Control: s-max-age)", 449 listener.attributes.getExpirationTime() <= System.currentTimeMillis() + (JCSCachedTileLoaderJob.DEFAULT_EXPIRE_TIME / 2) 450 ); 451 } 452 453 454 /** 355 455 * Check if verifying cache entries using HEAD requests work properly 356 456 * @throws IOException exception
Note:
See TracChangeset
for help on using the changeset viewer.