diff options
author | ritchie <ritchie@gmx.at> | 2015-10-03 07:31:10 +0200 |
---|---|---|
committer | ritchie <ritchie@gmx.at> | 2015-10-03 07:31:10 +0200 |
commit | 14d6e72cc194ace40662bdf9d81806f14e96d212 (patch) | |
tree | 68317044110f62451fc44b8eb066dc4f939e3db2 | |
parent | 8f5edfe4109511a25ccb16f526823435284481ad (diff) | |
download | nanohttpd-14d6e72cc194ace40662bdf9d81806f14e96d212.tar.gz |
easy way to add mime types fix #204
8 files changed, 177 insertions, 120 deletions
diff --git a/core/src/main/java/fi/iki/elonen/NanoHTTPD.java b/core/src/main/java/fi/iki/elonen/NanoHTTPD.java index 3b3d019..0d30d9f 100644 --- a/core/src/main/java/fi/iki/elonen/NanoHTTPD.java +++ b/core/src/main/java/fi/iki/elonen/NanoHTTPD.java @@ -58,6 +58,7 @@ import java.net.ServerSocket; import java.net.Socket; import java.net.SocketException; import java.net.SocketTimeoutException; +import java.net.URL; import java.net.URLDecoder; import java.nio.ByteBuffer; import java.nio.channels.FileChannel; @@ -68,11 +69,13 @@ import java.util.ArrayList; import java.util.Calendar; import java.util.Collections; import java.util.Date; +import java.util.Enumeration; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Locale; import java.util.Map; +import java.util.Properties; import java.util.StringTokenizer; import java.util.TimeZone; import java.util.logging.Level; @@ -1574,6 +1577,45 @@ public abstract class NanoHTTPD { private static final Logger LOG = Logger.getLogger(NanoHTTPD.class.getName()); /** + * Hashtable mapping (String)FILENAME_EXTENSION -> (String)MIME_TYPE + */ + protected static Map<String, String> MIME_TYPES; + + public static Map<String, String> mimeTypes() { + if (MIME_TYPES == null) { + MIME_TYPES = new HashMap<String, String>(); + loadMimeTypes(MIME_TYPES, "META-INF/nanohttpd/default-mimetypes.properties"); + loadMimeTypes(MIME_TYPES, "META-INF/nanohttpd/mimetypes.properties"); + if (MIME_TYPES.isEmpty()) { + LOG.log(Level.WARNING, "no mime types found in the classpath! please provide mimetypes.properties"); + } + } + return MIME_TYPES; + } + + private static void loadMimeTypes(Map<String, String> result, String resourceName) { + try { + Enumeration<URL> resources = NanoHTTPD.class.getClassLoader().getResources(resourceName); + while (resources.hasMoreElements()) { + URL url = (URL) resources.nextElement(); + Properties properties = new Properties(); + InputStream stream = null; + try { + stream = url.openStream(); + properties.load(url.openStream()); + } catch (IOException e) { + LOG.log(Level.SEVERE, "could not load mimetypes from " + url, e); + } finally { + safeClose(stream); + } + result.putAll((Map) properties); + } + } catch (IOException e) { + LOG.log(Level.INFO, "no mime types available at " + resourceName); + } + }; + + /** * Creates an SSLSocketFactory for HTTPS. Pass a loaded KeyStore and an * array of loaded KeyManagers. These objects must properly * loaded/initialized by the caller. @@ -1622,6 +1664,22 @@ public abstract class NanoHTTPD { } } + /** + * Get MIME type from file name extension, if possible + * + * @param uri + * the string representing a file + * @return the connected mime/type + */ + public static String getMimeTypeForFile(String uri) { + int dot = uri.lastIndexOf('.'); + String mime = null; + if (dot >= 0) { + mime = mimeTypes().get(uri.substring(dot + 1).toLowerCase()); + } + return mime == null ? "application/octet-stream" : mime; + } + private static final void safeClose(Object closeable) { try { if (closeable != null) { diff --git a/core/src/main/resources/META-INF/nanohttpd/default-mimetypes.properties b/core/src/main/resources/META-INF/nanohttpd/default-mimetypes.properties new file mode 100644 index 0000000..3fb242f --- /dev/null +++ b/core/src/main/resources/META-INF/nanohttpd/default-mimetypes.properties @@ -0,0 +1,30 @@ +#default mime types for nanohttpd, use META-INF/mimetypes.properties for user defined mimetypes +css=text/css +htm=text/html +html=text/html +xml=text/xml +java=text/x-java-source, text/java +md=text/plain +txt=text/plain +asc=text/plain +gif=image/gif +jpg=image/jpeg +jpeg=image/jpeg +png=image/png +svg=image/svg+xml +mp3=audio/mpeg +m3u=audio/mpeg-url +mp4=video/mp4 +ogv=video/ogg +flv=video/x-flv +mov=video/quicktime +swf=application/x-shockwave-flash +js=application/javascript +pdf=application/pdf +doc=application/msword +ogg=application/x-ogg +zip=application/octet-stream +exe=application/octet-stream +class=application/octet-stream +m3u8=application/vnd.apple.mpegurl +ts=video/mp2t
\ No newline at end of file diff --git a/core/src/main/resources/META-INF/nanohttpd/mimetypes.properties b/core/src/main/resources/META-INF/nanohttpd/mimetypes.properties new file mode 100644 index 0000000..7166a88 --- /dev/null +++ b/core/src/main/resources/META-INF/nanohttpd/mimetypes.properties @@ -0,0 +1 @@ +#mime types for nanohttpd, use a file like this for user defined mimetypes
\ No newline at end of file diff --git a/core/src/test/java/fi/iki/elonen/HttpSSLServerTest.java b/core/src/test/java/fi/iki/elonen/HttpSSLServerTest.java index f6b1999..30fb48c 100644 --- a/core/src/test/java/fi/iki/elonen/HttpSSLServerTest.java +++ b/core/src/test/java/fi/iki/elonen/HttpSSLServerTest.java @@ -57,7 +57,7 @@ public class HttpSSLServerTest extends HttpServerTest { HttpResponse response = httpclient.execute(httphead); HttpEntity entity = response.getEntity(); Assert.assertEquals(200, response.getStatusLine().getStatusCode()); - + Assert.assertEquals(9043, this.testServer.getListeningPort()); Assert.assertTrue(this.testServer.isAlive()); } diff --git a/core/src/test/java/fi/iki/elonen/MimeTest.java b/core/src/test/java/fi/iki/elonen/MimeTest.java new file mode 100644 index 0000000..046ef00 --- /dev/null +++ b/core/src/test/java/fi/iki/elonen/MimeTest.java @@ -0,0 +1,62 @@ +package fi.iki.elonen; + +/* + * #%L + * NanoHttpd-Core + * %% + * 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 org.junit.Assert; +import org.junit.Test; + +public class MimeTest { + + @Test + public void testExistingMimeType() throws Exception { + Assert.assertEquals("text/html", NanoHTTPD.getMimeTypeForFile("xxxx.html")); + } + + @Test + public void testNotExistingMimeType() throws Exception { + Assert.assertNull(NanoHTTPD.mimeTypes().get("notExistent")); + Assert.assertEquals("application/octet-stream", NanoHTTPD.getMimeTypeForFile("xxxx.notExistent")); + } + + @Test + public void testOverwritenMimeType() throws Exception { + Assert.assertEquals("video/wrongOverwrite", NanoHTTPD.getMimeTypeForFile("xxxx.ts")); + } + + @Test + public void testManualMimeType() throws Exception { + NanoHTTPD.mimeTypes().put("flv", "video/manualOverwrite"); + Assert.assertEquals("video/manualOverwrite", NanoHTTPD.getMimeTypeForFile("xxxx.flv")); + } +} diff --git a/core/src/test/resources/META-INF/nanohttpd/mimetypes.properties b/core/src/test/resources/META-INF/nanohttpd/mimetypes.properties new file mode 100644 index 0000000..2f353d8 --- /dev/null +++ b/core/src/test/resources/META-INF/nanohttpd/mimetypes.properties @@ -0,0 +1,3 @@ +#test mime types for nanohttpd +blabla=text/blabla +ts=video/wrongOverwrite
\ No newline at end of file diff --git a/nanolets/src/main/java/fi/iki/elonen/router/RouterNanoHTTPD.java b/nanolets/src/main/java/fi/iki/elonen/router/RouterNanoHTTPD.java index 6b9e270..11f5d92 100644 --- a/nanolets/src/main/java/fi/iki/elonen/router/RouterNanoHTTPD.java +++ b/nanolets/src/main/java/fi/iki/elonen/router/RouterNanoHTTPD.java @@ -36,7 +36,6 @@ package fi.iki.elonen.router; import java.io.BufferedInputStream; import java.io.File; import java.io.FileInputStream; -import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; @@ -180,55 +179,6 @@ public class RouterNanoHTTPD extends NanoHTTPD { */ public static class StaticPageHandler extends DefaultHandler { - /** - * Hashtable mapping (String)FILENAME_EXTENSION -> (String)MIME_TYPE - */ - @SuppressWarnings("serial") - private static final Map<String, String> MIME_TYPES = new HashMap<String, String>() { - - { - put("css", "text/css"); - put("htm", "text/html"); - put("html", "text/html"); - put("xml", "text/xml"); - put("java", "text/x-java-source, text/java"); - put("md", "text/plain"); - put("txt", "text/plain"); - put("asc", "text/plain"); - put("gif", "image/gif"); - put("jpg", "image/jpeg"); - put("jpeg", "image/jpeg"); - put("png", "image/png"); - put("svg", "image/svg+xml"); - put("mp3", "audio/mpeg"); - put("m3u", "audio/mpeg-url"); - put("mp4", "video/mp4"); - put("ogv", "video/ogg"); - put("flv", "video/x-flv"); - put("mov", "video/quicktime"); - put("swf", "application/x-shockwave-flash"); - put("js", "application/javascript"); - put("pdf", "application/pdf"); - put("doc", "application/msword"); - put("ogg", "application/x-ogg"); - put("zip", "application/octet-stream"); - put("exe", "application/octet-stream"); - put("class", "application/octet-stream"); - put("m3u8", "application/vnd.apple.mpegurl"); - put("ts", " video/mp2t"); - } - }; - - // Get MIME type from file name extension, if possible - private String getMimeTypeForFile(String uri) { - int dot = uri.lastIndexOf('.'); - String mime = null; - if (dot >= 0) { - mime = MIME_TYPES.get(uri.substring(dot + 1).toLowerCase()); - } - return mime == null ? "application/octet-stream" : mime; - } - private static String[] getPathArray(String uri) { String array[] = uri.split("/"); ArrayList<String> pathArray = new ArrayList<String>(); diff --git a/webserver/src/main/java/fi/iki/elonen/SimpleWebServer.java b/webserver/src/main/java/fi/iki/elonen/SimpleWebServer.java index f5415d6..3f176fe 100644 --- a/webserver/src/main/java/fi/iki/elonen/SimpleWebServer.java +++ b/webserver/src/main/java/fi/iki/elonen/SimpleWebServer.java @@ -32,11 +32,13 @@ package fi.iki.elonen; * OF THE POSSIBILITY OF SUCH DAMAGE. * #L% */ +import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FilenameFilter; import java.io.IOException; +import java.io.InputStream; import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import java.util.ArrayList; @@ -55,11 +57,6 @@ import fi.iki.elonen.util.ServerRunner; public class SimpleWebServer extends NanoHTTPD { /** - * Common mime type for dynamic content: binary - */ - public static final String MIME_DEFAULT_BINARY = "application/octet-stream"; - - /** * Default Index file names. */ @SuppressWarnings("serial") @@ -72,58 +69,26 @@ public class SimpleWebServer extends NanoHTTPD { }; /** - * Hashtable mapping (String)FILENAME_EXTENSION -> (String)MIME_TYPE - */ - @SuppressWarnings("serial") - private static final Map<String, String> MIME_TYPES = new HashMap<String, String>() { - - { - put("css", "text/css"); - put("htm", "text/html"); - put("html", "text/html"); - put("xml", "text/xml"); - put("java", "text/x-java-source, text/java"); - put("md", "text/plain"); - put("txt", "text/plain"); - put("asc", "text/plain"); - put("gif", "image/gif"); - put("jpg", "image/jpeg"); - put("jpeg", "image/jpeg"); - put("png", "image/png"); - put("svg", "image/svg+xml"); - put("mp3", "audio/mpeg"); - put("m3u", "audio/mpeg-url"); - put("mp4", "video/mp4"); - put("ogv", "video/ogg"); - put("flv", "video/x-flv"); - put("mov", "video/quicktime"); - put("swf", "application/x-shockwave-flash"); - put("js", "application/javascript"); - put("pdf", "application/pdf"); - put("doc", "application/msword"); - put("ogg", "application/x-ogg"); - put("zip", "application/octet-stream"); - put("exe", "application/octet-stream"); - put("class", "application/octet-stream"); - put("m3u8", "application/vnd.apple.mpegurl"); - put("ts", " video/mp2t"); - } - }; - - /** * The distribution licence */ - private static final String LICENCE = "Copyright (c) 2012-2013 by Paul S. Hawke, 2001,2005-2013 by Jarno Elonen, 2010 by Konstantinos Togias\n" + "\n" - + "Redistribution and use in source and binary forms, with or without\n" + "modification, are permitted provided that the following conditions\n" + "are met:\n" - + "\n" + "Redistributions of source code must retain the above copyright notice,\n" + "this list of conditions and the following disclaimer. Redistributions in\n" - + "binary form must reproduce the above copyright notice, this list of\n" + "conditions and the following disclaimer in the documentation and/or other\n" - + "materials provided with the distribution. The name of the author may not\n" + "be used to endorse or promote products derived from this software without\n" - + "specific prior written permission. \n" + " \n" + "THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\n" - + "IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\n" + "OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\n" - + "IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,\n" + "INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n" - + "NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n" + "DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n" - + "THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n" + "(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n" - + "OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."; + private static final String LICENCE; + static { + mimeTypes(); + InputStream stream = SimpleWebServer.class.getResourceAsStream("/LICENSE.txt"); + ByteArrayOutputStream bytes = new ByteArrayOutputStream(); + byte[] buffer = new byte[1024]; + int count; + String text; + try { + while ((count = stream.read(buffer)) >= 0) { + bytes.write(buffer, 0, count); + } + text = bytes.toString("UTF-8"); + } catch (IOException e) { + text = "unknown"; + } + LICENCE = text; + } private static Map<String, WebServerPlugin> mimeTypeHandlers = new HashMap<String, WebServerPlugin>(); @@ -216,7 +181,7 @@ public class SimpleWebServer extends NanoHTTPD { int dot = filename.lastIndexOf('.'); if (dot >= 0) { String extension = filename.substring(dot + 1).toLowerCase(); - SimpleWebServer.MIME_TYPES.put(extension, mimeType); + mimeTypes().put(extension, mimeType); } } SimpleWebServer.INDEX_FILE_NAMES.addAll(Arrays.asList(indexFiles)); @@ -257,8 +222,7 @@ public class SimpleWebServer extends NanoHTTPD { File f = new File(homeDir, uri); canServeUri = f.exists(); if (!canServeUri) { - String mimeTypeForFile = getMimeTypeForFile(uri); - WebServerPlugin plugin = SimpleWebServer.mimeTypeHandlers.get(mimeTypeForFile); + WebServerPlugin plugin = SimpleWebServer.mimeTypeHandlers.get(getMimeTypeForFile(uri)); if (plugin != null) { canServeUri = plugin.canServeUri(uri, homeDir); } @@ -307,16 +271,6 @@ public class SimpleWebServer extends NanoHTTPD { return newFixedLengthResponse(Response.Status.INTERNAL_ERROR, NanoHTTPD.MIME_PLAINTEXT, "INTERNAL ERROR: " + s); } - // Get MIME type from file name extension, if possible - private String getMimeTypeForFile(String uri) { - int dot = uri.lastIndexOf('.'); - String mime = null; - if (dot >= 0) { - mime = SimpleWebServer.MIME_TYPES.get(uri.substring(dot + 1).toLowerCase()); - } - return mime == null ? SimpleWebServer.MIME_DEFAULT_BINARY : mime; - } - protected Response getNotFoundResponse() { return newFixedLengthResponse(Response.Status.NOT_FOUND, NanoHTTPD.MIME_PLAINTEXT, "Error 404, file not found."); } @@ -465,7 +419,6 @@ public class SimpleWebServer extends NanoHTTPD { return respond(headers, session, uri + indexFile); } } - String mimeTypeForFile = getMimeTypeForFile(uri); WebServerPlugin plugin = SimpleWebServer.mimeTypeHandlers.get(mimeTypeForFile); Response response = null; |