aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Hawke <paul.hawke@gmail.com>2013-09-08 05:59:02 -0500
committerPaul Hawke <paul.hawke@gmail.com>2013-09-08 05:59:02 -0500
commit399229d96d32865f9979217bdc06ea8fa56e962d (patch)
tree6e970df141aa8ae921b94329ad83f7638ab9b086
parent140479555d9dca01e00bc057764df7a69c94e2c5 (diff)
downloadnanohttpd-399229d96d32865f9979217bdc06ea8fa56e962d.tar.gz
Refactoring to serve files by mime type. @psh
-rw-r--r--core/src/main/java/fi/iki/elonen/NanoHTTPD.java4
-rw-r--r--webserver/src/main/java/fi/iki/elonen/SimpleWebServer.java439
2 files changed, 234 insertions, 209 deletions
diff --git a/core/src/main/java/fi/iki/elonen/NanoHTTPD.java b/core/src/main/java/fi/iki/elonen/NanoHTTPD.java
index bfe08a5..8c81435 100644
--- a/core/src/main/java/fi/iki/elonen/NanoHTTPD.java
+++ b/core/src/main/java/fi/iki/elonen/NanoHTTPD.java
@@ -61,10 +61,6 @@ public abstract class NanoHTTPD {
*/
public static final String MIME_HTML = "text/html";
/**
- * Common mime type for dynamic content: binary
- */
- public static final String MIME_DEFAULT_BINARY = "application/octet-stream";
- /**
* Pseudo-Parameter to use to store the actual query string in the parameters map for later re-processing.
*/
private static final String QUERY_STRING_PARAMETER = "NanoHttpd.QUERY_STRING";
diff --git a/webserver/src/main/java/fi/iki/elonen/SimpleWebServer.java b/webserver/src/main/java/fi/iki/elonen/SimpleWebServer.java
index 72121e7..bff1421 100644
--- a/webserver/src/main/java/fi/iki/elonen/SimpleWebServer.java
+++ b/webserver/src/main/java/fi/iki/elonen/SimpleWebServer.java
@@ -6,6 +6,14 @@ import java.util.*;
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.
+ */
+ public static final String[] INDEX_FILE_NAMES = {"index.html", "index.htm"};
+ /**
* Hashtable mapping (String)FILENAME_EXTENSION -> (String)MIME_TYPE
*/
private static final Map<String, String> MIME_TYPES = new HashMap<String, String>() {{
@@ -35,36 +43,34 @@ public class SimpleWebServer extends NanoHTTPD {
put("exe", "application/octet-stream");
put("class", "application/octet-stream");
}};
-
/**
* 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.";
-
+ "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 final File rootDir;
private final boolean quiet;
@@ -74,7 +80,37 @@ public class SimpleWebServer extends NanoHTTPD {
this.quiet = quiet;
}
- File getRootDir() {
+ /**
+ * Starts as a standalone file server and waits for Enter.
+ */
+ public static void main(String[] args) {
+ // Defaults
+ int port = 8080;
+
+ String host = "127.0.0.1";
+ File wwwroot = new File(".").getAbsoluteFile();
+ boolean quiet = false;
+
+ // Parse command-line, with short and long versions of the options.
+ for (int i = 0; i < args.length; ++i) {
+ if (args[i].equalsIgnoreCase("-h") || args[i].equalsIgnoreCase("--host")) {
+ host = args[i + 1];
+ } else if (args[i].equalsIgnoreCase("-p") || args[i].equalsIgnoreCase("--port")) {
+ port = Integer.parseInt(args[i + 1]);
+ } else if (args[i].equalsIgnoreCase("-q") || args[i].equalsIgnoreCase("--quiet")) {
+ quiet = true;
+ } else if (args[i].equalsIgnoreCase("-d") || args[i].equalsIgnoreCase("--dir")) {
+ wwwroot = new File(args[i + 1]).getAbsoluteFile();
+ } else if (args[i].equalsIgnoreCase("--licence")) {
+ System.out.println(LICENCE + "\n");
+ break;
+ }
+ }
+
+ ServerRunner.executeInstance(new SimpleWebServer(host, port, wwwroot, quiet));
+ }
+
+ private File getRootDir() {
return rootDir;
}
@@ -100,148 +136,196 @@ public class SimpleWebServer extends NanoHTTPD {
return newUri;
}
- /**
- * Serves file from homeDir and its' subdirectories (only). Uses only URI, ignores all headers and HTTP parameters.
- */
- Response serveFile(String uri, Map<String, String> header, File homeDir) {
- Response res = null;
+ public Response serve(HTTPSession session) {
+ Map<String, String> header = session.getHeaders();
+ Map<String, String> parms = session.getParms();
+ String uri = session.getUri();
+
+ if (!quiet) {
+ System.out.println(session.getMethod() + " '" + uri + "' ");
+
+ Iterator<String> e = header.keySet().iterator();
+ while (e.hasNext()) {
+ String value = e.next();
+ System.out.println(" HDR: '" + value + "' = '" + header.get(value) + "'");
+ }
+ e = parms.keySet().iterator();
+ while (e.hasNext()) {
+ String value = e.next();
+ System.out.println(" PRM: '" + value + "' = '" + parms.get(value) + "'");
+ }
+ }
+
+ File homeDir = getRootDir();
// Make sure we won't die of an exception later
if (!homeDir.isDirectory()) {
- res = new Response(Response.Status.INTERNAL_ERROR, NanoHTTPD.MIME_PLAINTEXT, "INTERNAL ERRROR: serveFile(): given homeDir is not a directory.");
+ return createResponse(Response.Status.INTERNAL_ERROR, NanoHTTPD.MIME_PLAINTEXT, "INTERNAL ERRROR: serveFile(): given homeDir is not a directory.");
}
- if (res == null) {
- // Remove URL arguments
- uri = uri.trim().replace(File.separatorChar, '/');
- if (uri.indexOf('?') >= 0)
- uri = uri.substring(0, uri.indexOf('?'));
+ // Remove URL arguments
+ uri = uri.trim().replace(File.separatorChar, '/');
+ if (uri.indexOf('?') >= 0) {
+ uri = uri.substring(0, uri.indexOf('?'));
+ }
- // Prohibit getting out of current directory
- if (uri.startsWith("src/main") || uri.endsWith("src/main") || uri.contains("../"))
- res = new Response(Response.Status.FORBIDDEN, NanoHTTPD.MIME_PLAINTEXT, "FORBIDDEN: Won't serve ../ for security reasons.");
+ // Prohibit getting out of current directory
+ if (uri.startsWith("src/main") || uri.endsWith("src/main") || uri.contains("../")) {
+ return createResponse(Response.Status.FORBIDDEN, NanoHTTPD.MIME_PLAINTEXT, "FORBIDDEN: Won't serve ../ for security reasons.");
}
File f = new File(homeDir, uri);
- if (res == null && !f.exists()) {
- res = new Response(Response.Status.NOT_FOUND, NanoHTTPD.MIME_PLAINTEXT, "Error 404, file not found.");
+ if (!f.exists()) {
+ return createResponse(Response.Status.NOT_FOUND, NanoHTTPD.MIME_PLAINTEXT, "Error 404, file not found.");
}
+ return serveFile(uri, header, f);
+ }
+
+ /**
+ * Serves file from homeDir and its' subdirectories (only). Uses only URI, ignores all headers and HTTP parameters.
+ */
+ Response serveFile(String uri, Map<String, String> header, File file) {
// List the directory, if necessary
- if (res == null && f.isDirectory()) {
+ if (file.isDirectory()) {
// Browsers get confused without '/' after the
// directory, send a redirect.
if (!uri.endsWith("/")) {
uri += "/";
- res = new Response(Response.Status.REDIRECT, NanoHTTPD.MIME_HTML, "<html><body>Redirected: <a href=\"" + uri + "\">" + uri
- + "</a></body></html>");
+ Response res = createResponse(Response.Status.REDIRECT, NanoHTTPD.MIME_HTML, "<html><body>Redirected: <a href=\"" + uri + "\">" +
+ uri + "</a></body></html>");
res.addHeader("Location", uri);
+ return res;
}
- if (res == null) {
- // First try index.html and index.htm
- if (new File(f, "index.html").exists()) {
- f = new File(homeDir, uri + "/index.html");
- } else if (new File(f, "index.htm").exists()) {
- f = new File(homeDir, uri + "/index.htm");
- } else if (f.canRead()) {
+ // First look for index files (index.html, index.htm, etc) and if none found, list the directory if readable.
+ File indexFile = findIndexFileInDirectory(file);
+ if (indexFile == null) {
+ if (file.canRead()) {
// No index file, list the directory if it is readable
- res = new Response(listDirectory(uri, f));
+ return createResponse(Response.Status.OK, NanoHTTPD.MIME_HTML, listDirectory(uri, file));
} else {
- res = new Response(Response.Status.FORBIDDEN, NanoHTTPD.MIME_PLAINTEXT, "FORBIDDEN: No directory listing.");
+ return createResponse(Response.Status.FORBIDDEN, NanoHTTPD.MIME_PLAINTEXT, "FORBIDDEN: No directory listing.");
}
+ } else {
+ // Index file was found, so serve it.
+ file = indexFile;
}
}
+ Response res;
try {
- if (res == null) {
- // Get MIME type from file name extension, if possible
- String mime = null;
- int dot = f.getCanonicalPath().lastIndexOf('.');
- if (dot >= 0) {
- mime = MIME_TYPES.get(f.getCanonicalPath().substring(dot + 1).toLowerCase());
- }
- if (mime == null) {
- mime = NanoHTTPD.MIME_DEFAULT_BINARY;
- }
+ String mime = getMimeTypeForFile(file);
+
+ // Calculate etag
+ String etag = Integer.toHexString((file.getAbsolutePath() + file.lastModified() + "" + file.length()).hashCode());
- // Calculate etag
- String etag = Integer.toHexString((f.getAbsolutePath() + f.lastModified() + "" + f.length()).hashCode());
-
- // Support (simple) skipping:
- long startFrom = 0;
- long endAt = -1;
- String range = header.get("range");
- if (range != null) {
- if (range.startsWith("bytes=")) {
- range = range.substring("bytes=".length());
- int minus = range.indexOf('-');
- try {
- if (minus > 0) {
- startFrom = Long.parseLong(range.substring(0, minus));
- endAt = Long.parseLong(range.substring(minus + 1));
- }
- } catch (NumberFormatException ignored) {
+ // Support (simple) skipping:
+ long startFrom = 0;
+ long endAt = -1;
+ String range = header.get("range");
+ if (range != null) {
+ if (range.startsWith("bytes=")) {
+ range = range.substring("bytes=".length());
+ int minus = range.indexOf('-');
+ try {
+ if (minus > 0) {
+ startFrom = Long.parseLong(range.substring(0, minus));
+ endAt = Long.parseLong(range.substring(minus + 1));
}
+ } catch (NumberFormatException ignored) {
}
}
+ }
- // Change return code and add Content-Range header when skipping is requested
- long fileLen = f.length();
- if (range != null && startFrom >= 0) {
- if (startFrom >= fileLen) {
- res = new Response(Response.Status.RANGE_NOT_SATISFIABLE, NanoHTTPD.MIME_PLAINTEXT, "");
- res.addHeader("Content-Range", "bytes 0-0/" + fileLen);
- res.addHeader("ETag", etag);
- } else {
- if (endAt < 0) {
- endAt = fileLen - 1;
- }
- long newLen = endAt - startFrom + 1;
- if (newLen < 0) {
- newLen = 0;
- }
-
- final long dataLen = newLen;
- FileInputStream fis = new FileInputStream(f) {
- @Override
- public int available() throws IOException {
- return (int) dataLen;
- }
- };
- fis.skip(startFrom);
-
- res = new Response(Response.Status.PARTIAL_CONTENT, mime, fis);
- res.addHeader("Content-Length", "" + dataLen);
- res.addHeader("Content-Range", "bytes " + startFrom + "-" + endAt + "/" + fileLen);
- res.addHeader("ETag", etag);
- }
+ // Change return code and add Content-Range header when skipping is requested
+ long fileLen = file.length();
+ if (range != null && startFrom >= 0) {
+ if (startFrom >= fileLen) {
+ res = createResponse(Response.Status.RANGE_NOT_SATISFIABLE, NanoHTTPD.MIME_PLAINTEXT, "");
+ res.addHeader("Content-Range", "bytes 0-0/" + fileLen);
+ res.addHeader("ETag", etag);
} else {
- if (etag.equals(header.get("if-none-match")))
- res = new Response(Response.Status.NOT_MODIFIED, mime, "");
- else {
- res = new Response(Response.Status.OK, mime, new FileInputStream(f));
- res.addHeader("Content-Length", "" + fileLen);
- res.addHeader("ETag", etag);
+ if (endAt < 0) {
+ endAt = fileLen - 1;
}
+ long newLen = endAt - startFrom + 1;
+ if (newLen < 0) {
+ newLen = 0;
+ }
+
+ final long dataLen = newLen;
+ FileInputStream fis = new FileInputStream(file) {
+ @Override
+ public int available() throws IOException {
+ return (int) dataLen;
+ }
+ };
+ fis.skip(startFrom);
+
+ res = createResponse(Response.Status.PARTIAL_CONTENT, mime, fis);
+ res.addHeader("Content-Length", "" + dataLen);
+ res.addHeader("Content-Range", "bytes " + startFrom + "-" + endAt + "/" + fileLen);
+ res.addHeader("ETag", etag);
+ }
+ } else {
+ if (etag.equals(header.get("if-none-match")))
+ res = createResponse(Response.Status.NOT_MODIFIED, mime, "");
+ else {
+ res = createResponse(Response.Status.OK, mime, new FileInputStream(file));
+ res.addHeader("Content-Length", "" + fileLen);
+ res.addHeader("ETag", etag);
}
}
} catch (IOException ioe) {
- res = new Response(Response.Status.FORBIDDEN, NanoHTTPD.MIME_PLAINTEXT, "FORBIDDEN: Reading file failed.");
+ res = createResponse(Response.Status.FORBIDDEN, NanoHTTPD.MIME_PLAINTEXT, "FORBIDDEN: Reading file failed.");
+ }
+
+ return res;
+ }
+
+ // Get MIME type from file name extension, if possible
+ private String getMimeTypeForFile(File f) throws IOException {
+ String mime = null;
+ int dot = f.getCanonicalPath().lastIndexOf('.');
+ if (dot >= 0) {
+ mime = MIME_TYPES.get(f.getCanonicalPath().substring(dot + 1).toLowerCase());
}
+ return mime == null ? MIME_DEFAULT_BINARY : mime;
+ }
+
+ // Announce that the file server accepts partial content requests
+ private Response createResponse(Response.Status status, String mimeType, InputStream message) {
+ Response res = new Response(status, mimeType, message);
+ res.addHeader("Accept-Ranges", "bytes");
+ return res;
+ }
- res.addHeader("Accept-Ranges", "bytes"); // Announce that the file server accepts partial content requestes
+ // Announce that the file server accepts partial content requests
+ private Response createResponse(Response.Status status, String mimeType, String message) {
+ Response res = new Response(status, mimeType, message);
+ res.addHeader("Accept-Ranges", "bytes");
return res;
}
+ private File findIndexFileInDirectory(File directory) {
+ for (String fileName : INDEX_FILE_NAMES) {
+ File indexFile = new File(directory, fileName);
+ if (indexFile.exists()) {
+ return indexFile;
+ }
+ }
+ return null;
+ }
+
private String listDirectory(String uri, File f) {
String heading = "Directory " + uri;
- String msg = "<html><head><title>" + heading + "</title><style><!--\n"+
- "span.dirname { font-weight: bold; }\n"+
- "span.filesize { font-size: 75%; }\n"+
- "// -->\n"+
- "</style>"+
- "</head><body><h1>" + heading + "</h1>";
+ StringBuilder msg = new StringBuilder("<html><head><title>" + heading + "</title><style><!--\n" +
+ "span.dirname { font-weight: bold; }\n" +
+ "span.filesize { font-size: 75%; }\n" +
+ "// -->\n" +
+ "</style>" +
+ "</head><body><h1>" + heading + "</h1>");
String up = null;
if (uri.length() > 1) {
@@ -262,99 +346,44 @@ public class SimpleWebServer extends NanoHTTPD {
List<String> directories = Arrays.asList(f.list(new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
- return new File (dir, name).isDirectory();
+ return new File(dir, name).isDirectory();
}
}));
Collections.sort(directories);
if (up != null || directories.size() + files.size() > 0) {
- msg += "<ul>";
+ msg.append("<ul>");
if (up != null || directories.size() > 0) {
- msg += "<section class=\"directories\">";
+ msg.append("<section class=\"directories\">");
if (up != null) {
- msg += "<li><a rel=\"directory\" href=\"" + up + "\"><span class=\"dirname\">..</span></a></b></li>";
+ msg.append("<li><a rel=\"directory\" href=\"").append(up).append("\"><span class=\"dirname\">..</span></a></b></li>");
}
- for (int i = 0; i < directories.size(); i++) {
- String dir = directories.get(i) + "/";
- msg += "<li><a rel=\"directory\" href=\"" + encodeUri(uri + dir) + "\"><span class=\"dirname\">" + dir + "</span></a></b></li>";
+ for (String directory : directories) {
+ String dir = directory + "/";
+ msg.append("<li><a rel=\"directory\" href=\"").append(encodeUri(uri + dir)).append("\"><span class=\"dirname\">").append(dir).append("</span></a></b></li>");
}
- msg += "</section>";
+ msg.append("</section>");
}
if (files.size() > 0) {
- msg += "<section class=\"files\">";
- for (int i = 0; i < files.size(); i++) {
- String file = files.get(i);
-
- msg += "<li><a href=\"" + encodeUri(uri + file) + "\"><span class=\"filename\">" + file + "</span></a>";
+ msg.append("<section class=\"files\">");
+ for (String file : files) {
+ msg.append("<li><a href=\"").append(encodeUri(uri + file)).append("\"><span class=\"filename\">").append(file).append("</span></a>");
File curFile = new File(f, file);
long len = curFile.length();
- msg += "&nbsp;<span class=\"filesize\">(";
- if (len < 1024)
- msg += len + " bytes";
- else if (len < 1024 * 1024)
- msg += len / 1024 + "." + (len % 1024 / 10 % 100) + " KB";
- else
- msg += len / (1024 * 1024) + "." + len % (1024 * 1024) / 10 % 100 + " MB";
- msg += ")</span></li>";
+ msg.append("&nbsp;<span class=\"filesize\">(");
+ if (len < 1024) {
+ msg.append(len).append(" bytes");
+ } else if (len < 1024 * 1024) {
+ msg.append(len / 1024).append(".").append(len % 1024 / 10 % 100).append(" KB");
+ } else {
+ msg.append(len / (1024 * 1024)).append(".").append(len % (1024 * 1024) / 10 % 100).append(" MB");
+ }
+ msg.append(")</span></li>");
}
- msg += "</section>";
+ msg.append("</section>");
}
- msg += "</ul>";
+ msg.append("</ul>");
}
- msg += "</body></html>";
- return msg;
- }
-
- @Override
- public Response serve(String uri, Method method, Map<String, String> header, Map<String, String> parms, Map<String, String> files) {
- if (!quiet) {
- System.out.println(method + " '" + uri + "' ");
-
- Iterator<String> e = header.keySet().iterator();
- while (e.hasNext()) {
- String value = e.next();
- System.out.println(" HDR: '" + value + "' = '" + header.get(value) + "'");
- }
- e = parms.keySet().iterator();
- while (e.hasNext()) {
- String value = e.next();
- System.out.println(" PRM: '" + value + "' = '" + parms.get(value) + "'");
- }
- e = files.keySet().iterator();
- while (e.hasNext()) {
- String value = e.next();
- System.out.println(" UPLOADED: '" + value + "' = '" + files.get(value) + "'");
- }
- }
- return serveFile(uri, header, getRootDir());
- }
-
- /**
- * Starts as a standalone file server and waits for Enter.
- */
- public static void main(String[] args) {
- // Defaults
- int port = 8080;
-
- String host = "127.0.0.1";
- File wwwroot = new File(".").getAbsoluteFile();
- boolean quiet = false;
-
- // Parse command-line, with short and long versions of the options.
- for (int i = 0; i < args.length; ++i) {
- if (args[i].equalsIgnoreCase("-h") || args[i].equalsIgnoreCase("--host")) {
- host = args[i + 1];
- } else if (args[i].equalsIgnoreCase("-p") || args[i].equalsIgnoreCase("--port")) {
- port = Integer.parseInt(args[i + 1]);
- } else if (args[i].equalsIgnoreCase("-q") || args[i].equalsIgnoreCase("--quiet")) {
- quiet = true;
- } else if (args[i].equalsIgnoreCase("-d") || args[i].equalsIgnoreCase("--dir")) {
- wwwroot = new File(args[i + 1]).getAbsoluteFile();
- } else if (args[i].equalsIgnoreCase("--licence")) {
- System.out.println(LICENCE + "\n");
- break;
- }
- }
-
- ServerRunner.executeInstance(new SimpleWebServer(host, port, wwwroot, quiet));
+ msg.append("</body></html>");
+ return msg.toString();
}
}