diff --git a/jetty-core/jetty-http/src/main/java/org/eclipse/jetty/http/MultiPartFormData.java b/jetty-core/jetty-http/src/main/java/org/eclipse/jetty/http/MultiPartFormData.java index 1f58648e6993..8e8b15122f11 100644 --- a/jetty-core/jetty-http/src/main/java/org/eclipse/jetty/http/MultiPartFormData.java +++ b/jetty-core/jetty-http/src/main/java/org/eclipse/jetty/http/MultiPartFormData.java @@ -317,6 +317,21 @@ public void setFilesDirectory(Path filesDirectory) this.filesDirectory = filesDirectory; } + private Path findFilesDirectory() + { + Path dir = getFilesDirectory(); + if (dir != null) + return dir; + String jettyBase = System.getProperty("jetty.base"); + if (jettyBase != null) + { + dir = Path.of(jettyBase).resolve("work"); + if (Files.exists(dir)) + return dir; + } + throw new IllegalArgumentException("No files directory configured"); + } + /** * @return the maximum file size in bytes, or -1 for unlimited file size */ @@ -627,7 +642,7 @@ private void createFileChannel() { try (AutoLock ignored = lock.lock()) { - Path directory = getFilesDirectory(); + Path directory = findFilesDirectory(); Files.createDirectories(directory); String fileName = "MultiPart"; filePath = Files.createTempFile(directory, fileName, ""); diff --git a/jetty-core/jetty-http/src/test/java/org/eclipse/jetty/http/MultiPartFormDataTest.java b/jetty-core/jetty-http/src/test/java/org/eclipse/jetty/http/MultiPartFormDataTest.java index c96c2035b654..efe48ff6de0d 100644 --- a/jetty-core/jetty-http/src/test/java/org/eclipse/jetty/http/MultiPartFormDataTest.java +++ b/jetty-core/jetty-http/src/test/java/org/eclipse/jetty/http/MultiPartFormDataTest.java @@ -912,6 +912,28 @@ public void testTerminalFailureIsTerminal() assertThat(chunk.getFailure(), instanceOf(NumberFormatException.class)); } + @Test + public void testMissingFilesDirectory() + { + AsyncContent source = new TestContent(); + MultiPartFormData.Parser formData = new MultiPartFormData.Parser("AaB03x"); + // Always save to disk. + formData.setMaxMemoryFileSize(0); + + String body = """ + --AaB03x\r + Content-Disposition: form-data; name="file1"; filename="file.txt"\r + Content-Type: text/plain\r + \r + ABCDEFGHIJKLMNOPQRSTUVWXYZ\r + --AaB03x--\r + """; + Content.Sink.write(source, true, body, Callback.NOOP); + + Throwable cause = assertThrows(ExecutionException.class, () -> formData.parse(source).get(5, TimeUnit.SECONDS)).getCause(); + assertInstanceOf(IllegalArgumentException.class, cause); + } + private class TestContent extends AsyncContent { @Override