blob: ac18e3a12876a6c265a77b9537825f4277730ef5 [file] [log] [blame]
package fi.iki.elonen;
/*
* #%L
* NanoHttpd-apache file upload integration
* %%
* Copyright (C) 2012 - 2015 nanohttpd
* %%
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the nanohttpd nor the names of its contributors
* may be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
* #L%
*/
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileItemIterator;
import org.apache.commons.fileupload.FileItemStream;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.util.Streams;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpTrace;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.entity.mime.content.StringBody;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.FixMethodOrder;
import org.junit.Test;
import org.junit.internal.runners.statements.Fail;
import fi.iki.elonen.NanoHTTPD.Response.Status;
/**
* very strange but if the file upload is the first request the test fails.
*
* @author ritchieGitHub
*/
@FixMethodOrder
public class TestNanoFileUpLoad {
protected TestServer testServer;
public static class TestServer extends NanoHTTPD {
public Response response = newFixedLengthResponse("");
public String uri;
public Method method;
public Map<String, String> header;
public Map<String, String> parms;
public Map<String, List<FileItem>> files;
public Map<String, List<String>> decodedParamters;
public Map<String, List<String>> decodedParamtersFromParameter;
public String queryParameterString;
public TestServer() {
super(8192);
uploader = new NanoFileUpload(new DiskFileItemFactory());
}
public HTTPSession createSession(TempFileManager tempFileManager, InputStream inputStream, OutputStream outputStream) {
return new HTTPSession(tempFileManager, inputStream, outputStream);
}
public HTTPSession createSession(TempFileManager tempFileManager, InputStream inputStream, OutputStream outputStream, InetAddress inetAddress) {
return new HTTPSession(tempFileManager, inputStream, outputStream, inetAddress);
}
NanoFileUpload uploader;
@Override
public Response serve(IHTTPSession session) {
this.uri = session.getUri();
this.method = session.getMethod();
this.header = session.getHeaders();
this.parms = session.getParms();
if (NanoFileUpload.isMultipartContent(session)) {
try {
if ("/uploadFile1".equals(this.uri)) {
session.getHeaders().put("content-length", "AA");
files = uploader.parseParameterMap(session);
}
if ("/uploadFile2".equals(this.uri)) {
files = new HashMap<String, List<FileItem>>();
List<FileItem> parseRequest = uploader.parseRequest(session);
files.put(parseRequest.get(0).getFieldName(), parseRequest);
}
if ("/uploadFile3".equals(this.uri)) {
files = new HashMap<String, List<FileItem>>();
FileItemIterator iter = uploader.getItemIterator(session);
while (iter.hasNext()) {
FileItemStream item = iter.next();
final String fileName = item.getName();
FileItem fileItem = uploader.getFileItemFactory().createItem(item.getFieldName(), item.getContentType(), item.isFormField(), fileName);
files.put(fileItem.getFieldName(), Arrays.asList(new FileItem[]{
fileItem
}));
try {
Streams.copy(item.openStream(), fileItem.getOutputStream(), true);
} catch (Exception e) {
}
fileItem.setHeaders(item.getHeaders());
}
}
} catch (Exception e) {
this.response.setStatus(Status.INTERNAL_ERROR);
e.printStackTrace();
}
}
this.queryParameterString = session.getQueryParameterString();
this.decodedParamtersFromParameter = decodeParameters(this.queryParameterString);
this.decodedParamters = decodeParameters(session.getQueryParameterString());
return this.response;
}
}
@Test
public void testNormalRequest() throws Exception {
CloseableHttpClient httpclient = HttpClients.createDefault();
HttpTrace httphead = new HttpTrace("http://localhost:8192/index.html");
CloseableHttpResponse response = httpclient.execute(httphead);
Assert.assertEquals(200, response.getStatusLine().getStatusCode());
response.close();
}
@Test
public void testPostWithMultipartFormUpload1() throws Exception {
CloseableHttpClient httpclient = HttpClients.createDefault();
String textFileName = "src/test/java/fi/iki/elonen/TestNanoFileUpLoad.java";
HttpPost post = new HttpPost("http://localhost:8192/uploadFile1");
executeUpload(httpclient, textFileName, post);
FileItem file = this.testServer.files.get("upfile").get(0);
Assert.assertEquals(file.getSize(), new File(textFileName).length());
}
@Test
public void testPostWithMultipartFormUpload2() throws Exception {
CloseableHttpClient httpclient = HttpClients.createDefault();
String textFileName = "src/test/java/fi/iki/elonen/TestNanoFileUpLoad.java";
HttpPost post = new HttpPost("http://localhost:8192/uploadFile2");
executeUpload(httpclient, textFileName, post);
FileItem file = this.testServer.files.get("upfile").get(0);
Assert.assertEquals(file.getSize(), new File(textFileName).length());
}
@Test
public void testPostWithMultipartFormUpload3() throws Exception {
CloseableHttpClient httpclient = HttpClients.createDefault();
String textFileName = "src/test/java/fi/iki/elonen/TestNanoFileUpLoad.java";
HttpPost post = new HttpPost("http://localhost:8192/uploadFile3");
executeUpload(httpclient, textFileName, post);
FileItem file = this.testServer.files.get("upfile").get(0);
Assert.assertEquals(file.getSize(), new File(textFileName).length());
}
private void executeUpload(CloseableHttpClient httpclient, String textFileName, HttpPost post) throws IOException, ClientProtocolException {
FileBody fileBody = new FileBody(new File(textFileName), ContentType.DEFAULT_BINARY);
StringBody stringBody1 = new StringBody("Message 1", ContentType.MULTIPART_FORM_DATA);
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
builder.addPart("upfile", fileBody);
builder.addPart("text1", stringBody1);
HttpEntity entity = builder.build();
//
post.setEntity(entity);
HttpResponse response = httpclient.execute(post);
Assert.assertEquals(200, response.getStatusLine().getStatusCode());
}
@Before
public void setUp() throws IOException {
this.testServer = new TestServer();
this.testServer.start();
try {
long start = System.currentTimeMillis();
Thread.sleep(100L);
while (!this.testServer.wasStarted()) {
Thread.sleep(100L);
if (System.currentTimeMillis() - start > 2000) {
Assert.fail("could not start server");
}
}
} catch (InterruptedException e) {
}
}
@After
public void tearDown() {
this.testServer.stop();
}
}