View Javadoc
1   /*
2    * Copyright (c) 2002-2025 Gargoyle Software Inc.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    * https://www.apache.org/licenses/LICENSE-2.0
8    *
9    * Unless required by applicable law or agreed to in writing, software
10   * distributed under the License is distributed on an "AS IS" BASIS,
11   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12   * See the License for the specific language governing permissions and
13   * limitations under the License.
14   */
15  package org.htmlunit.httpclient;
16  
17  import static java.nio.charset.StandardCharsets.UTF_8;
18  
19  import java.io.File;
20  import java.io.IOException;
21  import java.io.InputStream;
22  import java.io.Writer;
23  import java.net.URL;
24  import java.util.HashMap;
25  import java.util.Locale;
26  import java.util.Map;
27  
28  import javax.servlet.Servlet;
29  import javax.servlet.ServletException;
30  import javax.servlet.http.HttpServlet;
31  import javax.servlet.http.HttpServletRequest;
32  import javax.servlet.http.HttpServletResponse;
33  
34  import org.apache.commons.fileupload.FileItem;
35  import org.apache.commons.fileupload.FileUploadBase;
36  import org.apache.commons.fileupload.disk.DiskFileItemFactory;
37  import org.apache.commons.fileupload.servlet.ServletFileUpload;
38  import org.apache.commons.io.IOUtils;
39  import org.apache.http.HttpResponse;
40  import org.apache.http.client.methods.HttpPost;
41  import org.apache.http.entity.ContentType;
42  import org.apache.http.entity.mime.HttpMultipartMode;
43  import org.apache.http.entity.mime.MultipartEntityBuilder;
44  import org.apache.http.entity.mime.content.FileBody;
45  import org.apache.http.impl.client.HttpClientBuilder;
46  import org.htmlunit.WebServerTestCase;
47  import org.htmlunit.html.HtmlFileInput;
48  import org.htmlunit.util.MimeType;
49  import org.junit.jupiter.api.Test;
50  
51  /**
52   * Tests for {@link HtmlFileInput}.
53   *
54   * @author Marc Guillemot
55   * @author Ahmed Ashour
56   * @author Ronald Brill
57   * @author Frank Danek
58   */
59  public class HttpClientTest extends WebServerTestCase {
60  
61      /**
62       * Servlet for '/upload'.
63       */
64      public static class UploadServlet extends HttpServlet {
65  
66          /**
67           * {@inheritDoc}
68           */
69          @Override
70          protected void doPost(final HttpServletRequest request, final HttpServletResponse response)
71              throws ServletException, IOException {
72              request.setCharacterEncoding(UTF_8.name());
73              response.setContentType(MimeType.TEXT_HTML);
74              final Writer writer = response.getWriter();
75              if (ServletFileUpload.isMultipartContent(request)) {
76                  try {
77                      final ServletFileUpload upload = new ServletFileUpload(new DiskFileItemFactory());
78                      for (final FileItem item : upload.parseRequest(request)) {
79                          if ("myInput".equals(item.getFieldName())) {
80                              final String path = item.getName();
81                              for (final char ch : path.toCharArray()) {
82                                  writer.write(Integer.toHexString(ch).toUpperCase(Locale.ROOT) + " ");
83                              }
84                              writer.write("<br>");
85                              writer.write(item.getFieldName());
86                          }
87                      }
88                  }
89                  catch (final FileUploadBase.SizeLimitExceededException e) {
90                      writer.write("SizeLimitExceeded");
91                  }
92                  catch (final Exception e) {
93                      writer.write("error");
94                  }
95              }
96          }
97      }
98  
99      /**
100      * Test HttpClient for uploading a file with non-ASCII name, if it works it means HttpClient has fixed its bug.
101      *
102      * Test for http://issues.apache.org/jira/browse/HTTPCLIENT-293,
103      * which is related to http://sourceforge.net/p/htmlunit/bugs/535/
104      *
105      * @throws Exception if the test fails
106      */
107     @Test
108     public void uploadFileWithNonASCIIName_HttpClient() throws Exception {
109         final String filename = "\u6A94\u6848\uD30C\uC77C\u30D5\u30A1\u30A4\u30EB\u0645\u0644\u0641.txt";
110         final URL fileURL = getClass().getClassLoader().getResource(filename);
111         assertNotNull("Resource '" + filename + "' not found", fileURL);
112         final File file = new File(fileURL.toURI());
113         assertTrue("File '" + file.getAbsolutePath() + "' does not exist", file.exists());
114 
115         final Map<String, Class<? extends Servlet>> servlets = new HashMap<>();
116         servlets.put("/upload2", UploadServlet.class);
117 
118         startWebServer("./", null, servlets);
119         final HttpPost filePost = new HttpPost(URL_FIRST + "upload2");
120 
121         final MultipartEntityBuilder builder = MultipartEntityBuilder.create();
122         builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE).setCharset(UTF_8);
123         builder.addPart("myInput", new FileBody(file, ContentType.APPLICATION_OCTET_STREAM));
124 
125         filePost.setEntity(builder.build());
126 
127         final HttpClientBuilder clientBuilder = HttpClientBuilder.create();
128         final HttpResponse httpResponse = clientBuilder.build().execute(filePost);
129 
130         try (InputStream content = httpResponse.getEntity().getContent()) {
131             final String response = new String(IOUtils.toByteArray(content));
132             //this is the value with ASCII encoding
133             assertFalse("3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 2E 74 78 74 <br>myInput".equals(response));
134         }
135     }
136 }