Skip to content

HTTP 404 for static resources with last modified = 0L (breaks Docker images build with Jib) [SPR-17320] #21853

Closed
@spring-projects-issues

Description

@spring-projects-issues

Martin Bonato opened SPR-17320 and commented

The ResourceHTTPRequestHandler returns HTTP 404 Not Found for static resources that have a file modification date of 0L (i.e. the unix epoch 00:00:00 GMT, January 1, 1970). This breaks resolving static resources in web applications build as Docker images with Jib.

One of the goals of Docker images build with Jib are "reproducible builds". That is, Docker images build from the same sources should result in the same docker image with the same SHAs for the Docker image and it's layers. To achieve this, Jib sets the modification date of every file it includes to 0 (see ReproducibleLayerBuilder). When the ResourceHTTPRequestHandler resolves a static resource from the classpath or the filesystem it checks the resource's lastModified date (ResourceHttpRequestHandler line 467|[https://github.com/spring-projects/spring-framework/blob/7aa933437c874122fef10a3cb8282359312e8d6e/spring-webmvc/src/main/java/org/springframework/web/servlet/resource/ResourceHttpRequestHandler.java#L467]. The AbstractResource however, throws a FileNotFoundException when the file last-modified date is 0:

 

    public long lastModified() throws IOException {
        long lastModified = getFileForLastModifiedCheck().lastModified();
        if (lastModified == 0L) {
            throw new FileNotFoundException(getDescription() +
                    " cannot be resolved in the file system for resolving its last-modified timestamp");
        }
        return lastModified;
    }

In consequence, static resources in the classpath or filesystem in Docker images build with Jib are not resolvable by Spring WebMVCs standard ResourceHttpRequestHandler.

This renders Spring WebApplications build with Jib unusable in most cases.

Resources having a last modified date of 0L should not be treated special by Spring, however ...

Up to Java 6 the contract of java.io.File.getLastModifed() defined a return value of 0L as being returned if the file does not exist or if an I/O error occurs. From Java 7 it also considers 0L as vaild return value in the Javadoc of getLastModified() 
Where it is required to distinguish an I/O exception from the case where 0L is returned, or where several attributes of the same file are required at the same time, or where the time of last access or the creation time are required, then the Files.readAttributes method may be used.

IMHO, Spring should not throw a FileNotFoundException in case getLastModified() returns 0L but should either just return 0L itself or try to read file attributes in such cases.


Issue Links:

Referenced from: commits b7e4a56, ff0afcf, b53995b, cf3635b

Backported to: 5.0.10, 4.3.20

1 votes, 2 watchers

Metadata

Metadata

Assignees

Labels

in: coreIssues in core modules (aop, beans, core, context, expression)in: webIssues in web modules (web, webmvc, webflux, websocket)status: backportedAn issue that has been backported to maintenance branchestype: bugA general bug

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions