forked from deephaven/deephaven-core
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Wrap Jetty's Resource type to force an invalid last-modified header
Jetty always returns the last-modified date of the file, but Gradle unsets the "true" last modified date in favor of ensuring that build files cache only based on their contents. Disabling this feature is possible, but still may present as buggy in Jetty, such as if a 1.0 release occurred, then 2.0, then a 1.1 hotfix - if an installation of 1.1 were later replaced with 2.0, the 1.1 files would be "newer" so would be considered up to date. This patch removes the last-modified value by only returning -1 when requested. We could go further and return an etag that actually maps to the release version or the contents of the file, but that is left for future work. Fixes deephaven#3011
- Loading branch information
Showing
2 changed files
with
124 additions
and
5 deletions.
There are no files selected for viewing
122 changes: 122 additions & 0 deletions
122
server/jetty/src/main/java/io/deephaven/server/jetty/ControlledCacheResource.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
package io.deephaven.server.jetty; | ||
|
||
import org.eclipse.jetty.util.resource.Resource; | ||
|
||
import java.io.File; | ||
import java.io.IOException; | ||
import java.io.InputStream; | ||
import java.net.MalformedURLException; | ||
import java.net.URI; | ||
import java.nio.channels.ReadableByteChannel; | ||
|
||
/** | ||
* Simple wrapper around the Jetty Resource type, to grant us control over caching features. The current implementation | ||
* only removes the last-modified value, but a future version could provide a "real" weak/strong etag. | ||
*/ | ||
public class ControlledCacheResource extends Resource { | ||
private final Resource wrapped; | ||
|
||
public ControlledCacheResource(Resource wrapped) { | ||
this.wrapped = wrapped; | ||
} | ||
|
||
@Override | ||
public boolean isContainedIn(Resource r) throws MalformedURLException { | ||
return wrapped.isContainedIn(r); | ||
} | ||
|
||
@Override | ||
public void close() { | ||
wrapped.close(); | ||
} | ||
|
||
@Override | ||
public boolean exists() { | ||
return wrapped.exists(); | ||
} | ||
|
||
@Override | ||
public boolean isDirectory() { | ||
return wrapped.isDirectory(); | ||
} | ||
|
||
@Override | ||
public long lastModified() { | ||
// Always return -1, so that we don't get the build system timestamp. In theory we could return the app startup | ||
// time as well, so that clients that connect don't need to revalidate quite as often, but this could have other | ||
// side effects such as in load balancing with a short-lived old build against a seconds-older new build. | ||
return -1; | ||
} | ||
|
||
@Override | ||
public long length() { | ||
return wrapped.length(); | ||
} | ||
|
||
@Override | ||
public URI getURI() { | ||
return wrapped.getURI(); | ||
} | ||
|
||
@Override | ||
public File getFile() throws IOException { | ||
return wrapped.getFile(); | ||
} | ||
|
||
@Override | ||
public String getName() { | ||
return wrapped.getName(); | ||
} | ||
|
||
@Override | ||
public InputStream getInputStream() throws IOException { | ||
return wrapped.getInputStream(); | ||
} | ||
|
||
@Override | ||
public ReadableByteChannel getReadableByteChannel() throws IOException { | ||
return wrapped.getReadableByteChannel(); | ||
} | ||
|
||
@Override | ||
public boolean delete() throws SecurityException { | ||
return wrapped.delete(); | ||
} | ||
|
||
@Override | ||
public boolean renameTo(Resource dest) throws SecurityException { | ||
return wrapped.renameTo(dest); | ||
} | ||
|
||
@Override | ||
public String[] list() { | ||
return wrapped.list(); | ||
} | ||
|
||
@Override | ||
public Resource addPath(String path) throws IOException, MalformedURLException { | ||
// Re-wrap any instance that might be returned | ||
return new ControlledCacheResource(wrapped.addPath(path)); | ||
} | ||
|
||
@Override | ||
public String toString() { | ||
// Jetty's CachedContentFactory.CachedHttpContent requires that toString return the underlying URL found on | ||
// disk, or else the mime lookup from content type won't resolve anything. | ||
return wrapped.toString(); | ||
} | ||
|
||
@Override | ||
public int hashCode() { | ||
// As with toString, delegating this to the wrapped instance, just in case there is some specific, expected | ||
// behavior | ||
return wrapped.hashCode(); | ||
} | ||
|
||
@Override | ||
public boolean equals(Object obj) { | ||
// As with toString, delegating this to the wrapped instance, just in case there is some specific, expected | ||
// behavior | ||
return wrapped.equals(obj); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters