Home | History | Annotate | Download | only in elonen
      1 package fi.iki.elonen;
      2 
      3 /*
      4  * #%L
      5  * NanoHttpd-apache file upload integration
      6  * %%
      7  * Copyright (C) 2012 - 2015 nanohttpd
      8  * %%
      9  * Redistribution and use in source and binary forms, with or without modification,
     10  * are permitted provided that the following conditions are met:
     11  *
     12  * 1. Redistributions of source code must retain the above copyright notice, this
     13  *    list of conditions and the following disclaimer.
     14  *
     15  * 2. Redistributions in binary form must reproduce the above copyright notice,
     16  *    this list of conditions and the following disclaimer in the documentation
     17  *    and/or other materials provided with the distribution.
     18  *
     19  * 3. Neither the name of the nanohttpd nor the names of its contributors
     20  *    may be used to endorse or promote products derived from this software without
     21  *    specific prior written permission.
     22  *
     23  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
     24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     25  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     26  * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
     27  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
     28  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     29  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
     30  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
     31  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
     32  * OF THE POSSIBILITY OF SUCH DAMAGE.
     33  * #L%
     34  */
     35 
     36 import java.io.File;
     37 import java.io.IOException;
     38 import java.io.InputStream;
     39 import java.io.OutputStream;
     40 import java.net.InetAddress;
     41 import java.util.Arrays;
     42 import java.util.HashMap;
     43 import java.util.List;
     44 import java.util.Map;
     45 
     46 import org.apache.commons.fileupload.FileItem;
     47 import org.apache.commons.fileupload.FileItemIterator;
     48 import org.apache.commons.fileupload.FileItemStream;
     49 import org.apache.commons.fileupload.FileUploadException;
     50 import org.apache.commons.fileupload.disk.DiskFileItemFactory;
     51 import org.apache.commons.fileupload.util.Streams;
     52 import org.apache.http.HttpEntity;
     53 import org.apache.http.HttpResponse;
     54 import org.apache.http.client.ClientProtocolException;
     55 import org.apache.http.client.methods.CloseableHttpResponse;
     56 import org.apache.http.client.methods.HttpPost;
     57 import org.apache.http.client.methods.HttpTrace;
     58 import org.apache.http.entity.ContentType;
     59 import org.apache.http.entity.mime.HttpMultipartMode;
     60 import org.apache.http.entity.mime.MultipartEntityBuilder;
     61 import org.apache.http.entity.mime.content.FileBody;
     62 import org.apache.http.entity.mime.content.StringBody;
     63 import org.apache.http.impl.client.CloseableHttpClient;
     64 import org.apache.http.impl.client.HttpClients;
     65 import org.junit.After;
     66 import org.junit.Assert;
     67 import org.junit.Before;
     68 import org.junit.FixMethodOrder;
     69 import org.junit.Test;
     70 import org.junit.internal.runners.statements.Fail;
     71 
     72 import fi.iki.elonen.NanoHTTPD.Response.Status;
     73 
     74 /**
     75  * very strange but if the file upload is the first request the test fails.
     76  *
     77  * @author ritchieGitHub
     78  */
     79 @FixMethodOrder
     80 public class TestNanoFileUpLoad {
     81 
     82     protected TestServer testServer;
     83 
     84     public static class TestServer extends NanoHTTPD {
     85 
     86         public Response response = newFixedLengthResponse("");
     87 
     88         public String uri;
     89 
     90         public Method method;
     91 
     92         public Map<String, String> header;
     93 
     94         public Map<String, String> parms;
     95 
     96         public Map<String, List<FileItem>> files;
     97 
     98         public Map<String, List<String>> decodedParamters;
     99 
    100         public Map<String, List<String>> decodedParamtersFromParameter;
    101 
    102         public String queryParameterString;
    103 
    104         public TestServer() {
    105             super(8192);
    106             uploader = new NanoFileUpload(new DiskFileItemFactory());
    107         }
    108 
    109         public HTTPSession createSession(TempFileManager tempFileManager, InputStream inputStream, OutputStream outputStream) {
    110             return new HTTPSession(tempFileManager, inputStream, outputStream);
    111         }
    112 
    113         public HTTPSession createSession(TempFileManager tempFileManager, InputStream inputStream, OutputStream outputStream, InetAddress inetAddress) {
    114             return new HTTPSession(tempFileManager, inputStream, outputStream, inetAddress);
    115         }
    116 
    117         NanoFileUpload uploader;
    118 
    119         @Override
    120         public Response serve(IHTTPSession session) {
    121 
    122             this.uri = session.getUri();
    123             this.method = session.getMethod();
    124             this.header = session.getHeaders();
    125             this.parms = session.getParms();
    126             if (NanoFileUpload.isMultipartContent(session)) {
    127                 try {
    128                     if ("/uploadFile1".equals(this.uri)) {
    129                         session.getHeaders().put("content-length", "AA");
    130                         files = uploader.parseParameterMap(session);
    131                     }
    132                     if ("/uploadFile2".equals(this.uri)) {
    133                         files = new HashMap<String, List<FileItem>>();
    134                         List<FileItem> parseRequest = uploader.parseRequest(session);
    135                         files.put(parseRequest.get(0).getFieldName(), parseRequest);
    136                     }
    137                     if ("/uploadFile3".equals(this.uri)) {
    138                         files = new HashMap<String, List<FileItem>>();
    139                         FileItemIterator iter = uploader.getItemIterator(session);
    140                         while (iter.hasNext()) {
    141                             FileItemStream item = iter.next();
    142                             final String fileName = item.getName();
    143                             FileItem fileItem = uploader.getFileItemFactory().createItem(item.getFieldName(), item.getContentType(), item.isFormField(), fileName);
    144                             files.put(fileItem.getFieldName(), Arrays.asList(new FileItem[]{
    145                                 fileItem
    146                             }));
    147                             try {
    148                                 Streams.copy(item.openStream(), fileItem.getOutputStream(), true);
    149                             } catch (Exception e) {
    150                             }
    151                             fileItem.setHeaders(item.getHeaders());
    152                         }
    153                     }
    154                 } catch (Exception e) {
    155                     this.response.setStatus(Status.INTERNAL_ERROR);
    156                     e.printStackTrace();
    157                 }
    158             }
    159             this.queryParameterString = session.getQueryParameterString();
    160             this.decodedParamtersFromParameter = decodeParameters(this.queryParameterString);
    161             this.decodedParamters = decodeParameters(session.getQueryParameterString());
    162             return this.response;
    163         }
    164 
    165     }
    166 
    167     @Test
    168     public void testNormalRequest() throws Exception {
    169         CloseableHttpClient httpclient = HttpClients.createDefault();
    170         HttpTrace httphead = new HttpTrace("http://localhost:8192/index.html");
    171         CloseableHttpResponse response = httpclient.execute(httphead);
    172         Assert.assertEquals(200, response.getStatusLine().getStatusCode());
    173         response.close();
    174     }
    175 
    176     @Test
    177     public void testPostWithMultipartFormUpload1() throws Exception {
    178         CloseableHttpClient httpclient = HttpClients.createDefault();
    179         String textFileName = "src/test/java/fi/iki/elonen/TestNanoFileUpLoad.java";
    180         HttpPost post = new HttpPost("http://localhost:8192/uploadFile1");
    181 
    182         executeUpload(httpclient, textFileName, post);
    183         FileItem file = this.testServer.files.get("upfile").get(0);
    184         Assert.assertEquals(file.getSize(), new File(textFileName).length());
    185     }
    186 
    187     @Test
    188     public void testPostWithMultipartFormUpload2() throws Exception {
    189         CloseableHttpClient httpclient = HttpClients.createDefault();
    190         String textFileName = "src/test/java/fi/iki/elonen/TestNanoFileUpLoad.java";
    191         HttpPost post = new HttpPost("http://localhost:8192/uploadFile2");
    192 
    193         executeUpload(httpclient, textFileName, post);
    194         FileItem file = this.testServer.files.get("upfile").get(0);
    195         Assert.assertEquals(file.getSize(), new File(textFileName).length());
    196     }
    197 
    198     @Test
    199     public void testPostWithMultipartFormUpload3() throws Exception {
    200         CloseableHttpClient httpclient = HttpClients.createDefault();
    201         String textFileName = "src/test/java/fi/iki/elonen/TestNanoFileUpLoad.java";
    202         HttpPost post = new HttpPost("http://localhost:8192/uploadFile3");
    203 
    204         executeUpload(httpclient, textFileName, post);
    205         FileItem file = this.testServer.files.get("upfile").get(0);
    206         Assert.assertEquals(file.getSize(), new File(textFileName).length());
    207     }
    208 
    209     private void executeUpload(CloseableHttpClient httpclient, String textFileName, HttpPost post) throws IOException, ClientProtocolException {
    210         FileBody fileBody = new FileBody(new File(textFileName), ContentType.DEFAULT_BINARY);
    211         StringBody stringBody1 = new StringBody("Message 1", ContentType.MULTIPART_FORM_DATA);
    212 
    213         MultipartEntityBuilder builder = MultipartEntityBuilder.create();
    214         builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
    215         builder.addPart("upfile", fileBody);
    216         builder.addPart("text1", stringBody1);
    217         HttpEntity entity = builder.build();
    218         //
    219         post.setEntity(entity);
    220         HttpResponse response = httpclient.execute(post);
    221         Assert.assertEquals(200, response.getStatusLine().getStatusCode());
    222     }
    223 
    224     @Before
    225     public void setUp() throws IOException {
    226         this.testServer = new TestServer();
    227         this.testServer.start();
    228         try {
    229             long start = System.currentTimeMillis();
    230             Thread.sleep(100L);
    231             while (!this.testServer.wasStarted()) {
    232                 Thread.sleep(100L);
    233                 if (System.currentTimeMillis() - start > 2000) {
    234                     Assert.fail("could not start server");
    235                 }
    236             }
    237         } catch (InterruptedException e) {
    238         }
    239     }
    240 
    241     @After
    242     public void tearDown() {
    243         this.testServer.stop();
    244     }
    245 
    246 }
    247