Consider empty jar entries as readable
Prior to this commit, resource handling would not serve empty files and return instead HTTP 404 responses. This would only happen for files contained by JARs, but not on the filesystem. This can be tracked to changes done in `AbstractFileResolvingResource` where we avoid serving empty files for directories, see gh-21372. This commit improves the `checkReadable` method to align this behavior between file system and JAR files. Closes gh-28850
This commit is contained in:
parent
dfd1a31435
commit
94e5eb3eb6
|
|
@ -20,6 +20,7 @@ import java.io.File;
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.HttpURLConnection;
|
import java.net.HttpURLConnection;
|
||||||
|
import java.net.JarURLConnection;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.net.URLConnection;
|
import java.net.URLConnection;
|
||||||
|
|
@ -27,6 +28,7 @@ import java.nio.channels.FileChannel;
|
||||||
import java.nio.channels.ReadableByteChannel;
|
import java.nio.channels.ReadableByteChannel;
|
||||||
import java.nio.file.NoSuchFileException;
|
import java.nio.file.NoSuchFileException;
|
||||||
import java.nio.file.StandardOpenOption;
|
import java.nio.file.StandardOpenOption;
|
||||||
|
import java.util.jar.JarEntry;
|
||||||
|
|
||||||
import org.springframework.util.ResourceUtils;
|
import org.springframework.util.ResourceUtils;
|
||||||
|
|
||||||
|
|
@ -115,6 +117,16 @@ public abstract class AbstractFileResolvingResource extends AbstractResource {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (con instanceof JarURLConnection) {
|
||||||
|
JarURLConnection jarCon = (JarURLConnection) con;
|
||||||
|
JarEntry jarEntry = jarCon.getJarEntry();
|
||||||
|
if (jarEntry == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return !jarEntry.isDirectory();
|
||||||
|
}
|
||||||
|
}
|
||||||
long contentLength = con.getContentLengthLong();
|
long contentLength = con.getContentLengthLong();
|
||||||
if (contentLength > 0) {
|
if (contentLength > 0) {
|
||||||
return true;
|
return true;
|
||||||
|
|
|
||||||
|
|
@ -16,10 +16,18 @@
|
||||||
|
|
||||||
package org.springframework.core.io;
|
package org.springframework.core.io;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.net.URLClassLoader;
|
||||||
|
import java.util.zip.ZipEntry;
|
||||||
|
import java.util.zip.ZipOutputStream;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Nested;
|
import org.junit.jupiter.api.Nested;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.junit.jupiter.api.io.TempDir;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||||
|
|
@ -143,4 +151,32 @@ class ClassPathResourceTests {
|
||||||
assertThat(jarDir.isReadable()).isFalse();
|
assertThat(jarDir.isReadable()).isFalse();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void emptyFileReadable(@TempDir File tempDir) throws IOException {
|
||||||
|
File file = new File(tempDir, "empty.txt");
|
||||||
|
assertThat(file.createNewFile()).isTrue();
|
||||||
|
assertThat(file.isFile());
|
||||||
|
|
||||||
|
ClassLoader fileClassLoader = new URLClassLoader(new URL[]{tempDir.toURI().toURL()});
|
||||||
|
|
||||||
|
Resource emptyFile = new ClassPathResource("empty.txt", fileClassLoader);
|
||||||
|
assertThat(emptyFile.exists()).isTrue();
|
||||||
|
assertThat(emptyFile.isReadable()).isTrue();
|
||||||
|
assertThat(emptyFile.contentLength()).isEqualTo(0);
|
||||||
|
|
||||||
|
File jarFile = new File(tempDir, "test.jar");
|
||||||
|
try (ZipOutputStream zipOut = new ZipOutputStream(new FileOutputStream(jarFile))) {
|
||||||
|
zipOut.putNextEntry(new ZipEntry("empty2.txt"));
|
||||||
|
zipOut.closeEntry();
|
||||||
|
}
|
||||||
|
assertThat(jarFile.isFile());
|
||||||
|
|
||||||
|
ClassLoader jarClassLoader = new URLClassLoader(new URL[]{jarFile.toURI().toURL()});
|
||||||
|
|
||||||
|
Resource emptyJarEntry = new ClassPathResource("empty2.txt", jarClassLoader);
|
||||||
|
assertThat(emptyJarEntry.exists()).isTrue();
|
||||||
|
assertThat(emptyJarEntry.isReadable()).isTrue();
|
||||||
|
assertThat(emptyJarEntry.contentLength()).isEqualTo(0);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue