-
-
Notifications
You must be signed in to change notification settings - Fork 4.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Last-Modified HTTP header of assets contained in jar is wrong when using sbt >= 1.4.0 #10572
Comments
Fixes sbt#6235 In sbt 1.4.0 (sbt#5344) we started wiping out the timestamps in JAR to make the builds more repeatable. This had an unintended consequence of breaking Play's last-modified response header (playframework/playframework#10572). This adds an opt-out from the default: ```scala Compile / packageBin / packageOptions += Package.keepTimestamps ``` ### before ``` $ ll example total 32 -rw-r--r-- 1 eed3si9n wheel 901 Jan 1 1970 Greeting.class -rw-r--r-- 1 eed3si9n wheel 3079 Jan 1 1970 Hello$.class -rw-r--r-- 1 eed3si9n wheel 738 Jan 1 1970 Hello$delayedInit$body.class -rw-r--r-- 1 eed3si9n wheel 875 Jan 1 1970 Hello.class ``` ### after ``` $ ll target/scala-2.13/hello_2.13-0.1.0-SNAPSHOT/example total 32 -rwxr-xr-x 1 eed3si9n wheel 901 Jan 3 12:20 Greeting.class* -rwxr-xr-x 1 eed3si9n wheel 3079 Jan 3 12:20 Hello$.class* -rwxr-xr-x 1 eed3si9n wheel 738 Jan 3 12:20 Hello$delayedInit$body.class* -rwxr-xr-x 1 eed3si9n wheel 875 Jan 3 12:20 Hello.class* ```
To add some context, I think it was me that provided this functionality in Play many moons ago. Assets can of course be provided as Webjars. The date of the webjar is therefore important. My memory on this is vague though. |
…mmitDate Fixes sbt#6235 In sbt 1.4.0 (sbt#5344) we started wiping out the timestamps in JAR to make the builds more repeatable. This had an unintended consequence of breaking Play's last-modified response header (playframework/playframework#10572). This adds an opt-out from the default: ```scala ThisBuild / packageOptions += Package.keepTimestamps ``` Before ------ ``` $ ll example total 32 -rw-r--r-- 1 eed3si9n wheel 901 Jan 1 1970 Greeting.class -rw-r--r-- 1 eed3si9n wheel 3079 Jan 1 1970 Hello$.class -rw-r--r-- 1 eed3si9n wheel 738 Jan 1 1970 Hello$delayedInit$body.class -rw-r--r-- 1 eed3si9n wheel 875 Jan 1 1970 Hello.class ``` After ----- ``` $ ll target/scala-2.13/hello_2.13-0.1.0-SNAPSHOT/example total 32 -rwxr-xr-x 1 eed3si9n wheel 901 Jan 3 12:20 Greeting.class* -rwxr-xr-x 1 eed3si9n wheel 3079 Jan 3 12:20 Hello$.class* -rwxr-xr-x 1 eed3si9n wheel 738 Jan 3 12:20 Hello$delayedInit$body.class* -rwxr-xr-x 1 eed3si9n wheel 875 Jan 3 12:20 Hello.class* ```
Fixes sbt#6235 In sbt 1.4.0 (sbt#5344) we started wiping out the timestamps in JAR to make the builds more repeatable. This had an unintended consequence of breaking Play's last-modified response header (playframework/playframework#10572). This adds a global setting called `packageTimestamp`, which is initialized as follows: ```scala packageTimestamp :== Package.defaultTimestamp, ``` Here the `Package.defaultTimestamp` would pick either the value from the `SOURCE_DATE_EPOCH` environment variable or 2010-01-01. To opt out of this default, the user can use: ```scala ThisBuild / packageTimestamp := Package.keepTimestamps // or ThisBuild / packageTimestamp := Package.gitCommitDateTimestamp ``` Before (sbt 1.4.6) ------------------ ``` $ ll example total 32 -rw-r--r-- 1 eed3si9n wheel 901 Jan 1 1970 Greeting.class -rw-r--r-- 1 eed3si9n wheel 3079 Jan 1 1970 Hello$.class -rw-r--r-- 1 eed3si9n wheel 738 Jan 1 1970 Hello$delayedInit$body.class -rw-r--r-- 1 eed3si9n wheel 875 Jan 1 1970 Hello.class ``` After (using Package.gitCommitDateTimestamp) -------------------------------------------- ``` $ unzip -v target/scala-2.13/root_2.13-0.1.0-SNAPSHOT.jar Archive: target/scala-2.13/root_2.13-0.1.0-SNAPSHOT.jar Length Method Size Cmpr Date Time CRC-32 Name -------- ------ ------- ---- ---------- ----- -------- ---- 288 Defl:N 136 53% 01-25-2021 03:09 888682a9 META-INF/MANIFEST.MF 0 Stored 0 0% 01-25-2021 03:09 00000000 example/ 901 Defl:N 601 33% 01-25-2021 03:09 3543f377 example/Greeting.class 3079 Defl:N 1279 59% 01-25-2021 03:09 848b4386 example/Hello$.class 738 Defl:N 464 37% 01-25-2021 03:09 571f4288 example/Hello$delayedInit$body.class 875 Defl:N 594 32% 01-25-2021 03:09 ad295259 example/Hello.class -------- ------- --- ------- 5881 3074 48% 6 files ```
sbt 1.5 makes this configurable: |
Ok, if this is the case, then let's stop setting the Last-Modified header on assets - obviously it is not correct and will mess up caching. This header is AFAIK not mandatory, and we are sending ETag as an alterative. |
Since SBT 1.4.0, SBT has edited the last modified dates in packaged JARs, which include web assets (css, js, etc.); Grid's current version sets the date to 1 Jan 2010. Play framework uses these dates to calculate the ETag and Last-Modified headers. Since the headers are now based upon a static date, caching (especially via Cloudfront) is broken, returning outdated assets. This commit changes the default to set the timestamp to match the latest git commit date, so cloudfront should now notice and pick up new assets upon deployment. See also <playframework/playframework#10572> See also <sbt/sbt#6237>
Since SBT 1.4.0, SBT has edited the last modified dates in packaged JARs, which include web assets (css, js, etc.); Grid's current version sets the date to 1 Jan 2010. Play framework uses these dates to calculate the ETag and Last-Modified headers. Since the headers are now based upon a static date, caching (especially via Cloudfront) is broken, returning outdated assets. This commit restores the previous behaviour, so cloudfront should now notice and pick up new assets upon deployment. See also <playframework/playframework#10572> See also <sbt/sbt#6237>
Since SBT 1.4.0, SBT has edited the last modified dates in packaged JARs, which include web assets (css, js, etc.); Grid's current version sets the date to 1 Jan 2010. Play framework uses these dates to calculate the ETag and Last-Modified headers. Since the headers are now based upon a static date, caching (especially via Cloudfront) is broken, returning outdated assets. This commit restores the previous behaviour, so cloudfront should now notice and pick up new assets upon deployment. See also <playframework/playframework#10572> See also <sbt/sbt#6237>
Since SBT 1.4.0, SBT has edited the last modified dates in packaged JARs, which include web assets (css, js, etc.); Grid's current version sets the date to 1 Jan 2010. Play framework uses these dates to calculate the ETag and Last-Modified headers. Since the headers are now based upon a static date, caching (especially via Cloudfront) is broken, returning outdated assets. This commit restores the previous behaviour, so cloudfront should now notice and pick up new assets upon deployment. See also <playframework/playframework#10572> See also <sbt/sbt#6237>
Since SBT 1.4.0, SBT has edited the last modified dates in packaged JARs, which include web assets (css, js, etc.); Grid's current version sets the date to 1 Jan 2010. Play framework uses these dates to calculate the ETag and Last-Modified headers. Since the headers are now based upon a static date, caching (especially via Cloudfront) is broken, returning outdated assets. This commit restores the previous behaviour, so cloudfront should now notice and pick up new assets upon deployment. See also <playframework/playframework#10572> See also <sbt/sbt#6237>
Since SBT 1.4.0, SBT has edited the last modified dates in packaged JARs, which include web assets (css, js, etc.); Grid's current version sets the date to 1 Jan 2010. Play framework uses these dates to calculate the ETag and Last-Modified headers. Since the headers are now based upon a static date, caching (especially via Cloudfront) is broken, returning outdated assets. This commit restores the previous behaviour, so cloudfront should now notice and pick up new assets upon deployment. See also <playframework/playframework#10572> See also <sbt/sbt#6237>
Since SBT 1.4.0, SBT has edited the last modified dates in packaged JARs, which include web assets (css, js, etc.); Grid's current version sets the date to 1 Jan 2010. Play framework uses these dates to calculate the ETag and Last-Modified headers. Since the headers are now based upon a static date, caching (especially via Cloudfront) is broken, returning outdated assets. This commit restores the previous behaviour, so cloudfront should now notice and pick up new assets upon deployment. See also <playframework/playframework#10572> See also <sbt/sbt#6237>
Since SBT 1.4.0, SBT has edited the last modified dates in packaged JARs, which include web assets (css, js, etc.); our current version sets the date to 1 Jan 2010. Play framework uses these dates to calculate the ETag and Last-Modified headers. Since the headers are now based upon a static date, caching (especially via Cloudfront) is broken, returning outdated assets. This commit restores the previous behaviour, so cloudfront should now notice and pick up new assets upon deployment. See also <playframework/playframework#10572> See also <sbt/sbt#6237>
Since SBT 1.4.0, SBT has edited the last modified dates in packaged JARs, which include web assets (css, js, etc.); our current version sets the date to 1 Jan 2010. Play framework uses these dates to calculate the ETag and Last-Modified headers. Since the headers are now based upon a static date, caching (especially via Cloudfront) is broken, returning outdated assets. This commit restores the previous behaviour, so cloudfront should now notice and pick up new assets upon deployment. See also <playframework/playframework#10572> See also <sbt/sbt#6237>
Since SBT 1.4.0, SBT has edited the last modified dates in packaged JARs, which include web assets (css, js, etc.); our current version sets the date to 1 Jan 2010. Play framework uses these dates to calculate the ETag and Last-Modified headers. Since the headers are now based upon a static date, caching (especially via Cloudfront) is broken, returning outdated assets. This commit restores the previous behaviour, so cloudfront should now notice and pick up new assets upon deployment. See also <playframework/playframework#10572> See also <sbt/sbt#6237>
Last-Modified HTTP header of assets contained in jar is wrong See playframework/playframework#10572
I'm looking into this. @mkurz, would this be brand new documentation? Or adding to an existing page? Any suggestion on where this documentation should go? |
I've been looking at updating the documentation for this. I was thinking of changing it here: https://www.playframework.com/documentation/3.0.x/Deploying#The-Native-Packager However, the suggested workaround from sbt is not working for me. Even after modifying my build.sbt as follows: val currentTime = System.currentTimeMillis()
ThisBuild / packageTimestamp := Some(currentTime)
Universal / packageBin / packageTimestamp := (ThisBuild / packageTimestamp).value
Compile / packageBin / packageTimestamp := (ThisBuild / packageTimestamp).value
Assets / packageBin / packageTimestamp := (ThisBuild / packageTimestamp).value I can confirm sbt will use the specified time, at least with sbt 1.8.2 on macOS Seqoia 15.0.1, but the assets still have the default time: jar tvf lib/dummyproject.dummyproject-1.0-SNAPSHOT-assets.jar | grep -i 'favicon'
687 Fri Jan 01 00:00:00 PST 2010 public/images/favicon.png And I get these headers:
Therefore, I don't want to submit a PR with updated documentation for a workaround that doesn't work. Has anyone gotten this to work? I also tried setting an environment variable like @bchazalet explained, but I still see the same behavior. Edit: Nevermind, this works: |
Adding documentation with #12895 |
Play Version
2.7.7
API
Scala
Operating System
macosx but will affect all I believe
JDK
Seen on OpenJDK 15 and Oracle Java 8
Library Dependencies
Sbt 1.4.4
Expected Behavior
universal:packageZipTarball
and sbt >= 1.4.0Actual Behavior
universal:packageZipTarball
We've tracked down the issue to this sbt change: sbt/sbt#5344. Basically, sbt now resets file timestamps in jars to 1970-01-01. And that date is in turn used by the play framework to set the last-modified header. You can double check by unpacking the jar yourself,
jar fx your-assets-jar.jar
and inspecting the dates on the filesystem.One fix to this is to set an environment variable to the current time when building and packaging the play application, e.g.:
I don't know if this should be fixed by the framework itself, but I think it should at least be documented as it will (and did for us) cause cache issues.
The text was updated successfully, but these errors were encountered: