diff --git a/jetty-servlet/pom.xml b/jetty-servlet/pom.xml index 0ef36b6bdb0..5e5a514d1c3 100644 --- a/jetty-servlet/pom.xml +++ b/jetty-servlet/pom.xml @@ -60,5 +60,11 @@ tests test + + org.eclipse.jetty + jetty-client + ${project.version} + test + diff --git a/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/MultiPartServletTest.java b/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/MultiPartServletTest.java new file mode 100644 index 00000000000..43ada8c9154 --- /dev/null +++ b/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/MultiPartServletTest.java @@ -0,0 +1,157 @@ +// +// ======================================================================== +// Copyright (c) 1995-2019 Mort Bay Consulting Pty. Ltd. +// ------------------------------------------------------------------------ +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// and Apache License v2.0 which accompanies this distribution. +// +// The Eclipse Public License is available at +// http://www.eclipse.org/legal/epl-v10.html +// +// The Apache License v2.0 is available at +// http://www.opensource.org/licenses/apache2.0.php +// +// You may elect to redistribute this code under either of these licenses. +// ======================================================================== +// + +package org.eclipse.jetty.servlet; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import javax.servlet.MultipartConfigElement; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.Part; + +import org.eclipse.jetty.client.HttpClient; +import org.eclipse.jetty.client.api.ContentResponse; +import org.eclipse.jetty.client.util.BytesContentProvider; +import org.eclipse.jetty.client.util.MultiPartContentProvider; +import org.eclipse.jetty.http.HttpMethod; +import org.eclipse.jetty.http.HttpScheme; +import org.eclipse.jetty.http.MimeTypes; +import org.eclipse.jetty.http.MultiPartFormInputStream; +import org.eclipse.jetty.server.HttpChannel; +import org.eclipse.jetty.server.HttpConnectionFactory; +import org.eclipse.jetty.server.MultiPartFormDataCompliance; +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.server.ServerConnector; +import org.eclipse.jetty.util.IO; +import org.eclipse.jetty.util.log.Log; +import org.eclipse.jetty.util.log.Logger; +import org.eclipse.jetty.util.log.StacklessLogging; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.is; +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class MultiPartServletTest +{ + private static final Logger LOG = Log.getLogger(MultiPartServletTest.class); + + private Server server; + private ServerConnector connector; + private HttpClient client; + + private Path tmpDir; + + private static final int MAX_FILE_SIZE = 512 * 1024; + private static final int LARGE_MESSAGE_SIZE = 1024 * 1024; + + public static class MultiPartServlet extends HttpServlet + { + @Override + protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException + { + if (!req.getContentType().contains(MimeTypes.Type.MULTIPART_FORM_DATA.asString())) + { + resp.setContentType("text/plain"); + resp.getWriter().println("not content type " + MimeTypes.Type.MULTIPART_FORM_DATA); + resp.getWriter().println("contentType: " + req.getContentType()); + return; + } + + resp.setContentType("text/plain"); + for (Part part : req.getParts()) + { + resp.getWriter().println("Part: name=" + part.getName() + ", size=" + part.getSize()); + } + } + } + + @BeforeEach + public void start() throws Exception + { + tmpDir = Files.createTempDirectory(MultiPartServletTest.class.getSimpleName()); + System.err.println(tmpDir); + + server = new Server(); + connector = new ServerConnector(server); + connector.getConnectionFactory(HttpConnectionFactory.class).getHttpConfiguration() + .setMultiPartFormDataCompliance(MultiPartFormDataCompliance.RFC7578); + server.addConnector(connector); + + ServletContextHandler contextHandler = new ServletContextHandler(ServletContextHandler.SESSIONS); + contextHandler.setContextPath("/"); + ServletHolder servletHolder = contextHandler.addServlet(MultiPartServlet.class, "/"); + + MultipartConfigElement config = new MultipartConfigElement(tmpDir.toAbsolutePath().toString(), + MAX_FILE_SIZE, -1, 1); + servletHolder.getRegistration().setMultipartConfig(config); + + server.setHandler(contextHandler); + + server.start(); + + client = new HttpClient(); + client.start(); + } + + @AfterEach + public void stop() throws Exception + { + client.stop(); + server.stop(); + + IO.delete(tmpDir.toFile()); + } + + @Test + public void testTempFilesDeletedOnError() throws Exception + { + String partName = "partName"; + + byte[] byteArray = new byte[LARGE_MESSAGE_SIZE]; + for (int i=0; i