Full Code of NanoHttpd/nanohttpd for AI

master efb2ebf85a2b cached
155 files
606.7 KB
144.9k tokens
817 symbols
1 requests
Download .txt
Showing preview only (658K chars total). Download the full file or copy to clipboard to get everything.
Repository: NanoHttpd/nanohttpd
Branch: master
Commit: efb2ebf85a2b
Files: 155
Total size: 606.7 KB

Directory structure:
gitextract_2uva_0s3/

├── .gitignore
├── .travis.yml
├── LICENSE.md
├── README.md
├── build.gradle
├── core/
│   ├── .gitignore
│   ├── build.gradle
│   ├── pom.xml
│   └── src/
│       ├── main/
│       │   ├── java/
│       │   │   └── org/
│       │   │       └── nanohttpd/
│       │   │           ├── protocols/
│       │   │           │   └── http/
│       │   │           │       ├── ClientHandler.java
│       │   │           │       ├── HTTPSession.java
│       │   │           │       ├── IHTTPSession.java
│       │   │           │       ├── NanoHTTPD.java
│       │   │           │       ├── ServerRunnable.java
│       │   │           │       ├── content/
│       │   │           │       │   ├── ContentType.java
│       │   │           │       │   ├── Cookie.java
│       │   │           │       │   └── CookieHandler.java
│       │   │           │       ├── request/
│       │   │           │       │   └── Method.java
│       │   │           │       ├── response/
│       │   │           │       │   ├── ChunkedOutputStream.java
│       │   │           │       │   ├── IStatus.java
│       │   │           │       │   ├── Response.java
│       │   │           │       │   └── Status.java
│       │   │           │       ├── sockets/
│       │   │           │       │   ├── DefaultServerSocketFactory.java
│       │   │           │       │   └── SecureServerSocketFactory.java
│       │   │           │       ├── tempfiles/
│       │   │           │       │   ├── DefaultTempFile.java
│       │   │           │       │   ├── DefaultTempFileManager.java
│       │   │           │       │   ├── DefaultTempFileManagerFactory.java
│       │   │           │       │   ├── ITempFile.java
│       │   │           │       │   └── ITempFileManager.java
│       │   │           │       └── threading/
│       │   │           │           ├── DefaultAsyncRunner.java
│       │   │           │           └── IAsyncRunner.java
│       │   │           └── util/
│       │   │               ├── IFactory.java
│       │   │               ├── IFactoryThrowing.java
│       │   │               ├── IHandler.java
│       │   │               └── ServerRunner.java
│       │   └── resources/
│       │       └── META-INF/
│       │           └── nanohttpd/
│       │               ├── default-mimetypes.properties
│       │               └── mimetypes.properties
│       ├── site/
│       │   └── site.xml
│       └── test/
│           ├── java/
│           │   └── org/
│           │       └── nanohttpd/
│           │           └── junit/
│           │               └── protocols/
│           │                   └── http/
│           │                       ├── BadRequestTest.java
│           │                       ├── CookieHandlerTest.java
│           │                       ├── CookieTest.java
│           │                       ├── HttpChunkedResponseTest.java
│           │                       ├── HttpDeleteRequestTest.java
│           │                       ├── HttpGetRequestTest.java
│           │                       ├── HttpHeadRequestTest.java
│           │                       ├── HttpKeepAliveTest.java
│           │                       ├── HttpParsingTest.java
│           │                       ├── HttpPostRequestTest.java
│           │                       ├── HttpPutRequestTest.java
│           │                       ├── HttpSSLServerTest.java
│           │                       ├── HttpServerTest.java
│           │                       ├── HttpSessionHeadersTest.java
│           │                       ├── HttpSessionTest.java
│           │                       ├── InvalidRequestTest.java
│           │                       ├── JavaIOTempDirExistTest.java
│           │                       ├── LoadKeyStoreTest.java
│           │                       ├── MimeTest.java
│           │                       ├── SSLServerSocketFactoryTest.java
│           │                       ├── ServerSocketFactoryTest.java
│           │                       ├── StatusTest.java
│           │                       └── integration/
│           │                           ├── CookieIntegrationTest.java
│           │                           ├── GZipIntegrationTest.java
│           │                           ├── GetAndPostIntegrationTest.java
│           │                           ├── IntegrationTestBase.java
│           │                           ├── PutStreamIntegrationTest.java
│           │                           └── ShutdownTest.java
│           └── resources/
│               ├── META-INF/
│               │   └── nanohttpd/
│               │       └── mimetypes.properties
│               ├── file-upload-test.htm
│               ├── keystore.jks
│               └── multipart-form-test.htm
├── fileupload/
│   ├── .gitignore
│   ├── build.gradle
│   ├── pom.xml
│   └── src/
│       ├── main/
│       │   └── java/
│       │       └── org/
│       │           └── nanohttpd/
│       │               └── fileupload/
│       │                   └── NanoFileUpload.java
│       └── test/
│           └── java/
│               └── org/
│                   └── nanohttpd/
│                       └── junit/
│                           └── fileupload/
│                               └── TestNanoFileUpLoad.java
├── markdown-plugin/
│   ├── .gitignore
│   ├── build.gradle
│   ├── pom.xml
│   └── src/
│       ├── main/
│       │   ├── java/
│       │   │   └── org/
│       │   │       └── nanohttpd/
│       │   │           └── markdown/
│       │   │               ├── MarkdownWebServerPlugin.java
│       │   │               └── MarkdownWebServerPluginInfo.java
│       │   └── resources/
│       │       └── META-INF/
│       │           └── services/
│       │               └── org.nanohttpd.webserver.WebServerPluginInfo
│       └── site/
│           └── site.xml
├── nanohttpd release perform.launch
├── nanohttpd release prepare.launch
├── nanolets/
│   ├── .gitignore
│   ├── build.gradle
│   ├── pom.xml
│   └── src/
│       ├── main/
│       │   └── java/
│       │       └── org/
│       │           └── nanohttpd/
│       │               └── router/
│       │                   └── RouterNanoHTTPD.java
│       └── test/
│           ├── java/
│           │   └── org/
│           │       └── nanohttpd/
│           │           └── junit/
│           │               └── router/
│           │                   ├── AppNanolets.java
│           │                   └── TestNanolets.java
│           └── resources/
│               ├── blabla.html
│               ├── dir/
│               │   ├── blabla.html
│               │   └── index.htm
│               └── exception.html
├── pom.xml
├── relocation/
│   ├── nanohttpd/
│   │   ├── pom.xml
│   │   └── src/
│   │       └── main/
│   │           └── resources/
│   │               └── relocated.txt
│   ├── nanohttpd-samples/
│   │   ├── pom.xml
│   │   └── src/
│   │       └── main/
│   │           └── resources/
│   │               └── relocated.txt
│   ├── nanohttpd-webserver/
│   │   ├── pom.xml
│   │   └── src/
│   │       └── main/
│   │           └── resources/
│   │               └── relocated.txt
│   ├── nanohttpd-webserver-markdown-plugin/
│   │   ├── pom.xml
│   │   └── src/
│   │       └── main/
│   │           └── resources/
│   │               └── relocated.txt
│   ├── nanohttpd-websocket/
│   │   ├── pom.xml
│   │   └── src/
│   │       └── main/
│   │           └── resources/
│   │               └── relocated.txt
│   └── pom.xml
├── samples/
│   ├── .gitignore
│   ├── build.gradle
│   ├── pom.xml
│   └── src/
│       ├── main/
│       │   └── java/
│       │       └── org/
│       │           └── nanohttpd/
│       │               └── samples/
│       │                   ├── http/
│       │                   │   ├── DebugServer.java
│       │                   │   └── HelloServer.java
│       │                   └── tempfiles/
│       │                       └── TempFilesServer.java
│       └── site/
│           └── site.xml
├── settings.gradle
├── settings.xml
├── src/
│   ├── main/
│   │   ├── checkstyle/
│   │   │   ├── checkstyle-suppressions.xml
│   │   │   └── nanohttpd-style.xml
│   │   └── formatter/
│   │       └── formatter.xml
│   └── site/
│       ├── markdown/
│       │   └── index.md
│       └── site.xml
├── webserver/
│   ├── .gitignore
│   ├── build.gradle
│   ├── pom.xml
│   └── src/
│       ├── main/
│       │   └── java/
│       │       └── org/
│       │           └── nanohttpd/
│       │               └── webserver/
│       │                   ├── InternalRewrite.java
│       │                   ├── SimpleWebServer.java
│       │                   ├── WebServerPlugin.java
│       │                   └── WebServerPluginInfo.java
│       ├── site/
│       │   └── site.xml
│       └── test/
│           ├── java/
│           │   └── org/
│           │       └── nanohttpd/
│           │           └── junit/
│           │               └── webserver/
│           │                   ├── AbstractTestHttpServer.java
│           │                   ├── DummyPlugin.java
│           │                   ├── DummyPluginInfo.java
│           │                   ├── TestCorsHttpServer.java
│           │                   ├── TestCorsHttpServerWithSingleOrigin.java
│           │                   └── TestHttpServer.java
│           └── resources/
│               ├── META-INF/
│               │   └── services/
│               │       └── org.nanohttpd.webserver.WebServerPluginInfo
│               └── testdir/
│                   ├── test.html
│                   └── testdir/
│                       ├── different.xml
│                       └── index.html
└── websocket/
    ├── .gitignore
    ├── build.gradle
    ├── pom.xml
    └── src/
        ├── main/
        │   └── java/
        │       └── org/
        │           └── nanohttpd/
        │               ├── protocols/
        │               │   └── websockets/
        │               │       ├── CloseCode.java
        │               │       ├── CloseFrame.java
        │               │       ├── NanoWSD.java
        │               │       ├── OpCode.java
        │               │       ├── State.java
        │               │       ├── WebSocket.java
        │               │       ├── WebSocketException.java
        │               │       └── WebSocketFrame.java
        │               └── samples/
        │                   └── websockets/
        │                       ├── DebugWebSocketServer.java
        │                       └── EchoSocketSample.java
        ├── site/
        │   └── site.xml
        └── test/
            ├── java/
            │   └── org/
            │       └── nanohttpd/
            │           └── junit/
            │               └── protocols/
            │                   └── websockets/
            │                       ├── EchoWebSocketsTest.java
            │                       ├── SimpleEchoSocket.java
            │                       └── WebSocketResponseHandlerTest.java
            └── resources/
                └── echo-test.html

================================================
FILE CONTENTS
================================================

================================================
FILE: .gitignore
================================================
out
build
target

*.iml
*.ipr
*.iws
*.class

.idea
.classpath
.project
.gradle
gradle/
gradlew
gradlew.bat

# Vim Backup/Swap Files
*~
.swp
.*.swp

/.settings/
/LICENSE.txt


================================================
FILE: .travis.yml
================================================
language: java
jdk:
- openjdk7

before_install:
  - cat ~/.m2/settings.xml
  - rm  ~/.m2/settings.xml

install:
  - mvn install -DskipTests=true

script:
    - mvn test; export MAVEN_RESULT=$?
    - if [ "$MAVEN_RESULT" -ne 0 ]; then exit 1; fi
    - if [ "$TRAVIS_BRANCH" = "master" -a "$TRAVIS_PULL_REQUEST" = "false" ]; then mvn clean deploy --quiet --settings settings.xml; fi

after_success:
  - mvn clean test jacoco:report coveralls:report
  
 
notifications:
  email:
    - richard.vannieuwenhoven@adesso.at
    - elonen@iki.fi
    - diogo.duarte@techie.com
    
env:
 global:
  - secure: "OtD0z3y4/OjSzg8irVD8v/u0TElcw8AiCCXb7a0UQEnTpGxcf5DOdkvHv0hF4xjHKFtlMMHxevW+a4C4NuFR8it8ZJ/i2m24reB28JicDcRQY9nwV/BR/T08CRG9KDz5EuTHgfPJDF0y+5MiVNwJVhHFviBWKuXyIuYouJ5IHgc="
  - secure: "tgTVycNLwYDM3U0EVK1TkffylQHfZihvSDC9QoZEo+wz9aBBLoAtUJP7DWltRQFOkfTeGltGHEfGM2/qkIG6Wz+hNFG/fveHqyI01JWXc64d7yBm7agaCP5uTtt2wjaZ7ZK5Mps5QoufblYu+j9gb2v31t9IdsJ9PUs0+wgE/WU="
  


================================================
FILE: LICENSE.md
================================================
Copyright (c) 2012-2013 by Paul S. Hawke, 2001,2005-2013 by Jarno Elonen, 2010 by Konstantinos Togias
All rights reserved.

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.

* 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.

* Neither the name of the NanoHttpd organization 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.


================================================
FILE: README.md
================================================
## NanoHTTPD – a tiny web server in Java

*NanoHTTPD* is a light-weight HTTP server designed for embedding in other applications, released under a Modified BSD licence.

It is being developed at Github and uses Apache Maven for builds & unit testing:

 * Build status: [![Build Status](https://api.travis-ci.org/NanoHttpd/nanohttpd.png)](https://travis-ci.org/NanoHttpd/nanohttpd)
 * Coverage Status: [![Coverage Status](https://coveralls.io/repos/NanoHttpd/nanohttpd/badge.svg)](https://coveralls.io/r/NanoHttpd/nanohttpd)
 * Current central released version: [![Maven Central](https://maven-badges.herokuapp.com/maven-central/org.nanohttpd/nanohttpd/badge.svg)](https://maven-badges.herokuapp.com/maven-central/org.nanohttpd/nanohttpd)

## Quickstart

We'll create a custom HTTP server project using Maven for build/dep system. This tutorial assumes you are using a Unix variant and a shell. First, install Maven and Java SDK if not already installed. Then run:

    mvn compile
    mvn exec:java -pl webserver -Dexec.mainClass="org.nanohttpd.webserver.SimpleWebServer"
    
You should now have a HTTP file server running on <http://localhost:8080/>.

### Custom web app

Let's raise the bar and build a custom web application next:

    mvn archetype:generate -DgroupId=com.example -DartifactId=myHellopApp -DinteractiveMode=false
    cd myHellopApp
    
Edit `pom.xml`, and add this between \<dependencies\>:
 
	<dependency>
		<groupId>org.nanohttpd</groupId> <!-- <groupId>com.nanohttpd</groupId> for 2.1.0 and earlier -->
		<artifactId>nanohttpd</artifactId>
		<version>2.2.0</version>
	</dependency>
	
Edit `src/main/java/com/example/App.java` and replace it with:
```java
    package com.example;
    
    import java.io.IOException;
    import java.util.Map;
    
    import fi.iki.elonen.NanoHTTPD;
    // NOTE: If you're using NanoHTTPD >= 3.0.0 the namespace is different,
    //       instead of the above import use the following:
	// import org.nanohttpd.NanoHTTPD;
    
    public class App extends NanoHTTPD {
    
        public App() throws IOException {
            super(8080);
            start(NanoHTTPD.SOCKET_READ_TIMEOUT, false);
            System.out.println("\nRunning! Point your browsers to http://localhost:8080/ \n");
        }
    
        public static void main(String[] args) {
            try {
                new App();
            } catch (IOException ioe) {
                System.err.println("Couldn't start server:\n" + ioe);
            }
        }
    
        @Override
        public Response serve(IHTTPSession session) {
            String msg = "<html><body><h1>Hello server</h1>\n";
            Map<String, String> parms = session.getParms();
            if (parms.get("username") == null) {
                msg += "<form action='?' method='get'>\n  <p>Your name: <input type='text' name='username'></p>\n" + "</form>\n";
            } else {
                msg += "<p>Hello, " + parms.get("username") + "!</p>";
            }
            return newFixedLengthResponse(msg + "</body></html>\n");
        }
    }
```

Compile and run the server:
 
    mvn compile
    mvn exec:java -Dexec.mainClass="com.example.App"
    
If it started ok, point your browser at <http://localhost:8080/> and enjoy a web server that asks your name and replies with a greeting. 

### Nanolets

Nanolets are like servlets only that they have a extremely low profile. They offer an easy to use system for a more complex server application.
This text has to be extended with an example, so for now take a look at the unit tests for the usage. <https://github.com/NanoHttpd/nanohttpd/blob/master/nanolets/src/test/java/org/nanohttpd/junit/router/AppNanolets.java>

## Status

We are currently in the process of stabilizing NanoHTTPD from the many pull requests and feature requests that were integrated over the last few months. The next release will come soon, and there will not be any more "intended" major changes before the next release. If you want to use the bleeding edge version, you can clone it from Github, or get it from sonatype.org (see "Maven dependencies / Living on the edge" below).

## Project structure

NanoHTTPD project currently consist of four parts:

 * `/core` – Fully functional HTTP(s) server consisting of one (1) Java file, ready to be customized/inherited for your own project.

 * `/samples` – Simple examples on how to customize NanoHTTPD. See *HelloServer.java* for a killer app that greets you enthusiastically!

 * `/websocket` – Websocket implementation, also in a single Java file. Depends on core.

 * `/webserver` – Standalone file server. Run & enjoy. A popular use seems to be serving files out off an Android device.

 * `/nanolets` – Standalone nano app server, giving a servlet like system to the implementor.

 * `/fileupload` – integration of the apache common file upload library.

## Features
### Core
* Only one Java file, providing HTTP 1.1 support.
* No fixed config files, logging, authorization etc. (Implement by yourself if you need them. Errors are passed to java.util.logging, though.)
* Support for HTTPS (SSL).
* Basic support for cookies.
* Supports parameter parsing of GET and POST methods.
* Some built-in support for HEAD, POST and DELETE requests. You can easily implement/customize any HTTP method, though.
* Supports file upload. Uses memory for small uploads, temp files for large ones.
* Never caches anything.
* Does not limit bandwidth, request time or simultaneous connections by default.
* All header names are converted to lower case so they don't vary between browsers/clients.
* Persistent connections (Connection "keep-alive") support allowing multiple requests to be served over a single socket connection.

### Websocket
* Tested on Firefox, Chrome and IE.

### Webserver
* Default code serves files and shows (prints on console) all HTTP parameters and headers.
* Supports both dynamic content and file serving.
* File server supports directory listing, `index.html` and `index.htm`.
* File server supports partial content (streaming & continue download).
* File server supports ETags.
* File server does the 301 redirection trick for directories without `/`.
* File server serves also very long files without memory overhead.
* Contains a built-in list of most common MIME types.
* Runtime extension support (extensions that serve particular MIME types) - example extension that serves Markdown formatted files. Simply including an extension JAR in the webserver classpath is enough for the extension to be loaded.
* Simple [CORS](https://en.wikipedia.org/wiki/Cross-origin_resource_sharing) support via `--cors` parameter
  * by default serves `Access-Control-Allow-Headers: origin,accept,content-type`
  * possibility to set `Access-Control-Allow-Headers` by setting System property: `AccessControlAllowHeader`
  * _example: _ `-DAccessControlAllowHeader=origin,accept,content-type,Authorization`
  * possible values:
      * `--cors`: activates CORS support, `Access-Control-Allow-Origin` will be set to `*`.
      * `--cors=some_value`: `Access-Control-Allow-Origin` will be set to `some_value`. 

**_CORS argument examples_**


* `--cors=http://appOne.company.com`
* `--cors="http://appOne.company.com, http://appTwo.company.com"`: note the double quotes so that the two URLs are considered part of a single argument.

## Maven dependencies

NanoHTTPD is a Maven based project and deployed to central. Most development environments have means to access the central repository. The coordinates to use in Maven are: 

	<dependencies>
		<dependency>
			<groupId>org.nanohttpd</groupId> <!-- <groupId>com.nanohttpd</groupId> for 2.1.0 and earlier -->
			<artifactId>nanohttpd</artifactId>
			<version>CURRENT_VERSION</version>
		</dependency>
	</dependencies>

(Replace `CURRENT_VERSION` with whatever is reported latest at <http://nanohttpd.org/>.)

The coordinates for your development environment should correspond to these. When looking for an older version take care because we switched groupId from *com.nanohttpd* to *org.nanohttpd* in mid 2015.

Next it depends what you are using NanoHTTPD for, there are three main usages.

## Gradle dependencies

In gradle you can use NanoHTTPD the same way because gradle accesses the same central repository:

	dependencies {
		runtime(
			[group: 'org.nanohttpd', name: 'nanohttpd', version: 'CURRENT_VERSION'],
		)
	}

(Replace `CURRENT_VERSION` with whatever is reported latest at <http://nanohttpd.org/>.)

Just replace the name with the artifact id of the module you want to use and gradle will find it for you. 

### Develop your own specialized HTTP service

For a specialized HTTP (HTTPS) service you can use the module with artifactId *nanohttpd*.

		<dependency>
			<groupId>org.nanohttpd</groupId> <!-- <groupId>com.nanohttpd</groupId> for 2.1.0 and earlier -->
			<artifactId>nanohttpd</artifactId>
			<version>CURRENT_VERSION</version>
		</dependency>
		
Here you write your own subclass of *org.nanohttpd.NanoHTTPD* to configure and to serve the requests.
  
### Develop a websocket based service    

For a specialized websocket service you can use the module with artifactId *nanohttpd-websocket*.

		<dependency>
			<groupId>org.nanohttpd</groupId> <!-- <groupId>com.nanohttpd</groupId> for 2.1.0 and earlier -->
			<artifactId>nanohttpd-websocket</artifactId>
			<version>CURRENT_VERSION</version>
		</dependency>

Here you write your own subclass of *org.nanohttpd.NanoWebSocketServer* to configure and to serve the websocket requests. A small standard echo example is included as *org.nanohttpd.samples.echo.DebugWebSocketServer*. You can use it as a starting point to implement your own services.

### Develop a custom HTTP file server    

For a more classic approach, perhaps to just create a HTTP server serving mostly service files from your disk, you can use the module with artifactId *nanohttpd-webserver*.

		<dependency>
			<groupId>org.nanohttpd</groupId>
			<artifactId>nanohttpd-webserver</artifactId>
			<version>CURRENT_VERSION</version>
		</dependency>

The included class *org.nanohttpd.SimpleWebServer* is intended to be used as a starting point for your own implementation but it also can be used as is. Starting the class as is will start a HTTP server on port 8080 and publishing the current directory.

### Living on the edge

The latest Github master version can be fetched through sonatype.org:

	<dependencies>
		<dependency>
			<artifactId>nanohttpd</artifactId>
			<groupId>org.nanohttpd</groupId>
			<version>XXXXX-SNAPSHOT</version>
		</dependency>
	</dependencies>
	...
	<repositories>
		<repository>
			<id>sonatype-snapshots</id>
			<url>https://oss.sonatype.org/content/repositories/snapshots</url>
			<snapshots>
				<enabled>true</enabled>
			</snapshots>
		</repository>
	</repositories>

### generating an self signed SSL certificate

Just a hint how to generate a certificate for localhost.

	keytool -genkey -keyalg RSA -alias selfsigned -keystore keystore.jks -storepass password -validity 360 -keysize 2048 -ext SAN=DNS:localhost,IP:127.0.0.1  -validity 9999

This will generate a keystore file named 'keystore.jks' with a self signed certificate for a host named localhost with the IP address 127.0.0.1 . Now
you can use:

	server.makeSecure(NanoHTTPD.makeSSLSocketFactory("/keystore.jks", "password".toCharArray()), null);

Before you start the server to make NanoHTTPD serve HTTPS connections, when you make sure 'keystore.jks' is in your classpath.
 
-----

*Thank you to everyone who has reported bugs and suggested fixes.*


================================================
FILE: build.gradle
================================================
allprojects {
	apply plugin: 'java'
	apply plugin: 'idea'
	
	group = 'org.nanohttpd'
	version = '2.3.2-SNAPSHOT'
}

subprojects {
	apply plugin: 'java'
	sourceCompatibility = 1.7
	targetCompatibility = 1.7
	
	repositories {
		jcenter()
	}
	
	dependencies {
		testCompile group: 'junit', name: 'junit', version: '4.12'
	}
}

task wrapper(type: Wrapper) {
	gradleVersion = "4.4.1"
}


================================================
FILE: core/.gitignore
================================================
/.settings/
/LICENSE.txt


================================================
FILE: core/build.gradle
================================================
description = 'NanoHttpd-Core'

dependencies {
	testCompile group: 'org.apache.httpcomponents', name: 'httpclient', version: '4.2.5'
	testCompile group: 'org.apache.httpcomponents', name: 'httpmime', version: '4.2.5'
}

task wrapper(type: Wrapper) {
	gradleVersion = "4.4.1"
}


================================================
FILE: core/pom.xml
================================================
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.nanohttpd</groupId>
		<artifactId>nanohttpd-project</artifactId>
		<version>2.3.2-SNAPSHOT</version>
	</parent>
	<artifactId>nanohttpd</artifactId>
	<packaging>jar</packaging>
	<name>NanoHttpd-Core</name>
	<dependencies>
		<dependency>
			<groupId>org.apache.httpcomponents</groupId>
			<artifactId>httpclient</artifactId>
			<version>4.2.5</version>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>org.apache.httpcomponents</groupId>
			<artifactId>httpmime</artifactId>
			<version>4.2.5</version>
			<scope>test</scope>
		</dependency>
	</dependencies>
	<properties>
		<minimal.coverage>0.82</minimal.coverage>
	</properties>
</project>


================================================
FILE: core/src/main/java/org/nanohttpd/protocols/http/ClientHandler.java
================================================
package org.nanohttpd.protocols.http;

/*
 * #%L
 * NanoHttpd-Core
 * %%
 * Copyright (C) 2012 - 2016 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.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.net.SocketException;
import java.net.SocketTimeoutException;
import java.util.logging.Level;

import org.nanohttpd.protocols.http.tempfiles.ITempFileManager;

/**
 * The runnable that will be used for every new client connection.
 */
public class ClientHandler implements Runnable {

    private final NanoHTTPD httpd;

    private final InputStream inputStream;

    private final Socket acceptSocket;

    public ClientHandler(NanoHTTPD httpd, InputStream inputStream, Socket acceptSocket) {
        this.httpd = httpd;
        this.inputStream = inputStream;
        this.acceptSocket = acceptSocket;
    }

    public void close() {
        NanoHTTPD.safeClose(this.inputStream);
        NanoHTTPD.safeClose(this.acceptSocket);
    }

    @Override
    public void run() {
        OutputStream outputStream = null;
        try {
            outputStream = this.acceptSocket.getOutputStream();
            ITempFileManager tempFileManager = httpd.getTempFileManagerFactory().create();
            HTTPSession session = new HTTPSession(httpd, tempFileManager, this.inputStream, outputStream, this.acceptSocket.getInetAddress());
            while (!this.acceptSocket.isClosed()) {
                session.execute();
            }
        } catch (Exception e) {
            // When the socket is closed by the client,
            // we throw our own SocketException
            // to break the "keep alive" loop above. If
            // the exception was anything other
            // than the expected SocketException OR a
            // SocketTimeoutException, print the
            // stacktrace
            if (!(e instanceof SocketException && "NanoHttpd Shutdown".equals(e.getMessage())) && !(e instanceof SocketTimeoutException)) {
                NanoHTTPD.LOG.log(Level.SEVERE, "Communication with the client broken, or an bug in the handler code", e);
            }
        } finally {
            NanoHTTPD.safeClose(outputStream);
            NanoHTTPD.safeClose(this.inputStream);
            NanoHTTPD.safeClose(this.acceptSocket);
            httpd.asyncRunner.closed(this);
        }
    }
}


================================================
FILE: core/src/main/java/org/nanohttpd/protocols/http/HTTPSession.java
================================================
package org.nanohttpd.protocols.http;

/*
 * #%L
 * NanoHttpd-Core
 * %%
 * Copyright (C) 2012 - 2016 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.BufferedInputStream;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataOutput;
import java.io.DataOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.RandomAccessFile;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.SocketTimeoutException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.StringTokenizer;
import java.util.logging.Level;
import java.util.regex.Matcher;

import javax.net.ssl.SSLException;

import org.nanohttpd.protocols.http.NanoHTTPD.ResponseException;
import org.nanohttpd.protocols.http.content.ContentType;
import org.nanohttpd.protocols.http.content.CookieHandler;
import org.nanohttpd.protocols.http.request.Method;
import org.nanohttpd.protocols.http.response.Response;
import org.nanohttpd.protocols.http.response.Status;
import org.nanohttpd.protocols.http.tempfiles.ITempFile;
import org.nanohttpd.protocols.http.tempfiles.ITempFileManager;

public class HTTPSession implements IHTTPSession {

    public static final String POST_DATA = "postData";

    private static final int REQUEST_BUFFER_LEN = 512;

    private static final int MEMORY_STORE_LIMIT = 1024;

    public static final int BUFSIZE = 8192;

    public static final int MAX_HEADER_SIZE = 1024;

    private final NanoHTTPD httpd;

    private final ITempFileManager tempFileManager;

    private final OutputStream outputStream;

    private final BufferedInputStream inputStream;

    private int splitbyte;

    private int rlen;

    private String uri;

    private Method method;

    private Map<String, List<String>> parms;

    private Map<String, String> headers;

    private CookieHandler cookies;

    private String queryParameterString;

    private String remoteIp;

    private String protocolVersion;

    public HTTPSession(NanoHTTPD httpd, ITempFileManager tempFileManager, InputStream inputStream, OutputStream outputStream) {
        this.httpd = httpd;
        this.tempFileManager = tempFileManager;
        this.inputStream = new BufferedInputStream(inputStream, HTTPSession.BUFSIZE);
        this.outputStream = outputStream;
    }

    public HTTPSession(NanoHTTPD httpd, ITempFileManager tempFileManager, InputStream inputStream, OutputStream outputStream, InetAddress inetAddress) {
        this.httpd = httpd;
        this.tempFileManager = tempFileManager;
        this.inputStream = new BufferedInputStream(inputStream, HTTPSession.BUFSIZE);
        this.outputStream = outputStream;
        this.remoteIp = inetAddress.isLoopbackAddress() || inetAddress.isAnyLocalAddress() ? "127.0.0.1" : inetAddress.getHostAddress().toString();
        this.headers = new HashMap<String, String>();
    }

    /**
     * Decodes the sent headers and loads the data into Key/value pairs
     */
    private void decodeHeader(BufferedReader in, Map<String, String> pre, Map<String, List<String>> parms, Map<String, String> headers) throws ResponseException {
        try {
            // Read the request line
            String inLine = in.readLine();
            if (inLine == null) {
                return;
            }

            StringTokenizer st = new StringTokenizer(inLine);
            if (!st.hasMoreTokens()) {
                throw new ResponseException(Status.BAD_REQUEST, "BAD REQUEST: Syntax error. Usage: GET /example/file.html");
            }

            pre.put("method", st.nextToken());

            if (!st.hasMoreTokens()) {
                throw new ResponseException(Status.BAD_REQUEST, "BAD REQUEST: Missing URI. Usage: GET /example/file.html");
            }

            String uri = st.nextToken();

            // Decode parameters from the URI
            int qmi = uri.indexOf('?');
            if (qmi >= 0) {
                decodeParms(uri.substring(qmi + 1), parms);
                uri = NanoHTTPD.decodePercent(uri.substring(0, qmi));
            } else {
                uri = NanoHTTPD.decodePercent(uri);
            }

            // If there's another token, its protocol version,
            // followed by HTTP headers.
            // NOTE: this now forces header names lower case since they are
            // case insensitive and vary by client.
            if (st.hasMoreTokens()) {
                protocolVersion = st.nextToken();
            } else {
                protocolVersion = "HTTP/1.1";
                NanoHTTPD.LOG.log(Level.FINE, "no protocol version specified, strange. Assuming HTTP/1.1.");
            }
            String line = in.readLine();
            while (line != null && !line.trim().isEmpty()) {
                int p = line.indexOf(':');
                if (p >= 0) {
                    headers.put(line.substring(0, p).trim().toLowerCase(Locale.US), line.substring(p + 1).trim());
                }
                line = in.readLine();
            }

            pre.put("uri", uri);
        } catch (IOException ioe) {
            throw new ResponseException(Status.INTERNAL_ERROR, "SERVER INTERNAL ERROR: IOException: " + ioe.getMessage(), ioe);
        }
    }

    /**
     * Decodes the Multipart Body data and put it into Key/Value pairs.
     */
    private void decodeMultipartFormData(ContentType contentType, ByteBuffer fbuf, Map<String, List<String>> parms, Map<String, String> files) throws ResponseException {
        int pcount = 0;
        try {
            int[] boundaryIdxs = getBoundaryPositions(fbuf, contentType.getBoundary().getBytes());
            if (boundaryIdxs.length < 2) {
                throw new ResponseException(Status.BAD_REQUEST, "BAD REQUEST: Content type is multipart/form-data but contains less than two boundary strings.");
            }

            byte[] partHeaderBuff = new byte[MAX_HEADER_SIZE];
            for (int boundaryIdx = 0; boundaryIdx < boundaryIdxs.length - 1; boundaryIdx++) {
                fbuf.position(boundaryIdxs[boundaryIdx]);
                int len = (fbuf.remaining() < MAX_HEADER_SIZE) ? fbuf.remaining() : MAX_HEADER_SIZE;
                fbuf.get(partHeaderBuff, 0, len);
                BufferedReader in =
                        new BufferedReader(new InputStreamReader(new ByteArrayInputStream(partHeaderBuff, 0, len), Charset.forName(contentType.getEncoding())), len);

                int headerLines = 0;
                // First line is boundary string
                String mpline = in.readLine();
                headerLines++;
                if (mpline == null || !mpline.contains(contentType.getBoundary())) {
                    throw new ResponseException(Status.BAD_REQUEST, "BAD REQUEST: Content type is multipart/form-data but chunk does not start with boundary.");
                }

                String partName = null, fileName = null, partContentType = null;
                // Parse the reset of the header lines
                mpline = in.readLine();
                headerLines++;
                while (mpline != null && mpline.trim().length() > 0) {
                    Matcher matcher = NanoHTTPD.CONTENT_DISPOSITION_PATTERN.matcher(mpline);
                    if (matcher.matches()) {
                        String attributeString = matcher.group(2);
                        matcher = NanoHTTPD.CONTENT_DISPOSITION_ATTRIBUTE_PATTERN.matcher(attributeString);
                        while (matcher.find()) {
                            String key = matcher.group(1);
                            if ("name".equalsIgnoreCase(key)) {
                                partName = matcher.group(2);
                            } else if ("filename".equalsIgnoreCase(key)) {
                                fileName = matcher.group(2);
                                // add these two line to support multiple
                                // files uploaded using the same field Id
                                if (!fileName.isEmpty()) {
                                    if (pcount > 0)
                                        partName = partName + String.valueOf(pcount++);
                                    else
                                        pcount++;
                                }
                            }
                        }
                    }
                    matcher = NanoHTTPD.CONTENT_TYPE_PATTERN.matcher(mpline);
                    if (matcher.matches()) {
                        partContentType = matcher.group(2).trim();
                    }
                    mpline = in.readLine();
                    headerLines++;
                }
                int partHeaderLength = 0;
                while (headerLines-- > 0) {
                    partHeaderLength = scipOverNewLine(partHeaderBuff, partHeaderLength);
                }
                // Read the part data
                if (partHeaderLength >= len - 4) {
                    throw new ResponseException(Status.INTERNAL_ERROR, "Multipart header size exceeds MAX_HEADER_SIZE.");
                }
                int partDataStart = boundaryIdxs[boundaryIdx] + partHeaderLength;
                int partDataEnd = boundaryIdxs[boundaryIdx + 1] - 4;

                fbuf.position(partDataStart);

                List<String> values = parms.get(partName);
                if (values == null) {
                    values = new ArrayList<String>();
                    parms.put(partName, values);
                }

                if (partContentType == null) {
                    // Read the part into a string
                    byte[] data_bytes = new byte[partDataEnd - partDataStart];
                    fbuf.get(data_bytes);

                    values.add(new String(data_bytes, contentType.getEncoding()));
                } else {
                    // Read it into a file
                    String path = saveTmpFile(fbuf, partDataStart, partDataEnd - partDataStart, fileName);
                    if (!files.containsKey(partName)) {
                        files.put(partName, path);
                    } else {
                        int count = 2;
                        while (files.containsKey(partName + count)) {
                            count++;
                        }
                        files.put(partName + count, path);
                    }
                    values.add(fileName);
                }
            }
        } catch (ResponseException re) {
            throw re;
        } catch (Exception e) {
            throw new ResponseException(Status.INTERNAL_ERROR, e.toString());
        }
    }

    private int scipOverNewLine(byte[] partHeaderBuff, int index) {
        while (partHeaderBuff[index] != '\n') {
            index++;
        }
        return ++index;
    }

    /**
     * Decodes parameters in percent-encoded URI-format ( e.g.
     * "name=Jack%20Daniels&pass=Single%20Malt" ) and adds them to given Map.
     */
    private void decodeParms(String parms, Map<String, List<String>> p) {
        if (parms == null) {
            this.queryParameterString = "";
            return;
        }

        this.queryParameterString = parms;
        StringTokenizer st = new StringTokenizer(parms, "&");
        while (st.hasMoreTokens()) {
            String e = st.nextToken();
            int sep = e.indexOf('=');
            String key = null;
            String value = null;

            if (sep >= 0) {
                key = NanoHTTPD.decodePercent(e.substring(0, sep)).trim();
                value = NanoHTTPD.decodePercent(e.substring(sep + 1));
            } else {
                key = NanoHTTPD.decodePercent(e).trim();
                value = "";
            }

            List<String> values = p.get(key);
            if (values == null) {
                values = new ArrayList<String>();
                p.put(key, values);
            }

            values.add(value);
        }
    }

    @Override
    public void execute() throws IOException {
        Response r = null;
        try {
            // Read the first 8192 bytes.
            // The full header should fit in here.
            // Apache's default header limit is 8KB.
            // Do NOT assume that a single read will get the entire header
            // at once!
            byte[] buf = new byte[HTTPSession.BUFSIZE];
            this.splitbyte = 0;
            this.rlen = 0;

            int read = -1;
            this.inputStream.mark(HTTPSession.BUFSIZE);
            try {
                read = this.inputStream.read(buf, 0, HTTPSession.BUFSIZE);
            } catch (SSLException e) {
                throw e;
            } catch (IOException e) {
                NanoHTTPD.safeClose(this.inputStream);
                NanoHTTPD.safeClose(this.outputStream);
                throw new SocketException("NanoHttpd Shutdown");
            }
            if (read == -1) {
                // socket was been closed
                NanoHTTPD.safeClose(this.inputStream);
                NanoHTTPD.safeClose(this.outputStream);
                throw new SocketException("NanoHttpd Shutdown");
            }
            while (read > 0) {
                this.rlen += read;
                this.splitbyte = findHeaderEnd(buf, this.rlen);
                if (this.splitbyte > 0) {
                    break;
                }
                read = this.inputStream.read(buf, this.rlen, HTTPSession.BUFSIZE - this.rlen);
            }

            if (this.splitbyte < this.rlen) {
                this.inputStream.reset();
                this.inputStream.skip(this.splitbyte);
            }

            this.parms = new HashMap<String, List<String>>();
            if (null == this.headers) {
                this.headers = new HashMap<String, String>();
            } else {
                this.headers.clear();
            }

            // Create a BufferedReader for parsing the header.
            BufferedReader hin = new BufferedReader(new InputStreamReader(new ByteArrayInputStream(buf, 0, this.rlen)));

            // Decode the header into parms and header java properties
            Map<String, String> pre = new HashMap<String, String>();
            decodeHeader(hin, pre, this.parms, this.headers);

            if (null != this.remoteIp) {
                this.headers.put("remote-addr", this.remoteIp);
                this.headers.put("http-client-ip", this.remoteIp);
            }

            this.method = Method.lookup(pre.get("method"));
            if (this.method == null) {
                throw new ResponseException(Status.BAD_REQUEST, "BAD REQUEST: Syntax error. HTTP verb " + pre.get("method") + " unhandled.");
            }

            this.uri = pre.get("uri");

            this.cookies = new CookieHandler(this.headers);

            String connection = this.headers.get("connection");
            boolean keepAlive = "HTTP/1.1".equals(protocolVersion) && (connection == null || !connection.matches("(?i).*close.*"));

            // Ok, now do the serve()

            // TODO: long body_size = getBodySize();
            // TODO: long pos_before_serve = this.inputStream.totalRead()
            // (requires implementation for totalRead())
            r = httpd.handle(this);
            // TODO: this.inputStream.skip(body_size -
            // (this.inputStream.totalRead() - pos_before_serve))

            if (r == null) {
                throw new ResponseException(Status.INTERNAL_ERROR, "SERVER INTERNAL ERROR: Serve() returned a null response.");
            } else {
                String acceptEncoding = this.headers.get("accept-encoding");
                this.cookies.unloadQueue(r);
                r.setRequestMethod(this.method);
                if (acceptEncoding == null || !acceptEncoding.contains("gzip")) {
                    r.setUseGzip(false);
                }
                r.setKeepAlive(keepAlive);
                r.send(this.outputStream);
            }
            if (!keepAlive || r.isCloseConnection()) {
                throw new SocketException("NanoHttpd Shutdown");
            }
        } catch (SocketException e) {
            // throw it out to close socket object (finalAccept)
            throw e;
        } catch (SocketTimeoutException ste) {
            // treat socket timeouts the same way we treat socket exceptions
            // i.e. close the stream & finalAccept object by throwing the
            // exception up the call stack.
            throw ste;
        } catch (SSLException ssle) {
            Response resp = Response.newFixedLengthResponse(Status.INTERNAL_ERROR, NanoHTTPD.MIME_PLAINTEXT, "SSL PROTOCOL FAILURE: " + ssle.getMessage());
            resp.send(this.outputStream);
            NanoHTTPD.safeClose(this.outputStream);
        } catch (IOException ioe) {
            Response resp = Response.newFixedLengthResponse(Status.INTERNAL_ERROR, NanoHTTPD.MIME_PLAINTEXT, "SERVER INTERNAL ERROR: IOException: " + ioe.getMessage());
            resp.send(this.outputStream);
            NanoHTTPD.safeClose(this.outputStream);
        } catch (ResponseException re) {
            Response resp = Response.newFixedLengthResponse(re.getStatus(), NanoHTTPD.MIME_PLAINTEXT, re.getMessage());
            resp.send(this.outputStream);
            NanoHTTPD.safeClose(this.outputStream);
        } finally {
            NanoHTTPD.safeClose(r);
            this.tempFileManager.clear();
        }
    }

    /**
     * Find byte index separating header from body. It must be the last byte of
     * the first two sequential new lines.
     */
    private int findHeaderEnd(final byte[] buf, int rlen) {
        int splitbyte = 0;
        while (splitbyte + 1 < rlen) {

            // RFC2616
            if (buf[splitbyte] == '\r' && buf[splitbyte + 1] == '\n' && splitbyte + 3 < rlen && buf[splitbyte + 2] == '\r' && buf[splitbyte + 3] == '\n') {
                return splitbyte + 4;
            }

            // tolerance
            if (buf[splitbyte] == '\n' && buf[splitbyte + 1] == '\n') {
                return splitbyte + 2;
            }
            splitbyte++;
        }
        return 0;
    }

    /**
     * Find the byte positions where multipart boundaries start. This reads a
     * large block at a time and uses a temporary buffer to optimize (memory
     * mapped) file access.
     */
    private int[] getBoundaryPositions(ByteBuffer b, byte[] boundary) {
        int[] res = new int[0];
        if (b.remaining() < boundary.length) {
            return res;
        }

        int search_window_pos = 0;
        byte[] search_window = new byte[4 * 1024 + boundary.length];

        int first_fill = (b.remaining() < search_window.length) ? b.remaining() : search_window.length;
        b.get(search_window, 0, first_fill);
        int new_bytes = first_fill - boundary.length;

        do {
            // Search the search_window
            for (int j = 0; j < new_bytes; j++) {
                for (int i = 0; i < boundary.length; i++) {
                    if (search_window[j + i] != boundary[i])
                        break;
                    if (i == boundary.length - 1) {
                        // Match found, add it to results
                        int[] new_res = new int[res.length + 1];
                        System.arraycopy(res, 0, new_res, 0, res.length);
                        new_res[res.length] = search_window_pos + j;
                        res = new_res;
                    }
                }
            }
            search_window_pos += new_bytes;

            // Copy the end of the buffer to the start
            System.arraycopy(search_window, search_window.length - boundary.length, search_window, 0, boundary.length);

            // Refill search_window
            new_bytes = search_window.length - boundary.length;
            new_bytes = (b.remaining() < new_bytes) ? b.remaining() : new_bytes;
            b.get(search_window, boundary.length, new_bytes);
        } while (new_bytes > 0);
        return res;
    }

    @Override
    public CookieHandler getCookies() {
        return this.cookies;
    }

    @Override
    public final Map<String, String> getHeaders() {
        return this.headers;
    }

    @Override
    public final InputStream getInputStream() {
        return this.inputStream;
    }

    @Override
    public final Method getMethod() {
        return this.method;
    }

    /**
     * @deprecated use {@link #getParameters()} instead.
     */
    @Override
    @Deprecated
    public final Map<String, String> getParms() {
        Map<String, String> result = new HashMap<String, String>();
        for (String key : this.parms.keySet()) {
            result.put(key, this.parms.get(key).get(0));
        }

        return result;
    }

    @Override
    public final Map<String, List<String>> getParameters() {
        return this.parms;
    }

    @Override
    public String getQueryParameterString() {
        return this.queryParameterString;
    }

    private RandomAccessFile getTmpBucket() {
        try {
            ITempFile tempFile = this.tempFileManager.createTempFile(null);
            return new RandomAccessFile(tempFile.getName(), "rw");
        } catch (Exception e) {
            throw new Error(e); // we won't recover, so throw an error
        }
    }

    @Override
    public final String getUri() {
        return this.uri;
    }

    /**
     * Deduce body length in bytes. Either from "content-length" header or read
     * bytes.
     */
    public long getBodySize() {
        if (this.headers.containsKey("content-length")) {
            return Long.parseLong(this.headers.get("content-length"));
        } else if (this.splitbyte < this.rlen) {
            return this.rlen - this.splitbyte;
        }
        return 0;
    }

    @Override
    public void parseBody(Map<String, String> files) throws IOException, ResponseException {
        RandomAccessFile randomAccessFile = null;
        try {
            long size = getBodySize();
            ByteArrayOutputStream baos = null;
            DataOutput requestDataOutput = null;

            // Store the request in memory or a file, depending on size
            if (size < MEMORY_STORE_LIMIT) {
                baos = new ByteArrayOutputStream();
                requestDataOutput = new DataOutputStream(baos);
            } else {
                randomAccessFile = getTmpBucket();
                requestDataOutput = randomAccessFile;
            }

            // Read all the body and write it to request_data_output
            byte[] buf = new byte[REQUEST_BUFFER_LEN];
            while (this.rlen >= 0 && size > 0) {
                this.rlen = this.inputStream.read(buf, 0, (int) Math.min(size, REQUEST_BUFFER_LEN));
                size -= this.rlen;
                if (this.rlen > 0) {
                    requestDataOutput.write(buf, 0, this.rlen);
                }
            }

            ByteBuffer fbuf = null;
            if (baos != null) {
                fbuf = ByteBuffer.wrap(baos.toByteArray(), 0, baos.size());
            } else {
                fbuf = randomAccessFile.getChannel().map(FileChannel.MapMode.READ_ONLY, 0, randomAccessFile.length());
                randomAccessFile.seek(0);
            }

            // If the method is POST, there may be parameters
            // in data section, too, read it:
            if (Method.POST.equals(this.method)) {
                ContentType contentType = new ContentType(this.headers.get("content-type"));
                if (contentType.isMultipart()) {
                    String boundary = contentType.getBoundary();
                    if (boundary == null) {
                        throw new ResponseException(Status.BAD_REQUEST, "BAD REQUEST: Content type is multipart/form-data but boundary missing. Usage: GET /example/file.html");
                    }
                    decodeMultipartFormData(contentType, fbuf, this.parms, files);
                } else {
                    byte[] postBytes = new byte[fbuf.remaining()];
                    fbuf.get(postBytes);
                    String postLine = new String(postBytes, contentType.getEncoding()).trim();
                    // Handle application/x-www-form-urlencoded
                    if ("application/x-www-form-urlencoded".equalsIgnoreCase(contentType.getContentType())) {
                        decodeParms(postLine, this.parms);
                    } else if (postLine.length() != 0) {
                        // Special case for raw POST data => create a
                        // special files entry "postData" with raw content
                        // data
                        files.put(POST_DATA, postLine);
                    }
                }
            } else if (Method.PUT.equals(this.method)) {
                files.put("content", saveTmpFile(fbuf, 0, fbuf.limit(), null));
            }
        } finally {
            NanoHTTPD.safeClose(randomAccessFile);
        }
    }

    /**
     * Retrieves the content of a sent file and saves it to a temporary file.
     * The full path to the saved file is returned.
     */
    private String saveTmpFile(ByteBuffer b, int offset, int len, String filename_hint) {
        String path = "";
        if (len > 0) {
            FileOutputStream fileOutputStream = null;
            try {
                ITempFile tempFile = this.tempFileManager.createTempFile(filename_hint);
                ByteBuffer src = b.duplicate();
                fileOutputStream = new FileOutputStream(tempFile.getName());
                FileChannel dest = fileOutputStream.getChannel();
                src.position(offset).limit(offset + len);
                dest.write(src.slice());
                path = tempFile.getName();
            } catch (Exception e) { // Catch exception if any
                throw new Error(e); // we won't recover, so throw an error
            } finally {
                NanoHTTPD.safeClose(fileOutputStream);
            }
        }
        return path;
    }

    @Override
    public String getRemoteIpAddress() {
        return this.remoteIp;
    }
}


================================================
FILE: core/src/main/java/org/nanohttpd/protocols/http/IHTTPSession.java
================================================
package org.nanohttpd.protocols.http;

/*
 * #%L
 * NanoHttpd-Core
 * %%
 * Copyright (C) 2012 - 2016 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.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.Map;

import org.nanohttpd.protocols.http.NanoHTTPD.ResponseException;
import org.nanohttpd.protocols.http.content.CookieHandler;
import org.nanohttpd.protocols.http.request.Method;

/**
 * Handles one session, i.e. parses the HTTP request and returns the response.
 */
public interface IHTTPSession {

    void execute() throws IOException;

    CookieHandler getCookies();

    Map<String, String> getHeaders();

    InputStream getInputStream();

    Method getMethod();

    /**
     * This method will only return the first value for a given parameter. You
     * will want to use getParameters if you expect multiple values for a given
     * key.
     * 
     * @deprecated use {@link #getParameters()} instead.
     */
    @Deprecated
    Map<String, String> getParms();

    Map<String, List<String>> getParameters();

    String getQueryParameterString();

    /**
     * @return the path part of the URL.
     */
    String getUri();

    /**
     * Adds the files in the request body to the files map.
     * 
     * @param files
     *            map to modify
     */
    void parseBody(Map<String, String> files) throws IOException, ResponseException;

    /**
     * Get the remote ip address of the requester.
     * 
     * @return the IP address.
     */
    String getRemoteIpAddress();
}


================================================
FILE: core/src/main/java/org/nanohttpd/protocols/http/NanoHTTPD.java
================================================
package org.nanohttpd.protocols.http;

/*
 * #%L
 * NanoHttpd-Core
 * %%
 * Copyright (C) 2012 - 2016 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.Closeable;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.URL;
import java.net.URLDecoder;
import java.security.KeyStore;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.StringTokenizer;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Pattern;

import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLServerSocketFactory;
import javax.net.ssl.TrustManagerFactory;

import org.nanohttpd.protocols.http.response.Response;
import org.nanohttpd.protocols.http.response.Status;
import org.nanohttpd.protocols.http.sockets.DefaultServerSocketFactory;
import org.nanohttpd.protocols.http.sockets.SecureServerSocketFactory;
import org.nanohttpd.protocols.http.tempfiles.DefaultTempFileManagerFactory;
import org.nanohttpd.protocols.http.tempfiles.ITempFileManager;
import org.nanohttpd.protocols.http.threading.DefaultAsyncRunner;
import org.nanohttpd.protocols.http.threading.IAsyncRunner;
import org.nanohttpd.util.IFactory;
import org.nanohttpd.util.IFactoryThrowing;
import org.nanohttpd.util.IHandler;

/**
 * A simple, tiny, nicely embeddable HTTP server in Java
 * <p/>
 * <p/>
 * NanoHTTPD
 * <p>
 * Copyright (c) 2012-2013 by Paul S. Hawke, 2001,2005-2013 by Jarno Elonen,
 * 2010 by Konstantinos Togias
 * </p>
 * <p/>
 * <p/>
 * <b>Features + limitations: </b>
 * <ul>
 * <p/>
 * <li>Only one Java file</li>
 * <li>Java 5 compatible</li>
 * <li>Released as open source, Modified BSD licence</li>
 * <li>No fixed config files, logging, authorization etc. (Implement yourself if
 * you need them.)</li>
 * <li>Supports parameter parsing of GET and POST methods (+ rudimentary PUT
 * support in 1.25)</li>
 * <li>Supports both dynamic content and file serving</li>
 * <li>Supports file upload (since version 1.2, 2010)</li>
 * <li>Supports partial content (streaming)</li>
 * <li>Supports ETags</li>
 * <li>Never caches anything</li>
 * <li>Doesn't limit bandwidth, request time or simultaneous connections</li>
 * <li>Default code serves files and shows all HTTP parameters and headers</li>
 * <li>File server supports directory listing, index.html and index.htm</li>
 * <li>File server supports partial content (streaming)</li>
 * <li>File server supports ETags</li>
 * <li>File server does the 301 redirection trick for directories without '/'</li>
 * <li>File server supports simple skipping for files (continue download)</li>
 * <li>File server serves also very long files without memory overhead</li>
 * <li>Contains a built-in list of most common MIME types</li>
 * <li>All header names are converted to lower case so they don't vary between
 * browsers/clients</li>
 * <p/>
 * </ul>
 * <p/>
 * <p/>
 * <b>How to use: </b>
 * <ul>
 * <p/>
 * <li>Subclass and implement serve() and embed to your own program</li>
 * <p/>
 * </ul>
 * <p/>
 * See the separate "LICENSE.md" file for the distribution license (Modified BSD
 * licence)
 */
public abstract class NanoHTTPD {

    public static final String CONTENT_DISPOSITION_REGEX = "([ |\t]*Content-Disposition[ |\t]*:)(.*)";

    public static final Pattern CONTENT_DISPOSITION_PATTERN = Pattern.compile(CONTENT_DISPOSITION_REGEX, Pattern.CASE_INSENSITIVE);

    public static final String CONTENT_TYPE_REGEX = "([ |\t]*content-type[ |\t]*:)(.*)";

    public static final Pattern CONTENT_TYPE_PATTERN = Pattern.compile(CONTENT_TYPE_REGEX, Pattern.CASE_INSENSITIVE);

    public static final String CONTENT_DISPOSITION_ATTRIBUTE_REGEX = "[ |\t]*([a-zA-Z]*)[ |\t]*=[ |\t]*['|\"]([^\"^']*)['|\"]";

    public static final Pattern CONTENT_DISPOSITION_ATTRIBUTE_PATTERN = Pattern.compile(CONTENT_DISPOSITION_ATTRIBUTE_REGEX);

    public static final class ResponseException extends Exception {

        private static final long serialVersionUID = 6569838532917408380L;

        private final Status status;

        public ResponseException(Status status, String message) {
            super(message);
            this.status = status;
        }

        public ResponseException(Status status, String message, Exception e) {
            super(message, e);
            this.status = status;
        }

        public Status getStatus() {
            return this.status;
        }
    }

    /**
     * Maximum time to wait on Socket.getInputStream().read() (in milliseconds)
     * This is required as the Keep-Alive HTTP connections would otherwise block
     * the socket reading thread forever (or as long the browser is open).
     */
    public static final int SOCKET_READ_TIMEOUT = 5000;

    /**
     * Common MIME type for dynamic content: plain text
     */
    public static final String MIME_PLAINTEXT = "text/plain";

    /**
     * Common MIME type for dynamic content: html
     */
    public static final String MIME_HTML = "text/html";

    /**
     * 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";

    /**
     * logger to log to.
     */
    public 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;
    }

    @SuppressWarnings({
        "unchecked",
        "rawtypes"
    })
    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(stream);
                } 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.
     */
    public static SSLServerSocketFactory makeSSLSocketFactory(KeyStore loadedKeyStore, KeyManager[] keyManagers) throws IOException {
        SSLServerSocketFactory res = null;
        try {
            TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
            trustManagerFactory.init(loadedKeyStore);
            SSLContext ctx = SSLContext.getInstance("TLS");
            ctx.init(keyManagers, trustManagerFactory.getTrustManagers(), null);
            res = ctx.getServerSocketFactory();
        } catch (Exception e) {
            throw new IOException(e.getMessage());
        }
        return res;
    }

    /**
     * Creates an SSLSocketFactory for HTTPS. Pass a loaded KeyStore and a
     * loaded KeyManagerFactory. These objects must properly loaded/initialized
     * by the caller.
     */
    public static SSLServerSocketFactory makeSSLSocketFactory(KeyStore loadedKeyStore, KeyManagerFactory loadedKeyFactory) throws IOException {
        try {
            return makeSSLSocketFactory(loadedKeyStore, loadedKeyFactory.getKeyManagers());
        } catch (Exception e) {
            throw new IOException(e.getMessage());
        }
    }

    /**
     * Creates an SSLSocketFactory for HTTPS. Pass a KeyStore resource with your
     * certificate and passphrase
     */
    public static SSLServerSocketFactory makeSSLSocketFactory(String keyAndTrustStoreClasspathPath, char[] passphrase) throws IOException {
        try {
            KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());
            InputStream keystoreStream = NanoHTTPD.class.getResourceAsStream(keyAndTrustStoreClasspathPath);

            if (keystoreStream == null) {
                throw new IOException("Unable to load keystore from classpath: " + keyAndTrustStoreClasspathPath);
            }

            keystore.load(keystoreStream, passphrase);
            KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
            keyManagerFactory.init(keystore, passphrase);
            return makeSSLSocketFactory(keystore, keyManagerFactory);
        } catch (Exception e) {
            throw new IOException(e.getMessage());
        }
    }

    /**
     * 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;
    }

    public static final void safeClose(Object closeable) {
        try {
            if (closeable != null) {
                if (closeable instanceof Closeable) {
                    ((Closeable) closeable).close();
                } else if (closeable instanceof Socket) {
                    ((Socket) closeable).close();
                } else if (closeable instanceof ServerSocket) {
                    ((ServerSocket) closeable).close();
                } else {
                    throw new IllegalArgumentException("Unknown object to close");
                }
            }
        } catch (IOException e) {
            NanoHTTPD.LOG.log(Level.SEVERE, "Could not close", e);
        }
    }

    public final String hostname;

    public final int myPort;

    private volatile ServerSocket myServerSocket;

    public ServerSocket getMyServerSocket() {
        return myServerSocket;
    }

    private IFactoryThrowing<ServerSocket, IOException> serverSocketFactory = new DefaultServerSocketFactory();

    private Thread myThread;

    private IHandler<IHTTPSession, Response> httpHandler;

    protected List<IHandler<IHTTPSession, Response>> interceptors = new ArrayList<IHandler<IHTTPSession, Response>>(4);

    /**
     * Pluggable strategy for asynchronously executing requests.
     */
    protected IAsyncRunner asyncRunner;

    /**
     * Pluggable strategy for creating and cleaning up temporary files.
     */
    private IFactory<ITempFileManager> tempFileManagerFactory;

    /**
     * Constructs an HTTP server on given port.
     */
    public NanoHTTPD(int port) {
        this(null, port);
    }

    // -------------------------------------------------------------------------------
    // //
    //
    // Threading Strategy.
    //
    // -------------------------------------------------------------------------------
    // //

    /**
     * Constructs an HTTP server on given hostname and port.
     */
    public NanoHTTPD(String hostname, int port) {
        this.hostname = hostname;
        this.myPort = port;
        setTempFileManagerFactory(new DefaultTempFileManagerFactory());
        setAsyncRunner(new DefaultAsyncRunner());

        // creates a default handler that redirects to deprecated serve();
        this.httpHandler = new IHandler<IHTTPSession, Response>() {

            @Override
            public Response handle(IHTTPSession input) {
                return NanoHTTPD.this.serve(input);
            }
        };
    }

    public void setHTTPHandler(IHandler<IHTTPSession, Response> handler) {
        this.httpHandler = handler;
    }

    public void addHTTPInterceptor(IHandler<IHTTPSession, Response> interceptor) {
        interceptors.add(interceptor);
    }

    /**
     * Forcibly closes all connections that are open.
     */
    public synchronized void closeAllConnections() {
        stop();
    }

    /**
     * create a instance of the client handler, subclasses can return a subclass
     * of the ClientHandler.
     * 
     * @param finalAccept
     *            the socket the cleint is connected to
     * @param inputStream
     *            the input stream
     * @return the client handler
     */
    protected ClientHandler createClientHandler(final Socket finalAccept, final InputStream inputStream) {
        return new ClientHandler(this, inputStream, finalAccept);
    }

    /**
     * Instantiate the server runnable, can be overwritten by subclasses to
     * provide a subclass of the ServerRunnable.
     * 
     * @param timeout
     *            the socet timeout to use.
     * @return the server runnable.
     */
    protected ServerRunnable createServerRunnable(final int timeout) {
        return new ServerRunnable(this, timeout);
    }

    /**
     * Decode parameters from a URL, handing the case where a single parameter
     * name might have been supplied several times, by return lists of values.
     * In general these lists will contain a single element.
     * 
     * @param parms
     *            original <b>NanoHTTPD</b> parameters values, as passed to the
     *            <code>serve()</code> method.
     * @return a map of <code>String</code> (parameter name) to
     *         <code>List&lt;String&gt;</code> (a list of the values supplied).
     */
    protected static Map<String, List<String>> decodeParameters(Map<String, String> parms) {
        return decodeParameters(parms.get(NanoHTTPD.QUERY_STRING_PARAMETER));
    }

    // -------------------------------------------------------------------------------
    // //

    /**
     * Decode parameters from a URL, handing the case where a single parameter
     * name might have been supplied several times, by return lists of values.
     * In general these lists will contain a single element.
     * 
     * @param queryString
     *            a query string pulled from the URL.
     * @return a map of <code>String</code> (parameter name) to
     *         <code>List&lt;String&gt;</code> (a list of the values supplied).
     */
    protected static Map<String, List<String>> decodeParameters(String queryString) {
        Map<String, List<String>> parms = new HashMap<String, List<String>>();
        if (queryString != null) {
            StringTokenizer st = new StringTokenizer(queryString, "&");
            while (st.hasMoreTokens()) {
                String e = st.nextToken();
                int sep = e.indexOf('=');
                String propertyName = sep >= 0 ? decodePercent(e.substring(0, sep)).trim() : decodePercent(e).trim();
                if (!parms.containsKey(propertyName)) {
                    parms.put(propertyName, new ArrayList<String>());
                }
                String propertyValue = sep >= 0 ? decodePercent(e.substring(sep + 1)) : null;
                if (propertyValue != null) {
                    parms.get(propertyName).add(propertyValue);
                }
            }
        }
        return parms;
    }

    /**
     * Decode percent encoded <code>String</code> values.
     * 
     * @param str
     *            the percent encoded <code>String</code>
     * @return expanded form of the input, for example "foo%20bar" becomes
     *         "foo bar"
     */
    public static String decodePercent(String str) {
        String decoded = null;
        try {
            decoded = URLDecoder.decode(str, "UTF8");
        } catch (UnsupportedEncodingException ignored) {
            NanoHTTPD.LOG.log(Level.WARNING, "Encoding not supported, ignored", ignored);
        }
        return decoded;
    }

    public final int getListeningPort() {
        return this.myServerSocket == null ? -1 : this.myServerSocket.getLocalPort();
    }

    public final boolean isAlive() {
        return wasStarted() && !this.myServerSocket.isClosed() && this.myThread.isAlive();
    }

    public IFactoryThrowing<ServerSocket, IOException> getServerSocketFactory() {
        return serverSocketFactory;
    }

    public void setServerSocketFactory(IFactoryThrowing<ServerSocket, IOException> serverSocketFactory) {
        this.serverSocketFactory = serverSocketFactory;
    }

    public String getHostname() {
        return hostname;
    }

    public IFactory<ITempFileManager> getTempFileManagerFactory() {
        return tempFileManagerFactory;
    }

    /**
     * Call before start() to serve over HTTPS instead of HTTP
     */
    public void makeSecure(SSLServerSocketFactory sslServerSocketFactory, String[] sslProtocols) {
        this.serverSocketFactory = new SecureServerSocketFactory(sslServerSocketFactory, sslProtocols);
    }

    /**
     * This is the "master" method that delegates requests to handlers and makes
     * sure there is a response to every request. You are not supposed to call
     * or override this method in any circumstances. But no one will stop you if
     * you do. I'm a Javadoc, not Code Police.
     * 
     * @param session
     *            the incoming session
     * @return a response to the incoming session
     */
    public Response handle(IHTTPSession session) {
        for (IHandler<IHTTPSession, Response> interceptor : interceptors) {
            Response response = interceptor.handle(session);
            if (response != null)
                return response;
        }
        return httpHandler.handle(session);
    }

    /**
     * Override this to customize the server.
     * <p/>
     * <p/>
     * (By default, this returns a 404 "Not Found" plain text error response.)
     * 
     * @param session
     *            The HTTP session
     * @return HTTP response, see class Response for details
     */
    @Deprecated
    protected Response serve(IHTTPSession session) {
        return Response.newFixedLengthResponse(Status.NOT_FOUND, NanoHTTPD.MIME_PLAINTEXT, "Not Found");
    }

    /**
     * Pluggable strategy for asynchronously executing requests.
     * 
     * @param asyncRunner
     *            new strategy for handling threads.
     */
    public void setAsyncRunner(IAsyncRunner asyncRunner) {
        this.asyncRunner = asyncRunner;
    }

    /**
     * Pluggable strategy for creating and cleaning up temporary files.
     * 
     * @param tempFileManagerFactory
     *            new strategy for handling temp files.
     */
    public void setTempFileManagerFactory(IFactory<ITempFileManager> tempFileManagerFactory) {
        this.tempFileManagerFactory = tempFileManagerFactory;
    }

    /**
     * Start the server.
     * 
     * @throws IOException
     *             if the socket is in use.
     */
    public void start() throws IOException {
        start(NanoHTTPD.SOCKET_READ_TIMEOUT);
    }

    /**
     * Starts the server (in setDaemon(true) mode).
     */
    public void start(final int timeout) throws IOException {
        start(timeout, true);
    }

    /**
     * Start the server.
     * 
     * @param timeout
     *            timeout to use for socket connections.
     * @param daemon
     *            start the thread daemon or not.
     * @throws IOException
     *             if the socket is in use.
     */
    public void start(final int timeout, boolean daemon) throws IOException {
        this.myServerSocket = this.getServerSocketFactory().create();
        this.myServerSocket.setReuseAddress(true);

        ServerRunnable serverRunnable = createServerRunnable(timeout);
        this.myThread = new Thread(serverRunnable);
        this.myThread.setDaemon(daemon);
        this.myThread.setName("NanoHttpd Main Listener");
        this.myThread.start();
        while (!serverRunnable.hasBinded() && serverRunnable.getBindException() == null) {
            try {
                Thread.sleep(10L);
            } catch (Throwable e) {
                // on android this may not be allowed, that's why we
                // catch throwable the wait should be very short because we are
                // just waiting for the bind of the socket
            }
        }
        if (serverRunnable.getBindException() != null) {
            throw serverRunnable.getBindException();
        }
    }

    /**
     * Stop the server.
     */
    public void stop() {
        try {
            safeClose(this.myServerSocket);
            this.asyncRunner.closeAll();
            if (this.myThread != null) {
                this.myThread.join();
            }
        } catch (Exception e) {
            NanoHTTPD.LOG.log(Level.SEVERE, "Could not stop all connections", e);
        }
    }

    public final boolean wasStarted() {
        return this.myServerSocket != null && this.myThread != null;
    }
}


================================================
FILE: core/src/main/java/org/nanohttpd/protocols/http/ServerRunnable.java
================================================
package org.nanohttpd.protocols.http;

/*
 * #%L
 * NanoHttpd-Core
 * %%
 * Copyright (C) 2012 - 2016 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.IOException;
import java.io.InputStream;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.util.logging.Level;

/**
 * The runnable that will be used for the main listening thread.
 */
public class ServerRunnable implements Runnable {

    private NanoHTTPD httpd;

    private final int timeout;

    private IOException bindException;

    private boolean hasBinded = false;

    public ServerRunnable(NanoHTTPD httpd, int timeout) {
        this.httpd = httpd;
        this.timeout = timeout;
    }

    @Override
    public void run() {
        try {
            httpd.getMyServerSocket().bind(httpd.hostname != null ? new InetSocketAddress(httpd.hostname, httpd.myPort) : new InetSocketAddress(httpd.myPort));
            hasBinded = true;
        } catch (IOException e) {
            this.bindException = e;
            return;
        }
        do {
            try {
                final Socket finalAccept = httpd.getMyServerSocket().accept();
                if (this.timeout > 0) {
                    finalAccept.setSoTimeout(this.timeout);
                }
                final InputStream inputStream = finalAccept.getInputStream();
                httpd.asyncRunner.exec(httpd.createClientHandler(finalAccept, inputStream));
            } catch (IOException e) {
                NanoHTTPD.LOG.log(Level.FINE, "Communication with the client broken", e);
            }
        } while (!httpd.getMyServerSocket().isClosed());
    }

    public IOException getBindException() {
        return bindException;
    }

    public boolean hasBinded() {
        return hasBinded;
    }
}


================================================
FILE: core/src/main/java/org/nanohttpd/protocols/http/content/ContentType.java
================================================
package org.nanohttpd.protocols.http.content;

/*
 * #%L
 * NanoHttpd-Core
 * %%
 * Copyright (C) 2012 - 2016 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.util.regex.Matcher;
import java.util.regex.Pattern;

public class ContentType {

    private static final String ASCII_ENCODING = "US-ASCII";

    private static final String MULTIPART_FORM_DATA_HEADER = "multipart/form-data";

    private static final String CONTENT_REGEX = "[ |\t]*([^/^ ^;^,]+/[^ ^;^,]+)";

    private static final Pattern MIME_PATTERN = Pattern.compile(CONTENT_REGEX, Pattern.CASE_INSENSITIVE);

    private static final String CHARSET_REGEX = "[ |\t]*(charset)[ |\t]*=[ |\t]*['|\"]?([^\"^'^;^,]*)['|\"]?";

    private static final Pattern CHARSET_PATTERN = Pattern.compile(CHARSET_REGEX, Pattern.CASE_INSENSITIVE);

    private static final String BOUNDARY_REGEX = "[ |\t]*(boundary)[ |\t]*=[ |\t]*['|\"]?([^\"^'^;^,]*)['|\"]?";

    private static final Pattern BOUNDARY_PATTERN = Pattern.compile(BOUNDARY_REGEX, Pattern.CASE_INSENSITIVE);

    private final String contentTypeHeader;

    private final String contentType;

    private final String encoding;

    private final String boundary;

    public ContentType(String contentTypeHeader) {
        this.contentTypeHeader = contentTypeHeader;
        if (contentTypeHeader != null) {
            contentType = getDetailFromContentHeader(contentTypeHeader, MIME_PATTERN, "", 1);
            encoding = getDetailFromContentHeader(contentTypeHeader, CHARSET_PATTERN, null, 2);
        } else {
            contentType = "";
            encoding = "UTF-8";
        }
        if (MULTIPART_FORM_DATA_HEADER.equalsIgnoreCase(contentType)) {
            boundary = getDetailFromContentHeader(contentTypeHeader, BOUNDARY_PATTERN, null, 2);
        } else {
            boundary = null;
        }
    }

    private String getDetailFromContentHeader(String contentTypeHeader, Pattern pattern, String defaultValue, int group) {
        Matcher matcher = pattern.matcher(contentTypeHeader);
        return matcher.find() ? matcher.group(group) : defaultValue;
    }

    public String getContentTypeHeader() {
        return contentTypeHeader;
    }

    public String getContentType() {
        return contentType;
    }

    public String getEncoding() {
        return encoding == null ? ASCII_ENCODING : encoding;
    }

    public String getBoundary() {
        return boundary;
    }

    public boolean isMultipart() {
        return MULTIPART_FORM_DATA_HEADER.equalsIgnoreCase(contentType);
    }

    public ContentType tryUTF8() {
        if (encoding == null) {
            return new ContentType(this.contentTypeHeader + "; charset=UTF-8");
        }
        return this;
    }
}


================================================
FILE: core/src/main/java/org/nanohttpd/protocols/http/content/Cookie.java
================================================
package org.nanohttpd.protocols.http.content;

/*
 * #%L
 * NanoHttpd-Core
 * %%
 * Copyright (C) 2012 - 2016 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.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Locale;
import java.util.TimeZone;

/**
 * A simple cookie representation. This is old code and is flawed in many ways.
 * 
 * @author LordFokas
 */
public class Cookie {

    public static String getHTTPTime(int days) {
        Calendar calendar = Calendar.getInstance();
        SimpleDateFormat dateFormat = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z", Locale.US);
        dateFormat.setTimeZone(TimeZone.getTimeZone("GMT"));
        calendar.add(Calendar.DAY_OF_MONTH, days);
        return dateFormat.format(calendar.getTime());
    }

    private final String n, v, e;

    public Cookie(String name, String value) {
        this(name, value, 30);
    }

    public Cookie(String name, String value, int numDays) {
        this.n = name;
        this.v = value;
        this.e = getHTTPTime(numDays);
    }

    public Cookie(String name, String value, String expires) {
        this.n = name;
        this.v = value;
        this.e = expires;
    }

    public String getHTTPHeader() {
        String fmt = "%s=%s; expires=%s";
        return String.format(fmt, this.n, this.v, this.e);
    }
}


================================================
FILE: core/src/main/java/org/nanohttpd/protocols/http/content/CookieHandler.java
================================================
package org.nanohttpd.protocols.http.content;

/*
 * #%L
 * NanoHttpd-Core
 * %%
 * Copyright (C) 2012 - 2016 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.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import org.nanohttpd.protocols.http.response.Response;

/**
 * Provides rudimentary support for cookies. Doesn't support 'path', 'secure'
 * nor 'httpOnly'. Feel free to improve it and/or add unsupported features. This
 * is old code and it's flawed in many ways.
 * 
 * @author LordFokas
 */
public class CookieHandler implements Iterable<String> {

    private final HashMap<String, String> cookies = new HashMap<String, String>();

    private final ArrayList<Cookie> queue = new ArrayList<Cookie>();

    public CookieHandler(Map<String, String> httpHeaders) {
        String raw = httpHeaders.get("cookie");
        if (raw != null) {
            String[] tokens = raw.split(";");
            for (String token : tokens) {
                String[] data = token.trim().split("=");
                if (data.length == 2) {
                    this.cookies.put(data[0], data[1]);
                }
            }
        }
    }

    /**
     * Set a cookie with an expiration date from a month ago, effectively
     * deleting it on the client side.
     * 
     * @param name
     *            The cookie name.
     */
    public void delete(String name) {
        set(name, "-delete-", -30);
    }

    @Override
    public Iterator<String> iterator() {
        return this.cookies.keySet().iterator();
    }

    /**
     * Read a cookie from the HTTP Headers.
     * 
     * @param name
     *            The cookie's name.
     * @return The cookie's value if it exists, null otherwise.
     */
    public String read(String name) {
        return this.cookies.get(name);
    }

    public void set(Cookie cookie) {
        this.queue.add(cookie);
    }

    /**
     * Sets a cookie.
     * 
     * @param name
     *            The cookie's name.
     * @param value
     *            The cookie's value.
     * @param expires
     *            How many days until the cookie expires.
     */
    public void set(String name, String value, int expires) {
        this.queue.add(new Cookie(name, value, Cookie.getHTTPTime(expires)));
    }

    /**
     * Internally used by the webserver to add all queued cookies into the
     * Response's HTTP Headers.
     * 
     * @param response
     *            The Response object to which headers the queued cookies will
     *            be added.
     */
    public void unloadQueue(Response response) {
        for (Cookie cookie : this.queue) {
            response.addCookieHeader(cookie.getHTTPHeader());
        }
    }
}


================================================
FILE: core/src/main/java/org/nanohttpd/protocols/http/request/Method.java
================================================
package org.nanohttpd.protocols.http.request;

/*
 * #%L
 * NanoHttpd-Core
 * %%
 * Copyright (C) 2012 - 2016 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%
 */

/**
 * HTTP Request methods, with the ability to decode a <code>String</code> back
 * to its enum value.
 */
public enum Method {
    GET,
    PUT,
    POST,
    DELETE,
    HEAD,
    OPTIONS,
    TRACE,
    CONNECT,
    PATCH,
    PROPFIND,
    PROPPATCH,
    MKCOL,
    MOVE,
    COPY,
    LOCK,
    UNLOCK,
    NOTIFY,
    SUBSCRIBE;

    public static Method lookup(String method) {
        if (method == null)
            return null;

        try {
            return valueOf(method);
        } catch (IllegalArgumentException e) {
            // TODO: Log it?
            return null;
        }
    }
}


================================================
FILE: core/src/main/java/org/nanohttpd/protocols/http/response/ChunkedOutputStream.java
================================================
package org.nanohttpd.protocols.http.response;

/*
 * #%L
 * NanoHttpd-Core
 * %%
 * Copyright (C) 2012 - 2016 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.FilterOutputStream;
import java.io.IOException;
import java.io.OutputStream;

/**
 * Output stream that will automatically send every write to the wrapped
 * OutputStream according to chunked transfer:
 * http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.6.1
 */
public class ChunkedOutputStream extends FilterOutputStream {

    public ChunkedOutputStream(OutputStream out) {
        super(out);
    }

    @Override
    public void write(int b) throws IOException {
        byte[] data = {
            (byte) b
        };
        write(data, 0, 1);
    }

    @Override
    public void write(byte[] b) throws IOException {
        write(b, 0, b.length);
    }

    @Override
    public void write(byte[] b, int off, int len) throws IOException {
        if (len == 0)
            return;
        out.write(String.format("%x\r\n", len).getBytes());
        out.write(b, off, len);
        out.write("\r\n".getBytes());
    }

    public void finish() throws IOException {
        out.write("0\r\n\r\n".getBytes());
    }
}


================================================
FILE: core/src/main/java/org/nanohttpd/protocols/http/response/IStatus.java
================================================
package org.nanohttpd.protocols.http.response;

/*
 * #%L
 * NanoHttpd-Core
 * %%
 * Copyright (C) 2012 - 2016 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%
 */

public interface IStatus {

    String getDescription();

    int getRequestStatus();
}


================================================
FILE: core/src/main/java/org/nanohttpd/protocols/http/response/Response.java
================================================
package org.nanohttpd.protocols.http.response;

/*
 * #%L
 * NanoHttpd-Core
 * %%
 * Copyright (C) 2012 - 2016 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.BufferedWriter;
import java.io.ByteArrayInputStream;
import java.io.Closeable;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import java.nio.charset.CharsetEncoder;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import java.util.TimeZone;
import java.util.logging.Level;
import java.util.zip.GZIPOutputStream;

import org.nanohttpd.protocols.http.NanoHTTPD;
import org.nanohttpd.protocols.http.content.ContentType;
import org.nanohttpd.protocols.http.request.Method;

/**
 * HTTP response. Return one of these from serve().
 */
public class Response implements Closeable {

    /**
     * HTTP status code after processing, e.g. "200 OK", Status.OK
     */
    private IStatus status;

    /**
     * MIME type of content, e.g. "text/html"
     */
    private String mimeType;

    /**
     * Data of the response, may be null.
     */
    private InputStream data;

    private long contentLength;

    /**
     * Headers for the HTTP response. Use addHeader() to add lines. the
     * lowercase map is automatically kept up to date.
     */
    @SuppressWarnings("serial")
    private final Map<String, String> header = new HashMap<String, String>() {

        public String put(String key, String value) {
            lowerCaseHeader.put(key == null ? key : key.toLowerCase(), value);
            return super.put(key, value);
        };
    };

    /**
     * copy of the header map with all the keys lowercase for faster searching.
     */
    private final Map<String, String> lowerCaseHeader = new HashMap<String, String>();

    /**
     * The request method that spawned this response.
     */
    private Method requestMethod;

    /**
     * Use chunkedTransfer
     */
    private boolean chunkedTransfer;

    private boolean keepAlive;

    private List<String> cookieHeaders;

    private GzipUsage gzipUsage = GzipUsage.DEFAULT;

    private static enum GzipUsage {
        DEFAULT,
        ALWAYS,
        NEVER;
    }

    /**
     * Creates a fixed length response if totalBytes>=0, otherwise chunked.
     */
    @SuppressWarnings({
        "rawtypes",
        "unchecked"
    })
    protected Response(IStatus status, String mimeType, InputStream data, long totalBytes) {
        this.status = status;
        this.mimeType = mimeType;
        if (data == null) {
            this.data = new ByteArrayInputStream(new byte[0]);
            this.contentLength = 0L;
        } else {
            this.data = data;
            this.contentLength = totalBytes;
        }
        this.chunkedTransfer = this.contentLength < 0;
        this.keepAlive = true;
        this.cookieHeaders = new ArrayList(10);
    }

    @Override
    public void close() throws IOException {
        if (this.data != null) {
            this.data.close();
        }
    }

    /**
     * Adds a cookie header to the list. Should not be called manually, this is
     * an internal utility.
     */
    public void addCookieHeader(String cookie) {
        cookieHeaders.add(cookie);
    }

    /**
     * Should not be called manually. This is an internally utility for JUnit
     * test purposes.
     * 
     * @return All unloaded cookie headers.
     */
    public List<String> getCookieHeaders() {
        return cookieHeaders;
    }

    /**
     * Adds given line to the header.
     */
    public void addHeader(String name, String value) {
        this.header.put(name, value);
    }

    /**
     * Indicate to close the connection after the Response has been sent.
     * 
     * @param close
     *            {@code true} to hint connection closing, {@code false} to let
     *            connection be closed by client.
     */
    public void closeConnection(boolean close) {
        if (close)
            this.header.put("connection", "close");
        else
            this.header.remove("connection");
    }

    /**
     * @return {@code true} if connection is to be closed after this Response
     *         has been sent.
     */
    public boolean isCloseConnection() {
        return "close".equals(getHeader("connection"));
    }

    public InputStream getData() {
        return this.data;
    }

    public String getHeader(String name) {
        return this.lowerCaseHeader.get(name.toLowerCase());
    }

    public String getMimeType() {
        return this.mimeType;
    }

    public Method getRequestMethod() {
        return this.requestMethod;
    }

    public IStatus getStatus() {
        return this.status;
    }

    public void setKeepAlive(boolean useKeepAlive) {
        this.keepAlive = useKeepAlive;
    }

    /**
     * Sends given response to the socket.
     */
    public void send(OutputStream outputStream) {
        SimpleDateFormat gmtFrmt = new SimpleDateFormat("E, d MMM yyyy HH:mm:ss 'GMT'", Locale.US);
        gmtFrmt.setTimeZone(TimeZone.getTimeZone("GMT"));

        try {
            if (this.status == null) {
                throw new Error("sendResponse(): Status can't be null.");
            }
            PrintWriter pw = new PrintWriter(new BufferedWriter(new OutputStreamWriter(outputStream, new ContentType(this.mimeType).getEncoding())), false);
            pw.append("HTTP/1.1 ").append(this.status.getDescription()).append(" \r\n");
            if (this.mimeType != null) {
                printHeader(pw, "Content-Type", this.mimeType);
            }
            if (getHeader("date") == null) {
                printHeader(pw, "Date", gmtFrmt.format(new Date()));
            }
            for (Entry<String, String> entry : this.header.entrySet()) {
                printHeader(pw, entry.getKey(), entry.getValue());
            }
            for (String cookieHeader : this.cookieHeaders) {
                printHeader(pw, "Set-Cookie", cookieHeader);
            }
            if (getHeader("connection") == null) {
                printHeader(pw, "Connection", (this.keepAlive ? "keep-alive" : "close"));
            }
            if (getHeader("content-length") != null) {
                setUseGzip(false);
            }
            if (useGzipWhenAccepted()) {
                printHeader(pw, "Content-Encoding", "gzip");
                setChunkedTransfer(true);
            }
            long pending = this.data != null ? this.contentLength : 0;
            if (this.requestMethod != Method.HEAD && this.chunkedTransfer) {
                printHeader(pw, "Transfer-Encoding", "chunked");
            } else if (!useGzipWhenAccepted()) {
                pending = sendContentLengthHeaderIfNotAlreadyPresent(pw, pending);
            }
            pw.append("\r\n");
            pw.flush();
            sendBodyWithCorrectTransferAndEncoding(outputStream, pending);
            outputStream.flush();
            NanoHTTPD.safeClose(this.data);
        } catch (IOException ioe) {
            NanoHTTPD.LOG.log(Level.SEVERE, "Could not send response to the client", ioe);
        }
    }

    @SuppressWarnings("static-method")
    protected void printHeader(PrintWriter pw, String key, String value) {
        pw.append(key).append(": ").append(value).append("\r\n");
    }

    protected long sendContentLengthHeaderIfNotAlreadyPresent(PrintWriter pw, long defaultSize) {
        String contentLengthString = getHeader("content-length");
        long size = defaultSize;
        if (contentLengthString != null) {
            try {
                size = Long.parseLong(contentLengthString);
            } catch (NumberFormatException ex) {
                NanoHTTPD.LOG.severe("content-length was no number " + contentLengthString);
            }
        }else{
        	pw.print("Content-Length: " + size + "\r\n");
        }
        return size;
    }

    private void sendBodyWithCorrectTransferAndEncoding(OutputStream outputStream, long pending) throws IOException {
        if (this.requestMethod != Method.HEAD && this.chunkedTransfer) {
            ChunkedOutputStream chunkedOutputStream = new ChunkedOutputStream(outputStream);
            sendBodyWithCorrectEncoding(chunkedOutputStream, -1);
            try {
                chunkedOutputStream.finish();
            } catch (Exception e) {
                if(this.data != null) {
                    this.data.close();
                }
            }
        } else {
            sendBodyWithCorrectEncoding(outputStream, pending);
        }
    }

    private void sendBodyWithCorrectEncoding(OutputStream outputStream, long pending) throws IOException {
        if (useGzipWhenAccepted()) {
            GZIPOutputStream gzipOutputStream = null;
            try {
                gzipOutputStream = new GZIPOutputStream(outputStream);
            } catch (Exception e) {
                if(this.data != null) {
                    this.data.close();
                }
            }
            if (gzipOutputStream != null) {
                sendBody(gzipOutputStream, -1);
                gzipOutputStream.finish();
            }
        } else {
            sendBody(outputStream, pending);
        }
    }

    /**
     * Sends the body to the specified OutputStream. The pending parameter
     * limits the maximum amounts of bytes sent unless it is -1, in which case
     * everything is sent.
     * 
     * @param outputStream
     *            the OutputStream to send data to
     * @param pending
     *            -1 to send everything, otherwise sets a max limit to the
     *            number of bytes sent
     * @throws IOException
     *             if something goes wrong while sending the data.
     */
    private void sendBody(OutputStream outputStream, long pending) throws IOException {
        long BUFFER_SIZE = 16 * 1024;
        byte[] buff = new byte[(int) BUFFER_SIZE];
        boolean sendEverything = pending == -1;
        while (pending > 0 || sendEverything) {
            long bytesToRead = sendEverything ? BUFFER_SIZE : Math.min(pending, BUFFER_SIZE);
            int read = this.data.read(buff, 0, (int) bytesToRead);
            if (read <= 0) {
                break;
            }
            try {
                outputStream.write(buff, 0, read);
            } catch (Exception e) {
                if(this.data != null) {
                    this.data.close();
                }
            }
            if (!sendEverything) {
                pending -= read;
            }
        }
    }

    public void setChunkedTransfer(boolean chunkedTransfer) {
        this.chunkedTransfer = chunkedTransfer;
    }

    public void setData(InputStream data) {
        this.data = data;
    }

    public void setMimeType(String mimeType) {
        this.mimeType = mimeType;
    }

    public void setRequestMethod(Method requestMethod) {
        this.requestMethod = requestMethod;
    }

    public void setStatus(IStatus status) {
        this.status = status;
    }

    /**
     * Create a response with unknown length (using HTTP 1.1 chunking).
     */
    public static Response newChunkedResponse(IStatus status, String mimeType, InputStream data) {
        return new Response(status, mimeType, data, -1);
    }

    public static Response newFixedLengthResponse(IStatus status, String mimeType, byte[] data) {
        return newFixedLengthResponse(status, mimeType, new ByteArrayInputStream(data), data.length);
    }

    /**
     * Create a response with known length.
     */
    public static Response newFixedLengthResponse(IStatus status, String mimeType, InputStream data, long totalBytes) {
        return new Response(status, mimeType, data, totalBytes);
    }

    /**
     * Create a text response with known length.
     */
    public static Response newFixedLengthResponse(IStatus status, String mimeType, String txt) {
        ContentType contentType = new ContentType(mimeType);
        if (txt == null) {
            return newFixedLengthResponse(status, mimeType, new ByteArrayInputStream(new byte[0]), 0);
        } else {
            byte[] bytes;
            try {
                CharsetEncoder newEncoder = Charset.forName(contentType.getEncoding()).newEncoder();
                if (!newEncoder.canEncode(txt)) {
                    contentType = contentType.tryUTF8();
                }
                bytes = txt.getBytes(contentType.getEncoding());
            } catch (UnsupportedEncodingException e) {
                NanoHTTPD.LOG.log(Level.SEVERE, "encoding problem, responding nothing", e);
                bytes = new byte[0];
            }
            return newFixedLengthResponse(status, contentType.getContentTypeHeader(), new ByteArrayInputStream(bytes), bytes.length);
        }
    }

    /**
     * Create a text response with known length.
     */
    public static Response newFixedLengthResponse(String msg) {
        return newFixedLengthResponse(Status.OK, NanoHTTPD.MIME_HTML, msg);
    }

    public Response setUseGzip(boolean useGzip) {
        gzipUsage = useGzip ? GzipUsage.ALWAYS : GzipUsage.NEVER;
        return this;
    }

    // If a Gzip usage has been enforced, use it.
    // Else decide whether or not to use Gzip.
    public boolean useGzipWhenAccepted() {
        if (gzipUsage == GzipUsage.DEFAULT)
            return getMimeType() != null && (getMimeType().toLowerCase().contains("text/") || getMimeType().toLowerCase().contains("/json"));
        else
            return gzipUsage == GzipUsage.ALWAYS;
    }
}


================================================
FILE: core/src/main/java/org/nanohttpd/protocols/http/response/Status.java
================================================
package org.nanohttpd.protocols.http.response;

/*
 * #%L
 * NanoHttpd-Core
 * %%
 * Copyright (C) 2012 - 2016 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%
 */

/**
 * Some HTTP response status codes
 */
public enum Status implements IStatus {
    SWITCH_PROTOCOL(101, "Switching Protocols"),

    OK(200, "OK"),
    CREATED(201, "Created"),
    ACCEPTED(202, "Accepted"),
    NO_CONTENT(204, "No Content"),
    PARTIAL_CONTENT(206, "Partial Content"),
    MULTI_STATUS(207, "Multi-Status"),

    REDIRECT(301, "Moved Permanently"),
    /**
     * Many user agents mishandle 302 in ways that violate the RFC1945 spec
     * (i.e., redirect a POST to a GET). 303 and 307 were added in RFC2616 to
     * address this. You should prefer 303 and 307 unless the calling user agent
     * does not support 303 and 307 functionality
     */
    @Deprecated
    FOUND(302, "Found"),
    REDIRECT_SEE_OTHER(303, "See Other"),
    NOT_MODIFIED(304, "Not Modified"),
    TEMPORARY_REDIRECT(307, "Temporary Redirect"),

    BAD_REQUEST(400, "Bad Request"),
    UNAUTHORIZED(401, "Unauthorized"),
    FORBIDDEN(403, "Forbidden"),
    NOT_FOUND(404, "Not Found"),
    METHOD_NOT_ALLOWED(405, "Method Not Allowed"),
    NOT_ACCEPTABLE(406, "Not Acceptable"),
    REQUEST_TIMEOUT(408, "Request Timeout"),
    CONFLICT(409, "Conflict"),
    GONE(410, "Gone"),
    LENGTH_REQUIRED(411, "Length Required"),
    PRECONDITION_FAILED(412, "Precondition Failed"),
    PAYLOAD_TOO_LARGE(413, "Payload Too Large"),
    UNSUPPORTED_MEDIA_TYPE(415, "Unsupported Media Type"),
    RANGE_NOT_SATISFIABLE(416, "Requested Range Not Satisfiable"),
    EXPECTATION_FAILED(417, "Expectation Failed"),
    TOO_MANY_REQUESTS(429, "Too Many Requests"),

    INTERNAL_ERROR(500, "Internal Server Error"),
    NOT_IMPLEMENTED(501, "Not Implemented"),
    SERVICE_UNAVAILABLE(503, "Service Unavailable"),
    UNSUPPORTED_HTTP_VERSION(505, "HTTP Version Not Supported");

    private final int requestStatus;

    private final String description;

    Status(int requestStatus, String description) {
        this.requestStatus = requestStatus;
        this.description = description;
    }

    public static Status lookup(int requestStatus) {
        for (Status status : Status.values()) {
            if (status.getRequestStatus() == requestStatus) {
                return status;
            }
        }
        return null;
    }

    @Override
    public String getDescription() {
        return "" + this.requestStatus + " " + this.description;
    }

    @Override
    public int getRequestStatus() {
        return this.requestStatus;
    }
}


================================================
FILE: core/src/main/java/org/nanohttpd/protocols/http/sockets/DefaultServerSocketFactory.java
================================================
package org.nanohttpd.protocols.http.sockets;

/*
 * #%L
 * NanoHttpd-Core
 * %%
 * Copyright (C) 2012 - 2016 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.IOException;
import java.net.ServerSocket;

import org.nanohttpd.util.IFactoryThrowing;

/**
 * Creates a normal ServerSocket for TCP connections
 */
public class DefaultServerSocketFactory implements IFactoryThrowing<ServerSocket, IOException> {

    @Override
    public ServerSocket create() throws IOException {
        return new ServerSocket();
    }

}


================================================
FILE: core/src/main/java/org/nanohttpd/protocols/http/sockets/SecureServerSocketFactory.java
================================================
package org.nanohttpd.protocols.http.sockets;

/*
 * #%L
 * NanoHttpd-Core
 * %%
 * Copyright (C) 2012 - 2016 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.IOException;
import java.net.ServerSocket;

import javax.net.ssl.SSLServerSocket;
import javax.net.ssl.SSLServerSocketFactory;

import org.nanohttpd.util.IFactoryThrowing;

/**
 * Creates a new SSLServerSocket
 */
public class SecureServerSocketFactory implements IFactoryThrowing<ServerSocket, IOException> {

    private SSLServerSocketFactory sslServerSocketFactory;

    private String[] sslProtocols;

    public SecureServerSocketFactory(SSLServerSocketFactory sslServerSocketFactory, String[] sslProtocols) {
        this.sslServerSocketFactory = sslServerSocketFactory;
        this.sslProtocols = sslProtocols;
    }

    @Override
    public ServerSocket create() throws IOException {
        SSLServerSocket ss = null;
        ss = (SSLServerSocket) this.sslServerSocketFactory.createServerSocket();
        if (this.sslProtocols != null) {
            ss.setEnabledProtocols(this.sslProtocols);
        } else {
            ss.setEnabledProtocols(ss.getSupportedProtocols());
        }
        ss.setUseClientMode(false);
        ss.setWantClientAuth(false);
        ss.setNeedClientAuth(false);
        return ss;
    }

}


================================================
FILE: core/src/main/java/org/nanohttpd/protocols/http/tempfiles/DefaultTempFile.java
================================================
package org.nanohttpd.protocols.http.tempfiles;

/*
 * #%L
 * NanoHttpd-Core
 * %%
 * Copyright (C) 2012 - 2016 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.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;

import org.nanohttpd.protocols.http.NanoHTTPD;

/**
 * Default strategy for creating and cleaning up temporary files.
 * <p/>
 * <p>
 * By default, files are created by <code>File.createTempFile()</code> in the
 * directory specified.
 * </p>
 */
public class DefaultTempFile implements ITempFile {

    private final File file;

    private final OutputStream fstream;

    public DefaultTempFile(File tempdir) throws IOException {
        this.file = File.createTempFile("NanoHTTPD-", "", tempdir);
        this.fstream = new FileOutputStream(this.file);
    }

    @Override
    public void delete() throws Exception {
        NanoHTTPD.safeClose(this.fstream);
        if (!this.file.delete()) {
            throw new Exception("could not delete temporary file: " + this.file.getAbsolutePath());
        }
    }

    @Override
    public String getName() {
        return this.file.getAbsolutePath();
    }

    @Override
    public OutputStream open() throws Exception {
        return this.fstream;
    }
}


================================================
FILE: core/src/main/java/org/nanohttpd/protocols/http/tempfiles/DefaultTempFileManager.java
================================================
package org.nanohttpd.protocols.http.tempfiles;

/*
 * #%L
 * NanoHttpd-Core
 * %%
 * Copyright (C) 2012 - 2016 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.util.ArrayList;
import java.util.List;
import java.util.logging.Level;

import org.nanohttpd.protocols.http.NanoHTTPD;

/**
 * Default strategy for creating and cleaning up temporary files.
 * <p/>
 * <p>
 * This class stores its files in the standard location (that is, wherever
 * <code>java.io.tmpdir</code> points to). Files are added to an internal list,
 * and deleted when no longer needed (that is, when <code>clear()</code> is
 * invoked at the end of processing a request).
 * </p>
 */
public class DefaultTempFileManager implements ITempFileManager {

    private final File tmpdir;

    private final List<ITempFile> tempFiles;

    public DefaultTempFileManager() {
        this.tmpdir = new File(System.getProperty("java.io.tmpdir"));
        if (!tmpdir.exists()) {
            tmpdir.mkdirs();
        }
        this.tempFiles = new ArrayList<ITempFile>();
    }

    @Override
    public void clear() {
        for (ITempFile file : this.tempFiles) {
            try {
                file.delete();
            } catch (Exception ignored) {
                NanoHTTPD.LOG.log(Level.WARNING, "could not delete file ", ignored);
            }
        }
        this.tempFiles.clear();
    }

    @Override
    public ITempFile createTempFile(String filename_hint) throws Exception {
        DefaultTempFile tempFile = new DefaultTempFile(this.tmpdir);
        this.tempFiles.add(tempFile);
        return tempFile;
    }
}


================================================
FILE: core/src/main/java/org/nanohttpd/protocols/http/tempfiles/DefaultTempFileManagerFactory.java
================================================
package org.nanohttpd.protocols.http.tempfiles;

/*
 * #%L
 * NanoHttpd-Core
 * %%
 * Copyright (C) 2012 - 2016 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.nanohttpd.util.IFactory;

/**
 * Default strategy for creating and cleaning up temporary files.
 */
public class DefaultTempFileManagerFactory implements IFactory<ITempFileManager> {

    @Override
    public ITempFileManager create() {
        return new DefaultTempFileManager();
    }
}


================================================
FILE: core/src/main/java/org/nanohttpd/protocols/http/tempfiles/ITempFile.java
================================================
package org.nanohttpd.protocols.http.tempfiles;

/*
 * #%L
 * NanoHttpd-Core
 * %%
 * Copyright (C) 2012 - 2016 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.OutputStream;

/**
 * A temp file.
 * <p/>
 * <p>
 * Temp files are responsible for managing the actual temporary storage and
 * cleaning themselves up when no longer needed.
 * </p>
 */
public interface ITempFile {

    public void delete() throws Exception;

    public String getName();

    public OutputStream open() throws Exception;
}


================================================
FILE: core/src/main/java/org/nanohttpd/protocols/http/tempfiles/ITempFileManager.java
================================================
package org.nanohttpd.protocols.http.tempfiles;

/*
 * #%L
 * NanoHttpd-Core
 * %%
 * Copyright (C) 2012 - 2016 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%
 */

/**
 * Temp file manager.
 * <p/>
 * <p>
 * Temp file managers are created 1-to-1 with incoming requests, to create and
 * cleanup temporary files created as a result of handling the request.
 * </p>
 */
public interface ITempFileManager {

    void clear();

    public ITempFile createTempFile(String filename_hint) throws Exception;
}


================================================
FILE: core/src/main/java/org/nanohttpd/protocols/http/threading/DefaultAsyncRunner.java
================================================
package org.nanohttpd.protocols.http.threading;

/*
 * #%L
 * NanoHttpd-Core
 * %%
 * Copyright (C) 2012 - 2016 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.util.ArrayList;
import java.util.Collections;
import java.util.List;

import org.nanohttpd.protocols.http.ClientHandler;

/**
 * Default threading strategy for NanoHTTPD.
 * <p/>
 * <p>
 * By default, the server spawns a new Thread for every incoming request. These
 * are set to <i>daemon</i> status, and named according to the request number.
 * The name is useful when profiling the application.
 * </p>
 */
public class DefaultAsyncRunner implements IAsyncRunner {

    protected long requestCount;

    private final List<ClientHandler> running = Collections.synchronizedList(new ArrayList<ClientHandler>());

    /**
     * @return a list with currently running clients.
     */
    public List<ClientHandler> getRunning() {
        return running;
    }

    @Override
    public void closeAll() {
        // copy of the list for concurrency
        for (ClientHandler clientHandler : new ArrayList<ClientHandler>(this.running)) {
            clientHandler.close();
        }
    }

    @Override
    public void closed(ClientHandler clientHandler) {
        this.running.remove(clientHandler);
    }

    @Override
    public void exec(ClientHandler clientHandler) {
        ++this.requestCount;
        this.running.add(clientHandler);
        createThread(clientHandler).start();
    }

    protected Thread createThread(ClientHandler clientHandler) {
        Thread t = new Thread(clientHandler);
        t.setDaemon(true);
        t.setName("NanoHttpd Request Processor (#" + this.requestCount + ")");
        return t;
    }
}


================================================
FILE: core/src/main/java/org/nanohttpd/protocols/http/threading/IAsyncRunner.java
================================================
package org.nanohttpd.protocols.http.threading;

/*
 * #%L
 * NanoHttpd-Core
 * %%
 * Copyright (C) 2012 - 2016 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.nanohttpd.protocols.http.ClientHandler;

/**
 * Pluggable strategy for asynchronously executing requests.
 */
public interface IAsyncRunner {

    void closeAll();

    void closed(ClientHandler clientHandler);

    void exec(ClientHandler code);
}


================================================
FILE: core/src/main/java/org/nanohttpd/util/IFactory.java
================================================
package org.nanohttpd.util;

/*
 * #%L
 * NanoHttpd-Core
 * %%
 * Copyright (C) 2012 - 2016 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%
 */

/**
 * Represents a simple factory
 * 
 * @author LordFokas
 * @param <T>
 *            The Type of object to create
 */
public interface IFactory<T> {

    T create();
}


================================================
FILE: core/src/main/java/org/nanohttpd/util/IFactoryThrowing.java
================================================
package org.nanohttpd.util;

/*
 * #%L
 * NanoHttpd-Core
 * %%
 * Copyright (C) 2012 - 2016 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%
 */

/**
 * Represents a factory that can throw an exception instead of actually creating
 * an object
 * 
 * @author LordFokas
 * @param <T>
 *            The Type of object to create
 * @param <E>
 *            The base Type of exceptions that can be thrown
 */
public interface IFactoryThrowing<T, E extends Throwable> {

    T create() throws E;
}


================================================
FILE: core/src/main/java/org/nanohttpd/util/IHandler.java
================================================
package org.nanohttpd.util;

/*
 * #%L
 * NanoHttpd-Core
 * %%
 * Copyright (C) 2012 - 2016 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%
 */

/**
 * Defines a generic handler that returns an object of type O when given an
 * object of type I.
 * 
 * @author LordFokas
 * @param <I>
 *            The input type.
 * @param <O>
 *            The output type.
 */
public interface IHandler<I, O> {

    public O handle(I input);
}


================================================
FILE: core/src/main/java/org/nanohttpd/util/ServerRunner.java
================================================
package org.nanohttpd.util;

/*
 * #%L
 * NanoHttpd-Webserver
 * %%
 * 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.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.nanohttpd.protocols.http.NanoHTTPD;

public class ServerRunner {

    /**
     * logger to log to.
     */
    private static final Logger LOG = Logger.getLogger(ServerRunner.class.getName());

    public static void executeInstance(NanoHTTPD server) {
        try {
            server.start(NanoHTTPD.SOCKET_READ_TIMEOUT, false);
        } catch (IOException ioe) {
            System.err.println("Couldn't start server:\n" + ioe);
            System.exit(-1);
        }

        System.out.println("Server started, Hit Enter to stop.\n");

        try {
            System.in.read();
        } catch (Throwable ignored) {
        }

        server.stop();
        System.out.println("Server stopped.\n");
    }

    public static <T extends NanoHTTPD> void run(Class<T> serverClass) {
        try {
            executeInstance(serverClass.newInstance());
        } catch (Exception e) {
            ServerRunner.LOG.log(Level.SEVERE, "Could not create server", e);
        }
    }
}


================================================
FILE: core/src/main/resources/META-INF/nanohttpd/default-mimetypes.properties
================================================
#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

================================================
FILE: core/src/main/resources/META-INF/nanohttpd/mimetypes.properties
================================================
#mime types for nanohttpd, use a file like this for user defined mimetypes

================================================
FILE: core/src/site/site.xml
================================================
<?xml version="1.0" encoding="ISO-8859-1"?>
<project name="${project.name}">
	<skin>
		<groupId>org.apache.maven.skins</groupId>
		<artifactId>maven-fluido-skin</artifactId>
		<version>1.3.0</version>
	</skin>
	<bannerLeft>
		<src>../images/nanohttpd_logo.png</src>
	</bannerLeft>
	<bannerRight>
		<src>../images/nanohttpd_logo_text.png</src>
	</bannerRight>
	<publishDate position="left" format="yyyy-MM-dd" />
	<version position="right" />
	<poweredBy>
		<logo name="Maven" href="http://maven.apache.org/"
			img="http://maven.apache.org/images/logos/maven-feather.png" />
	</poweredBy>
	<custom>
		<fluidoSkin>
			<topBarEnabled>false</topBarEnabled>
			<sideBarEnabled>true</sideBarEnabled>
			<gitHub>
				<projectId>Nanohttpd/nanohttpd</projectId>
				<ribbonOrientation>right</ribbonOrientation>
				<ribbonColor>black</ribbonColor>
			</gitHub>
		</fluidoSkin>
	</custom>
	<body>
		<breadcrumbs>
			<item name="${project.name}" href="index.html" />
		</breadcrumbs>
		<menu name="Documentation">
			<item name="About" href="index.html" />
		</menu>
		<menu ref="modules" />
		<menu ref="reports" />
	</body>
</project>

================================================
FILE: core/src/test/java/org/nanohttpd/junit/protocols/http/BadRequestTest.java
================================================
package org.nanohttpd.junit.protocols.http;

/*
 * #%L
 * NanoHttpd-Core
 * %%
 * Copyright (C) 2012 - 2016 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.ByteArrayOutputStream;
import java.io.IOException;

import org.junit.Test;

public class BadRequestTest extends HttpServerTest {

    @Test
    public void testEmptyRequest() throws IOException {
        ByteArrayOutputStream outputStream = invokeServer("\n\n");
        String[] expected = new String[]{
            "HTTP/1.1 400 Bad Request"
        };
        assertResponse(outputStream, expected);
    }

    @Test
    public void testInvalidMethod() throws IOException {
        ByteArrayOutputStream outputStream = invokeServer("GETT http://example.com");
        String[] expected = new String[]{
            "HTTP/1.1 400 Bad Request"
        };
        assertResponse(outputStream, expected);
    }

    @Test
    public void testMissingURI() throws IOException {
        ByteArrayOutputStream outputStream = invokeServer("GET");
        String[] expected = new String[]{
            "HTTP/1.1 400 Bad Request"
        };
        assertResponse(outputStream, expected);
    }

}


================================================
FILE: core/src/test/java/org/nanohttpd/junit/protocols/http/CookieHandlerTest.java
================================================
package org.nanohttpd.junit.protocols.http;

/*
 * #%L
 * NanoHttpd-Core
 * %%
 * Copyright (C) 2012 - 2016 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 static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashSet;
import java.util.Locale;
import java.util.Set;
import java.util.TimeZone;

import org.junit.Test;
import org.nanohttpd.protocols.http.HTTPSession;
import org.nanohttpd.protocols.http.content.CookieHandler;
import org.nanohttpd.protocols.http.response.Response;

public class CookieHandlerTest extends HttpServerTest {

    @Test
    public void testCookieHeaderCorrectlyParsed() throws IOException {
        StringBuilder requestBuilder = new StringBuilder();
        requestBuilder.append("GET " + HttpServerTest.URI + " HTTP/1.1").append(System.getProperty("line.separator")).append("Cookie: theme=light; sessionToken=abc123");

        ByteArrayInputStream inputStream = new ByteArrayInputStream(requestBuilder.toString().getBytes());
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        HTTPSession session = this.testServer.createSession(this.tempFileManager, inputStream, outputStream);
        session.execute();
        Set<String> allCookies = new HashSet<String>();
        CookieHandler cookieHandler = session.getCookies();
        for (String cookie : cookieHandler) {
            allCookies.add(cookie);
        }
        assertTrue("cookie specified in header not correctly parsed", allCookies.contains("theme"));
        assertTrue("cookie specified in header not correctly parsed", allCookies.contains("sessionToken"));
        assertEquals("cookie value not correctly parsed", "light", cookieHandler.read("theme"));
        assertEquals("cookie value not correctly parsed", "abc123", cookieHandler.read("sessionToken"));

    }

    @Test
    public void testCookieHeaderWithSpecialCharactersCorrectlyParsed() throws IOException {
        StringBuilder requestBuilder = new StringBuilder();
        // not including ; = and ,
        requestBuilder.append("GET " + HttpServerTest.URI + " HTTP/1.1").append(System.getProperty("line.separator"))
                .append("Cookie: theme=light; sessionToken=abc123!@#$%^&*()-_+{}[]\\|:\"'<>.?/");

        ByteArrayInputStream inputStream = new ByteArrayInputStream(requestBuilder.toString().getBytes());
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        HTTPSession session = this.testServer.createSession(this.tempFileManager, inputStream, outputStream);
        session.execute();
        Set<String> allCookies = new HashSet<String>();
        CookieHandler cookieHandler = session.getCookies();
        for (String cookie : cookieHandler) {
            allCookies.add(cookie);
        }
        assertTrue("cookie specified in header not correctly parsed", allCookies.contains("theme"));
        assertTrue("cookie specified in header not correctly parsed", allCookies.contains("sessionToken"));
        assertEquals("cookie value not correctly parsed", "light", cookieHandler.read("theme"));
        assertEquals("cookie value not correctly parsed", "abc123!@#$%^&*()-_+{}[]\\|:\"'<>.?/", cookieHandler.read("sessionToken"));

    }

    @Test
    public void testUnloadQueue() throws IOException {
        StringBuilder requestBuilder = new StringBuilder();
        requestBuilder.append("GET " + HttpServerTest.URI + " HTTP/1.1").append(System.getProperty("line.separator")).append("Cookie: theme=light; sessionToken=abc123");

        ByteArrayInputStream inputStream = new ByteArrayInputStream(requestBuilder.toString().getBytes());
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        HTTPSession session = this.testServer.createSession(this.tempFileManager, inputStream, outputStream);
        session.execute();
        CookieHandler cookieHandler = session.getCookies();
        Response response = Response.newFixedLengthResponse("");
        cookieHandler.set("name", "value", 30);
        cookieHandler.unloadQueue(response);
        String setCookieHeader = response.getCookieHeaders().get(0);
        assertTrue("unloadQueue did not set the cookies correctly", setCookieHeader.startsWith("name=value; expires="));
    }

    @Test
    public void testDelete() throws IOException, ParseException {
        StringBuilder requestBuilder = new StringBuilder();
        requestBuilder.append("GET " + HttpServerTest.URI + " HTTP/1.1").append(System.getProperty("line.separator")).append("Cookie: theme=light; sessionToken=abc123");

        ByteArrayInputStream inputStream = new ByteArrayInputStream(requestBuilder.toString().getBytes());
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        HTTPSession session = this.testServer.createSession(this.tempFileManager, inputStream, outputStream);
        session.execute();
        CookieHandler cookieHandler = session.getCookies();

        Response response = Response.newFixedLengthResponse("");
        cookieHandler.delete("name");
        cookieHandler.unloadQueue(response);

        String setCookieHeader = response.getCookieHeaders().get(0);
        SimpleDateFormat dateFormat = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z", Locale.US);
        dateFormat.setTimeZone(TimeZone.getTimeZone("GMT"));
        String dateString = setCookieHeader.split(";")[1].split("=")[1].trim();
        Date date = dateFormat.parse(dateString);
        assertTrue("Deleted cookie's expiry time should be a time in the past", date.compareTo(new Date()) < 0);
    }
}


================================================
FILE: core/src/test/java/org/nanohttpd/junit/protocols/http/CookieTest.java
================================================
package org.nanohttpd.junit.protocols.http;

/*
 * #%L
 * NanoHttpd-Core
 * %%
 * Copyright (C) 2012 - 2016 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 static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;

import java.util.Random;

import org.junit.Test;
import org.nanohttpd.protocols.http.content.Cookie;

public class CookieTest {

    @Test
    public void testGetHTTPTime() {
        Random random = new Random();
        int randomExpirationTime = random.nextInt(100);
        assertNotNull("getHTTPTime should return a non-null value for " + randomExpirationTime + " days", Cookie.getHTTPTime(randomExpirationTime));
    }

    @Test
    public void testCookieWithNoExplicitExpirationTime() {
        Cookie cookie = new Cookie("CookieKey", "CookieValue");
        assertTrue("Cookie header should contain cookie key", cookie.getHTTPHeader().contains("CookieKey"));
        assertTrue("Cookie header should contain cookie value", cookie.getHTTPHeader().contains("CookieValue"));
    }

    @Test
    public void testCookieWithExplicitExpirationTime() {
        Cookie cookie = new Cookie("CookieKey", "CookieValue", 40);
        assertFalse("The default 30 days expires string should not be avaialbe in the cookie header" + " because the expiry has been specified as 40 days", cookie
                .getHTTPHeader().contains(Cookie.getHTTPTime(30)));
        assertTrue("Cookie header should contain cookie key", cookie.getHTTPHeader().contains("CookieKey"));
        assertTrue("Cookie header should contain cookie value", cookie.getHTTPHeader().contains("CookieValue"));
    }

    @Test
    public void testCookieWithExpiresString() {
        Random random = new Random();
        int randomExpirationTime = random.nextInt(100);
        String expiresString = Cookie.getHTTPTime(randomExpirationTime);
        Cookie cookie = new Cookie("CookieKey", "CookieValue", expiresString);
        assertTrue("Cookie should contain the expirs string passed in the constructor", cookie.getHTTPHeader().contains(expiresString));
        assertTrue("Cookie header should contain cookie key", cookie.getHTTPHeader().contains("CookieKey"));
        assertTrue("Cookie header should contain cookie value", cookie.getHTTPHeader().contains("CookieValue"));
    }

}


================================================
FILE: core/src/test/java/org/nanohttpd/junit/protocols/http/HttpChunkedResponseTest.java
================================================
package org.nanohttpd.junit.protocols.http;

/*
 * #%L
 * NanoHttpd-Core
 * %%
 * Copyright (C) 2012 - 2016 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.ByteArrayOutputStream;
import java.io.IOException;
import java.io.PipedInputStream;

import org.nanohttpd.protocols.http.response.Response;
import org.nanohttpd.protocols.http.response.Status;

public class HttpChunkedResponseTest extends HttpServerTest {

    private static class ChunkedInputStream extends PipedInputStream {

        int chunk = 0;

        String[] chunks;

        private ChunkedInputStream(String[] chunks) {
            this.chunks = chunks;
        }

        @Override
        public synchronized int read(byte[] buffer, int off, int len) throws IOException {
            // Too implementation-linked, but...
            for (int i = 0; i < this.chunks[this.chunk].length(); ++i) {
                buffer[i] = (byte) this.chunks[this.chunk].charAt(i);
            }
            return this.chunks[this.chunk++].length();
        }
    }

    @org.junit.Test
    public void thatChunkedContentIsChunked() throws Exception {
        PipedInputStream pipedInputStream = new ChunkedInputStream(new String[]{
            "some",
            "thing which is longer than sixteen characters",
            "whee!",
            ""
        });
        String[] expected = {
            "HTTP/1.1 200 OK",
            "Content-Type: what/ever",
            "Date: .*",
            "Connection: keep-alive",
            "Transfer-Encoding: chunked",
            "",
            "4",
            "some",
            "2d",
            "thing which is longer than sixteen characters",
            "5",
            "whee!",
            "0",
            ""
        };
        this.testServer.response = Response.newChunkedResponse(Status.OK, "what/ever", pipedInputStream);
        this.testServer.response.setChunkedTransfer(true);

        ByteArrayOutputStream byteArrayOutputStream = invokeServer("GET / HTTP/1.1");

        assertResponse(byteArrayOutputStream, expected);
    }
}


================================================
FILE: core/src/test/java/org/nanohttpd/junit/protocols/http/HttpDeleteRequestTest.java
================================================
package org.nanohttpd.junit.protocols.http;

/*
 * #%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 java.io.ByteArrayOutputStream;
import java.io.InputStream;

import org.junit.Test;
import org.nanohttpd.protocols.http.NanoHTTPD;
import org.nanohttpd.protocols.http.response.Response;
import org.nanohttpd.protocols.http.response.Status;

public class HttpDeleteRequestTest extends HttpServerTest {

    @Test
    public void testDeleteRequestThatDoesntSendBackResponseBody_EmptyString() throws Exception {
        this.testServer.response = Response.newFixedLengthResponse(Status.NO_CONTENT, NanoHTTPD.MIME_HTML, "");

        ByteArrayOutputStream outputStream = invokeServer("DELETE " + HttpServerTest.URI + " HTTP/1.1");

        String[] expected = {
            "HTTP/1.1 204 No Content",
            "Content-Type: text/html",
            "Date: .*",
            "Connection: keep-alive",
            "Content-Length: 0",
            ""
        };

        assertResponse(outputStream, expected);
    }

    @Test
    public void testDeleteRequestThatDoesntSendBackResponseBody_NullInputStream() throws Exception {
        this.testServer.response = Response.newChunkedResponse(Status.NO_CONTENT, NanoHTTPD.MIME_HTML, (InputStream) null);

        ByteArrayOutputStream outputStream = invokeServer("DELETE " + HttpServerTest.URI + " HTTP/1.1");

        String[] expected = {
            "HTTP/1.1 204 No Content",
            "Content-Type: text/html",
            "Date: .*",
            "Connection: keep-alive",
            "Content-Length: 0",
            ""
        };

        assertResponse(outputStream, expected);
    }

    @Test
    public void testDeleteRequestThatDoesntSendBackResponseBody_NullString() throws Exception {
        this.testServer.response = Response.newFixedLengthResponse(Status.NO_CONTENT, NanoHTTPD.MIME_HTML, (String) null);

        ByteArrayOutputStream outputStream = invokeServer("DELETE " + HttpServerTest.URI + " HTTP/1.1");

        String[] expected = {
            "HTTP/1.1 204 No Content",
            "Content-Type: text/html",
            "Date: .*",
            "Connection: keep-alive",
            "Content-Length: 0",
            ""
        };

        assertResponse(outputStream, expected);
    }

    @Test
    public void testDeleteRequestThatSendsBackResponseBody_Accepted() throws Exception {
        this.testServer.response = Response.newFixedLengthResponse(Status.ACCEPTED, "application/xml", "<body />");

        ByteArrayOutputStream outputStream = invokeServer("DELETE " + HttpServerTest.URI + " HTTP/1.1");

        String[] expected = {
            "HTTP/1.1 202 Accepted",
            "Content-Type: application/xml",
            "Date: .*",
            "Connection: keep-alive",
            "Content-Length: 8",
            "",
            "<body />"
        };

        assertResponse(outputStream, expected);
    }

    @Test
    public void testDeleteRequestThatSendsBackResponseBody_Success() throws Exception {
        this.testServer.response = Response.newFixedLengthResponse(Status.OK, "application/xml", "<body />");

        ByteArrayOutputStream outputStream = invokeServer("DELETE " + HttpServerTest.URI + " HTTP/1.1");

        String[] expected = {
            "HTTP/1.1 200 OK",
            "Content-Type: application/xml",
            "Date: .*",
            "Connection: keep-alive",
            "Content-Length: 8",
            "",
            "<body />"
        };

        assertResponse(outputStream, expected);
    }
}


================================================
FILE: core/src/test/java/org/nanohttpd/junit/protocols/http/HttpGetRequestTest.java
================================================
package org.nanohttpd.junit.protocols.http;

/*
 * #%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 static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;

import java.io.ByteArrayOutputStream;
import java.util.List;

import org.junit.Test;
import org.nanohttpd.protocols.http.request.Method;
import org.nanohttpd.protocols.http.response.Response;

public class HttpGetRequestTest extends HttpServerTest {

    @Test
    public void testDecodingFieldWithEmptyValueAndFieldWithMissingValueGiveDifferentResults() {
        invokeServer("GET " + HttpServerTest.URI + "?foo&bar= HTTP/1.1");
        assertTrue(this.testServer.decodedParamters.get("foo") instanceof List);
        assertEquals(0, this.testServer.decodedParamters.get("foo").size());
        assertTrue(this.testServer.decodedParamters.get("bar") instanceof List);
        assertEquals(1, this.testServer.decodedParamters.get("bar").size());
        assertEquals("", this.testServer.decodedParamters.get("bar").get(0));
    }

    @Test
    public void testDecodingMixtureOfParameters() {
        invokeServer("GET " + HttpServerTest.URI + "?foo=bar&foo=baz&zot&zim= HTTP/1.1");
        assertTrue(this.testServer.decodedParamters.get("foo") instanceof List);
        assertEquals(2, this.testServer.decodedParamters.get("foo").size());
        assertEquals("bar", this.testServer.decodedParamters.get("foo").get(0));
        assertEquals("baz", this.testServer.decodedParamters.get("foo").get(1));
        assertTrue(this.testServer.decodedParamters.get("zot") instanceof List);
        assertEquals(0, this.testServer.decodedParamters.get("zot").size());
        assertTrue(this.testServer.decodedParamters.get("zim") instanceof List);
        assertEquals(1, this.testServer.decodedParamters.get("zim").size());
        assertEquals("", this.testServer.decodedParamters.get("zim").get(0));
    }

    @Test
    public void testDecodingParametersFromParameterMap() {
        invokeServer("GET " + HttpServerTest.URI + "?foo=bar&foo=baz&zot&zim= HTTP/1.1");
        assertEquals(this.testServer.decodedParamters, this.testServer.decodedParamtersFromParameter);
    }

    // --------------------------------------------------------------------------------------------------------
    // //

    @Test
    public void testDecodingParametersWithSingleValue() {
        invokeServer("GET " + HttpServerTest.URI + "?foo=bar&baz=zot HTTP/1.1");
        assertEquals("foo=bar&baz=zot", this.testServer.queryParameterString);
        assertTrue(this.testServer.decodedParamters.get("foo") instanceof List);
        assertEquals(1, this.testServer.decodedParamters.get("foo").size());
        assertEquals("bar", this.testServer.decodedParamters.get("foo").get(0));
        assertTrue(this.testServer.decodedParamters.get("baz") instanceof List);
        assertEquals(1, this.testServer.decodedParamters.get("baz").size());
        assertEquals("zot", this.testServer.decodedParamters.get("baz").get(0));
    }

    @Test
    public void testDecodingParametersWithSingleValueAndMissingValue() {
        invokeServer("GET " + HttpServerTest.URI + "?foo&baz=zot HTTP/1.1");
        assertEquals("foo&baz=zot", this.testServer.queryParameterString);
        assertTrue(this.testServer.decodedParamters.get("foo") instanceof List);
        assertEquals(0, this.testServer.decodedParamters.get("foo").size());
        assertTrue(this.testServer.decodedParamters.get("baz") instanceof List);
        assertEquals(1, this.testServer.decodedParamters.get("baz").size());
        assertEquals("zot", this.testServer.decodedParamters.get("baz").get(0));
    }

    @Test
    public void testDecodingSingleFieldRepeated() {
        invokeServer("GET " + HttpServerTest.URI + "?foo=bar&foo=baz HTTP/1.1");
        assertTrue(this.testServer.decodedParamters.get("foo") instanceof List);
        assertEquals(2, this.testServer.decodedParamters.get("foo").size());
        assertEquals("bar", this.testServer.decodedParamters.get("foo").get(0));
        assertEquals("baz", this.testServer.decodedParamters.get("foo").get(1));
    }

    @Test
    public void testEmptyHeadersSuppliedToServeMethodFromSimpleWorkingGetRequest() {
        invokeServer("GET " + HttpServerTest.URI + " HTTP/1.1");
        assertNotNull(this.testServer.parms);
        assertNotNull(this.testServer.parameters);
        assertNotNull(this.testServer.header);
        assertNotNull(this.testServer.files);
        assertNotNull(this.testServer.uri);
    }

    @Test
    public void testFullyQualifiedWorkingGetRequest() throws Exception {
        ByteArrayOutputStream outputStream = invokeServer("GET " + HttpServerTest.URI + " HTTP/1.1");

        String[] expected = {
            "HTTP/1.1 200 OK",
            "Content-Type: text/html",
            "Date: .*",
            "Connection: keep-alive",
            "Content-Length: 0",
            ""
        };

        assertResponse(outputStream, expected);
    }

    @Test
    public void testMultipleGetParameters() {
        invokeServer("GET " + HttpServerTest.URI + "?foo=bar&baz=zot HTTP/1.1");
        assertEquals("bar", this.testServer.parms.get("foo"));
        assertEquals("zot", this.testServer.parms.get("baz"));
        assertEquals("bar", this.testServer.parameters.get("foo").get(0));
        assertEquals("zot", this.testServer.parameters.get("baz").get(0));
    }

    @Test
    public void testMultipleGetParametersWithMissingValue() {
        invokeServer("GET " + HttpServerTest.URI + "?foo=&baz=zot HTTP/1.1");
        assertEquals("", this.testServer.parms.get("foo"));
        assertEquals("zot", this.testServer.parms.get("baz"));
        assertEquals("", this.testServer.parameters.get("foo").get(0));
        assertEquals("zot", this.testServer.parameters.get("baz").get(0));
    }

    @Test
    public void testMultipleGetParametersWithMissingValueAndRequestHeaders() {
        invokeServer("GET " + HttpServerTest.URI + "?foo=&baz=zot HTTP/1.1\nAccept: text/html");
        assertEquals("", this.testServer.parms.get("foo"));
        assertEquals("zot", this.testServer.parms.get("baz"));
        assertEquals("", this.testServer.parameters.get("foo").get(0));
        assertEquals("zot", this.testServer.parameters.get("baz").get(0));
        assertEquals("text/html", this.testServer.header.get("accept"));
    }

    @Test
    public void testMultipleHeaderSuppliedToServeMethodFromSimpleWorkingGetRequest() {
        String userAgent = "jUnit 4.8.2 Unit Test";
        String accept = "text/html";
        invokeServer("GET " + HttpServerTest.URI + " HTTP/1.1\nUser-Agent: " + userAgent + "\nAccept: " + accept);
        assertEquals(userAgent, this.testServer.header.get("user-agent"));
        assertEquals(accept, this.testServer.header.get("accept"));
    }

    @Test
    public void testOutputOfServeSentBackToClient() throws Exception {
        String responseBody = "Success!";
        this.testServer.response = Response.newFixedLengthResponse(responseBody);
        ByteArrayOutputStream outputStream = invokeServer("GET " + HttpServerTest.URI + " HTTP/1.1");

        String[] expected = {
            "HTTP/1.1 200 OK",
            "Content-Type: text/html",
            "Date: .*",
            "Connection: keep-alive",
            "Content-Length: 8",
            "",
            responseBody
        };

        assertResponse(outputStream, expected);
    }

    @Test
    public void testSingleGetParameter() {
        invokeServer("GET " + HttpServerTest.URI + "?foo=bar HTTP/1.1");
        assertEquals("bar", this.testServer.parms.get("foo"));
        assertEquals("bar", this.testServer.parameters.get("foo").get(0));
    }

    @Test
    public void testMultipleValueGetParameter() {
        invokeServer("GET " + HttpServerTest.URI + "?foo=bar&foo=baz HTTP/1.1");
        assertEquals("bar", this.testServer.parms.get("foo"));
        assertEquals(2, this.testServer.parameters.get("foo").size());
        assertEquals("bar", this.testServer.parameters.get("foo").get(0));
        assertEquals("baz", this.testServer.parameters.get("foo").get(1));
    }

    @Test
    public void testSingleGetParameterWithNoValue() {
        invokeServer("GET " + HttpServerTest.URI + "?foo HTTP/1.1");
        assertEquals("", this.testServer.parms.get("foo"));
        assertEquals("", this.testServer.parameters.get("foo").get(0));
    }

    @Test
    public void testSingleUserAgentHeaderSuppliedToServeMethodFromSimpleWorkingGetRequest() {
        String userAgent = "jUnit 4.8.2 Unit Test";
        invokeServer("GET " + HttpServerTest.URI + " HTTP/1.1\nUser-Agent: " + userAgent + "\n");
        assertEquals(userAgent, this.testServer.header.get("user-agent"));
        assertEquals(Method.GET, this.testServer.method);
        assertEquals(HttpServerTest.URI, this.testServer.uri);
    }

    @Test
    public void testGetQueryParameterContainsSpace() {
        invokeServer("GET " + HttpServerTest.URI + "?foo=bar%20baz HTTP/1.1");
        assertEquals("Parameter count in URL and decodedParameters should match.", 1, this.testServer.decodedParamters.size());
        assertEquals("The query parameter value with space decoding incorrect", "bar baz", this.testServer.decodedParamters.get("foo").get(0));
    }

    @Test
    public void testGetQueryParameterContainsQuestionMark() {
        invokeServer("GET " + HttpServerTest.URI + "?foo=bar%3F HTTP/1.1");
        assertEquals("Parameter count in URL and decodedParameters should match.", 1, this.testServer.decodedParamters.size());
        assertEquals("The query parameter value with question mark decoding incorrect", "bar?", this.testServer.decodedParamters.get("foo").get(0));
    }

    @Test
    public void testGetQueryParameterContainsAmpersand() {
        invokeServer("GET " + HttpServerTest.URI + "?foo=bar%26 HTTP/1.1");
        assertEquals("Parameter count in URL and decodedParameters should match.", 1, this.testServer.decodedParamters.size());
        assertEquals("The query parameter value with ampersand decoding incorrect", "bar&", this.testServer.decodedParamters.get("foo").get(0));
    }

    @Test
    public void testGetQueryParameterContainsSpecialCharactersSingleFieldRepeated() {
        invokeServer("GET " + HttpServerTest.URI + "?foo=bar%20baz&foo=bar%3F&foo=bar%26 HTTP/1.1");
        assertEquals("Parameter count in URL and decodedParameters should match.", 1, this.testServer.decodedParamters.size());
        String[] parametersAsArray = this.testServer.decodedParamters.get("foo").toArray(new String[0]);
        String[] expected = new String[]{
            "bar baz",
            "bar?",
            "bar&"
        };
        assertArrayEquals("Repeated parameter not decoded correctly", expected, parametersAsArray);
    }
}


================================================
FILE: core/src/test/java/org/nanohttpd/junit/protocols/http/HttpHeadRequestTest.java
================================================
package org.nanohttpd.junit.protocols.http;

/*
 * #%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 static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertNotNull;
import static junit.framework.Assert.assertTrue;

import java.io.ByteArrayOutputStream;
import java.util.List;

import org.junit.Test;
import org.nanohttpd.protocols.http.request.Method;
import org.nanohttpd.protocols.http.response.Response;

public class HttpHeadRequestTest extends HttpServerTest {

    @Override
    public void setUp() throws Exception {
        super.setUp();
        String responseBody = "Success!";
        this.testServer.response = Response.newFixedLengthResponse(responseBody);
    }

    @Test
    public void testDecodingFieldWithEmptyValueAndFieldWithMissingValueGiveDifferentResults() {
        invokeServer("HEAD " + HttpServerTest.URI + "?foo&bar= HTTP/1.1");
        assertTrue(this.testServer.decodedParamters.get("foo") instanceof List);
        assertEquals(0, this.testServer.decodedParamters.get("foo").size());
        assertTrue(this.testServer.decodedParamters.get("bar") instanceof List);
        assertEquals(1, this.testServer.decodedParamters.get("bar").size());
        assertEquals("", this.testServer.decodedParamters.get("bar").get(0));
    }

    @Test
    public void testDecodingMixtureOfParameters() {
        invokeServer("HEAD " + HttpServerTest.URI + "?foo=bar&foo=baz&zot&zim= HTTP/1.1");
        assertTrue(this.testServer.decodedParamters.get("foo") instanceof List);
        assertEquals(2, this.testServer.decodedParamters.get("foo").size());
        assertEquals("bar", this.testServer.decodedParamters.get("foo").get(0));
        assertEquals("baz", this.testServer.decodedParamters.get("foo").get(1));
        assertTrue(this.testServer.decodedParamters.get("zot") instanceof List);
        assertEquals(0, this.testServer.decodedParamters.get("zot").size());
        assertTrue(this.testServer.decodedParamters.get("zim") instanceof List);
        assertEquals(1, this.testServer.decodedParamters.get("zim").size());
        assertEquals("", this.testServer.decodedParamters.get("zim").get(0));
    }

    @Test
    public void testDecodingParametersFromParameterMap() {
        invokeServer("HEAD " + HttpServerTest.URI + "?foo=bar&foo=baz&zot&zim= HTTP/1.1");
        assertEquals(this.testServer.decodedParamters, this.testServer.decodedParamtersFromParameter);
    }

    // --------------------------------------------------------------------------------------------------------
    // //

    @Test
    public void testDecodingParametersWithSingleValue() {
        invokeServer("HEAD " + HttpServerTest.URI + "?foo=bar&baz=zot HTTP/1.1");
        assertEquals("foo=bar&baz=zot", this.testServer.queryParameterString);
        assertTrue(this.testServer.decodedParamters.get("foo") instanceof List);
        assertEquals(1, this.testServer.decodedParamters.get("foo").size());
        assertEquals("bar", this.testServer.decodedParamters.get("foo").get(0));
        assertTrue(this.testServer.decodedParamters.get("baz") instanceof List);
        assertEquals(1, this.testServer.decodedParamters.get("baz").size());
        assertEquals("zot", this.testServer.decodedParamters.get("baz").get(0));
    }

    @Test
    public void testDecodingParametersWithSingleValueAndMissingValue() {
        invokeServer("HEAD " + HttpServerTest.URI + "?foo&baz=zot HTTP/1.1");
        assertEquals("foo&baz=zot", this.testServer.queryParameterString);
        assertTrue(this.testServer.decodedParamters.get("foo") instanceof List);
        assertEquals(0, this.testServer.decodedParamters.get("foo").size());
        assertTrue(this.testServer.decodedParamters.get("baz") instanceof List);
        assertEquals(1, this.testServer.decodedParamters.get("baz").size());
        assertEquals("zot", this.testServer.decodedParamters.get("baz").get(0));
    }

    @Test
    public void testDecodingSingleFieldRepeated() {
        invokeServer("HEAD " + HttpServerTest.URI + "?foo=bar&foo=baz HTTP/1.1");
        assertTrue(this.testServer.decodedParamters.get("foo") instanceof List);
        assertEquals(2, this.testServer.decodedParamters.get("foo").size());
        assertEquals("bar", this.testServer.decodedParamters.get("foo").get(0));
        assertEquals("baz", this.testServer.decodedParamters.get("foo").get(1));
    }

    @Test
    public void testEmptyHeadersSuppliedToServeMethodFromSimpleWorkingGetRequest() {
        invokeServer("HEAD " + HttpServerTest.URI + " HTTP/1.1");
        assertNotNull(this.testServer.parms);
        assertNotNull(this.testServer.parameters);
        assertNotNull(this.testServer.header);
        assertNotNull(this.testServer.files);
        assertNotNull(this.testServer.uri);
    }

    @Test
    public void testHeadRequestDoesntSendBackResponseBody() throws Exception {
        ByteArrayOutputStream outputStream = invokeServer("HEAD " + HttpServerTest.URI + " HTTP/1.1");

        String[] expected = {
            "HTTP/1.1 200 OK",
            "Content-Type: text/html",
            "Date: .*",
            "Connection: keep-alive",
            "Content-Length: 8",
            ""
        };

        assertResponse(outputStream, expected);
    }

    @Test
    public void testMultipleGetParameters() {
        invokeServer("HEAD " + HttpServerTest.URI + "?foo=bar&baz=zot HTTP/1.1");
        assertEquals("bar", this.testServer.parms.get("foo"));
        assertEquals("zot", this.testServer.parms.get("baz"));
        assertEquals("bar", this.testServer.parameters.get("foo").get(0));
        assertEquals("zot", this.testServer.parameters.get("baz").get(0));
    }

    @Test
    public void testMultipleGetParametersWithMissingValue() {
        invokeServer("HEAD " + HttpServerTest.URI + "?foo=&baz=zot HTTP/1.1");
        assertEquals("", this.testServer.parms.get("foo"));
        assertEquals("zot", this.testServer.parms.get("baz"));
        assertEquals("", this.testServer.parameters.get("foo").get(0));
        assertEquals("zot", this.testServer.parameters.get("baz").get(0));
    }

    @Test
    public void testMultipleGetParametersWithMissingValueAndRequestHeaders() {
        invokeServer("HEAD " + HttpServerTest.URI + "?foo=&baz=zot HTTP/1.1\nAccept: text/html");
        assertEquals("", this.testServer.parms.get("foo"));
        assertEquals("zot", this.testServer.parms.get("baz"));
        assertEquals("", this.testServer.parameters.get("foo").get(0));
        assertEquals("zot", this.testServer.parameters.get("baz").get(0));
        assertEquals("text/html", this.testServer.header.get("accept"));
    }

    @Test
    public void testMultipleHeaderSuppliedToServeMethodFromSimpleWorkingGetRequest() {
        String userAgent = "jUnit 4.8.2 Unit Test";
        String accept = "text/html";
        invokeServer("HEAD " + HttpServerTest.URI + " HTTP/1.1\nUser-Agent: " + userAgent + "\nAccept: " + accept);
        assertEquals(userAgent, this.testServer.header.get("user-agent"));
        assertEquals(accept, this.testServer.header.get("accept"));
    }

    @Test
    public void testSingleGetParameter() {
        invokeServer("HEAD " + HttpServerTest.URI + "?foo=bar HTTP/1.1");
        assertEquals("bar", this.testServer.parms.get("foo"));
        assertEquals("bar", this.testServer.parameters.get("foo").get(0));
    }

    @Test
    public void testMultipleValueGetParameter() {
        invokeServer("HEAD " + HttpServerTest.URI + "?foo=bar&foo=baz HTTP/1.1");
        assertEquals("bar", this.testServer.parms.get("foo"));
        assertEquals(2, this.testServer.parameters.get("foo").size());
        assertEquals("bar", this.testServer.parameters.get("foo").get(0));
        assertEquals("baz", this.testServer.parameters.get("foo").get(1));
    }

    @Test
    public void testSingleGetParameterWithNoValue() {
        invokeServer("HEAD " + HttpServerTest.URI + "?foo HTTP/1.1");
        assertEquals("", this.testServer.parms.get("foo"));
        assertEquals("", this.testServer.parameters.get("foo").get(0));
    }

    @Test
    public void testSingleUserAgentHeaderSuppliedToServeMethodFromSimpleWorkingGetRequest() {
        String userAgent = "jUnit 4.8.2 Unit Test";
        invokeServer("HEAD " + HttpServerTest.URI + " HTTP/1.1\nUser-Agent: " + userAgent + "\n");
        assertEquals(userAgent, this.testServer.header.get("user-agent"));
        assertEquals(Method.HEAD, this.testServer.method);
        assertEquals(HttpServerTest.URI, this.testServer.uri);
    }

}


================================================
FILE: core/src/test/java/org/nanohttpd/junit/protocols/http/HttpKeepAliveTest.java
================================================
package org.nanohttpd.junit.protocols.http;

/*
 * #%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, INCLUDIN
Download .txt
gitextract_2uva_0s3/

├── .gitignore
├── .travis.yml
├── LICENSE.md
├── README.md
├── build.gradle
├── core/
│   ├── .gitignore
│   ├── build.gradle
│   ├── pom.xml
│   └── src/
│       ├── main/
│       │   ├── java/
│       │   │   └── org/
│       │   │       └── nanohttpd/
│       │   │           ├── protocols/
│       │   │           │   └── http/
│       │   │           │       ├── ClientHandler.java
│       │   │           │       ├── HTTPSession.java
│       │   │           │       ├── IHTTPSession.java
│       │   │           │       ├── NanoHTTPD.java
│       │   │           │       ├── ServerRunnable.java
│       │   │           │       ├── content/
│       │   │           │       │   ├── ContentType.java
│       │   │           │       │   ├── Cookie.java
│       │   │           │       │   └── CookieHandler.java
│       │   │           │       ├── request/
│       │   │           │       │   └── Method.java
│       │   │           │       ├── response/
│       │   │           │       │   ├── ChunkedOutputStream.java
│       │   │           │       │   ├── IStatus.java
│       │   │           │       │   ├── Response.java
│       │   │           │       │   └── Status.java
│       │   │           │       ├── sockets/
│       │   │           │       │   ├── DefaultServerSocketFactory.java
│       │   │           │       │   └── SecureServerSocketFactory.java
│       │   │           │       ├── tempfiles/
│       │   │           │       │   ├── DefaultTempFile.java
│       │   │           │       │   ├── DefaultTempFileManager.java
│       │   │           │       │   ├── DefaultTempFileManagerFactory.java
│       │   │           │       │   ├── ITempFile.java
│       │   │           │       │   └── ITempFileManager.java
│       │   │           │       └── threading/
│       │   │           │           ├── DefaultAsyncRunner.java
│       │   │           │           └── IAsyncRunner.java
│       │   │           └── util/
│       │   │               ├── IFactory.java
│       │   │               ├── IFactoryThrowing.java
│       │   │               ├── IHandler.java
│       │   │               └── ServerRunner.java
│       │   └── resources/
│       │       └── META-INF/
│       │           └── nanohttpd/
│       │               ├── default-mimetypes.properties
│       │               └── mimetypes.properties
│       ├── site/
│       │   └── site.xml
│       └── test/
│           ├── java/
│           │   └── org/
│           │       └── nanohttpd/
│           │           └── junit/
│           │               └── protocols/
│           │                   └── http/
│           │                       ├── BadRequestTest.java
│           │                       ├── CookieHandlerTest.java
│           │                       ├── CookieTest.java
│           │                       ├── HttpChunkedResponseTest.java
│           │                       ├── HttpDeleteRequestTest.java
│           │                       ├── HttpGetRequestTest.java
│           │                       ├── HttpHeadRequestTest.java
│           │                       ├── HttpKeepAliveTest.java
│           │                       ├── HttpParsingTest.java
│           │                       ├── HttpPostRequestTest.java
│           │                       ├── HttpPutRequestTest.java
│           │                       ├── HttpSSLServerTest.java
│           │                       ├── HttpServerTest.java
│           │                       ├── HttpSessionHeadersTest.java
│           │                       ├── HttpSessionTest.java
│           │                       ├── InvalidRequestTest.java
│           │                       ├── JavaIOTempDirExistTest.java
│           │                       ├── LoadKeyStoreTest.java
│           │                       ├── MimeTest.java
│           │                       ├── SSLServerSocketFactoryTest.java
│           │                       ├── ServerSocketFactoryTest.java
│           │                       ├── StatusTest.java
│           │                       └── integration/
│           │                           ├── CookieIntegrationTest.java
│           │                           ├── GZipIntegrationTest.java
│           │                           ├── GetAndPostIntegrationTest.java
│           │                           ├── IntegrationTestBase.java
│           │                           ├── PutStreamIntegrationTest.java
│           │                           └── ShutdownTest.java
│           └── resources/
│               ├── META-INF/
│               │   └── nanohttpd/
│               │       └── mimetypes.properties
│               ├── file-upload-test.htm
│               ├── keystore.jks
│               └── multipart-form-test.htm
├── fileupload/
│   ├── .gitignore
│   ├── build.gradle
│   ├── pom.xml
│   └── src/
│       ├── main/
│       │   └── java/
│       │       └── org/
│       │           └── nanohttpd/
│       │               └── fileupload/
│       │                   └── NanoFileUpload.java
│       └── test/
│           └── java/
│               └── org/
│                   └── nanohttpd/
│                       └── junit/
│                           └── fileupload/
│                               └── TestNanoFileUpLoad.java
├── markdown-plugin/
│   ├── .gitignore
│   ├── build.gradle
│   ├── pom.xml
│   └── src/
│       ├── main/
│       │   ├── java/
│       │   │   └── org/
│       │   │       └── nanohttpd/
│       │   │           └── markdown/
│       │   │               ├── MarkdownWebServerPlugin.java
│       │   │               └── MarkdownWebServerPluginInfo.java
│       │   └── resources/
│       │       └── META-INF/
│       │           └── services/
│       │               └── org.nanohttpd.webserver.WebServerPluginInfo
│       └── site/
│           └── site.xml
├── nanohttpd release perform.launch
├── nanohttpd release prepare.launch
├── nanolets/
│   ├── .gitignore
│   ├── build.gradle
│   ├── pom.xml
│   └── src/
│       ├── main/
│       │   └── java/
│       │       └── org/
│       │           └── nanohttpd/
│       │               └── router/
│       │                   └── RouterNanoHTTPD.java
│       └── test/
│           ├── java/
│           │   └── org/
│           │       └── nanohttpd/
│           │           └── junit/
│           │               └── router/
│           │                   ├── AppNanolets.java
│           │                   └── TestNanolets.java
│           └── resources/
│               ├── blabla.html
│               ├── dir/
│               │   ├── blabla.html
│               │   └── index.htm
│               └── exception.html
├── pom.xml
├── relocation/
│   ├── nanohttpd/
│   │   ├── pom.xml
│   │   └── src/
│   │       └── main/
│   │           └── resources/
│   │               └── relocated.txt
│   ├── nanohttpd-samples/
│   │   ├── pom.xml
│   │   └── src/
│   │       └── main/
│   │           └── resources/
│   │               └── relocated.txt
│   ├── nanohttpd-webserver/
│   │   ├── pom.xml
│   │   └── src/
│   │       └── main/
│   │           └── resources/
│   │               └── relocated.txt
│   ├── nanohttpd-webserver-markdown-plugin/
│   │   ├── pom.xml
│   │   └── src/
│   │       └── main/
│   │           └── resources/
│   │               └── relocated.txt
│   ├── nanohttpd-websocket/
│   │   ├── pom.xml
│   │   └── src/
│   │       └── main/
│   │           └── resources/
│   │               └── relocated.txt
│   └── pom.xml
├── samples/
│   ├── .gitignore
│   ├── build.gradle
│   ├── pom.xml
│   └── src/
│       ├── main/
│       │   └── java/
│       │       └── org/
│       │           └── nanohttpd/
│       │               └── samples/
│       │                   ├── http/
│       │                   │   ├── DebugServer.java
│       │                   │   └── HelloServer.java
│       │                   └── tempfiles/
│       │                       └── TempFilesServer.java
│       └── site/
│           └── site.xml
├── settings.gradle
├── settings.xml
├── src/
│   ├── main/
│   │   ├── checkstyle/
│   │   │   ├── checkstyle-suppressions.xml
│   │   │   └── nanohttpd-style.xml
│   │   └── formatter/
│   │       └── formatter.xml
│   └── site/
│       ├── markdown/
│       │   └── index.md
│       └── site.xml
├── webserver/
│   ├── .gitignore
│   ├── build.gradle
│   ├── pom.xml
│   └── src/
│       ├── main/
│       │   └── java/
│       │       └── org/
│       │           └── nanohttpd/
│       │               └── webserver/
│       │                   ├── InternalRewrite.java
│       │                   ├── SimpleWebServer.java
│       │                   ├── WebServerPlugin.java
│       │                   └── WebServerPluginInfo.java
│       ├── site/
│       │   └── site.xml
│       └── test/
│           ├── java/
│           │   └── org/
│           │       └── nanohttpd/
│           │           └── junit/
│           │               └── webserver/
│           │                   ├── AbstractTestHttpServer.java
│           │                   ├── DummyPlugin.java
│           │                   ├── DummyPluginInfo.java
│           │                   ├── TestCorsHttpServer.java
│           │                   ├── TestCorsHttpServerWithSingleOrigin.java
│           │                   └── TestHttpServer.java
│           └── resources/
│               ├── META-INF/
│               │   └── services/
│               │       └── org.nanohttpd.webserver.WebServerPluginInfo
│               └── testdir/
│                   ├── test.html
│                   └── testdir/
│                       ├── different.xml
│                       └── index.html
└── websocket/
    ├── .gitignore
    ├── build.gradle
    ├── pom.xml
    └── src/
        ├── main/
        │   └── java/
        │       └── org/
        │           └── nanohttpd/
        │               ├── protocols/
        │               │   └── websockets/
        │               │       ├── CloseCode.java
        │               │       ├── CloseFrame.java
        │               │       ├── NanoWSD.java
        │               │       ├── OpCode.java
        │               │       ├── State.java
        │               │       ├── WebSocket.java
        │               │       ├── WebSocketException.java
        │               │       └── WebSocketFrame.java
        │               └── samples/
        │                   └── websockets/
        │                       ├── DebugWebSocketServer.java
        │                       └── EchoSocketSample.java
        ├── site/
        │   └── site.xml
        └── test/
            ├── java/
            │   └── org/
            │       └── nanohttpd/
            │           └── junit/
            │               └── protocols/
            │                   └── websockets/
            │                       ├── EchoWebSocketsTest.java
            │                       ├── SimpleEchoSocket.java
            │                       └── WebSocketResponseHandlerTest.java
            └── resources/
                └── echo-test.html
Download .txt
SYMBOL INDEX (817 symbols across 87 files)

FILE: core/src/main/java/org/nanohttpd/protocols/http/ClientHandler.java
  class ClientHandler (line 48) | public class ClientHandler implements Runnable {
    method ClientHandler (line 56) | public ClientHandler(NanoHTTPD httpd, InputStream inputStream, Socket ...
    method close (line 62) | public void close() {
    method run (line 67) | @Override

FILE: core/src/main/java/org/nanohttpd/protocols/http/HTTPSession.java
  class HTTPSession (line 74) | public class HTTPSession implements IHTTPSession {
    method HTTPSession (line 114) | public HTTPSession(NanoHTTPD httpd, ITempFileManager tempFileManager, ...
    method HTTPSession (line 121) | public HTTPSession(NanoHTTPD httpd, ITempFileManager tempFileManager, ...
    method decodeHeader (line 133) | private void decodeHeader(BufferedReader in, Map<String, String> pre, ...
    method decodeMultipartFormData (line 191) | private void decodeMultipartFormData(ContentType contentType, ByteBuff...
    method scipOverNewLine (line 295) | private int scipOverNewLine(byte[] partHeaderBuff, int index) {
    method decodeParms (line 306) | private void decodeParms(String parms, Map<String, List<String>> p) {
    method execute (line 338) | @Override
    method findHeaderEnd (line 467) | private int findHeaderEnd(final byte[] buf, int rlen) {
    method getBoundaryPositions (line 490) | private int[] getBoundaryPositions(ByteBuffer b, byte[] boundary) {
    method getCookies (line 531) | @Override
    method getHeaders (line 536) | @Override
    method getInputStream (line 541) | @Override
    method getMethod (line 546) | @Override
    method getParms (line 554) | @Override
    method getParameters (line 565) | @Override
    method getQueryParameterString (line 570) | @Override
    method getTmpBucket (line 575) | private RandomAccessFile getTmpBucket() {
    method getUri (line 584) | @Override
    method getBodySize (line 593) | public long getBodySize() {
    method parseBody (line 602) | @Override
    method saveTmpFile (line 673) | private String saveTmpFile(ByteBuffer b, int offset, int len, String f...
    method getRemoteIpAddress (line 694) | @Override

FILE: core/src/main/java/org/nanohttpd/protocols/http/IHTTPSession.java
  type IHTTPSession (line 48) | public interface IHTTPSession {
    method execute (line 50) | void execute() throws IOException;
    method getCookies (line 52) | CookieHandler getCookies();
    method getHeaders (line 54) | Map<String, String> getHeaders();
    method getInputStream (line 56) | InputStream getInputStream();
    method getMethod (line 58) | Method getMethod();
    method getParms (line 67) | @Deprecated
    method getParameters (line 70) | Map<String, List<String>> getParameters();
    method getQueryParameterString (line 72) | String getQueryParameterString();
    method getUri (line 77) | String getUri();
    method parseBody (line 85) | void parseBody(Map<String, String> files) throws IOException, Response...
    method getRemoteIpAddress (line 92) | String getRemoteIpAddress();

FILE: core/src/main/java/org/nanohttpd/protocols/http/NanoHTTPD.java
  class NanoHTTPD (line 125) | public abstract class NanoHTTPD {
    class ResponseException (line 139) | public static final class ResponseException extends Exception {
      method ResponseException (line 145) | public ResponseException(Status status, String message) {
      method ResponseException (line 150) | public ResponseException(Status status, String message, Exception e) {
      method getStatus (line 155) | public Status getStatus() {
    method mimeTypes (line 193) | public static Map<String, String> mimeTypes() {
    method loadMimeTypes (line 205) | @SuppressWarnings({
    method makeSSLSocketFactory (line 236) | public static SSLServerSocketFactory makeSSLSocketFactory(KeyStore loa...
    method makeSSLSocketFactory (line 255) | public static SSLServerSocketFactory makeSSLSocketFactory(KeyStore loa...
    method makeSSLSocketFactory (line 267) | public static SSLServerSocketFactory makeSSLSocketFactory(String keyAn...
    method getMimeTypeForFile (line 292) | public static String getMimeTypeForFile(String uri) {
    method safeClose (line 301) | public static final void safeClose(Object closeable) {
    method getMyServerSocket (line 325) | public ServerSocket getMyServerSocket() {
    method NanoHTTPD (line 350) | public NanoHTTPD(int port) {
    method NanoHTTPD (line 365) | public NanoHTTPD(String hostname, int port) {
    method setHTTPHandler (line 381) | public void setHTTPHandler(IHandler<IHTTPSession, Response> handler) {
    method addHTTPInterceptor (line 385) | public void addHTTPInterceptor(IHandler<IHTTPSession, Response> interc...
    method closeAllConnections (line 392) | public synchronized void closeAllConnections() {
    method createClientHandler (line 406) | protected ClientHandler createClientHandler(final Socket finalAccept, ...
    method createServerRunnable (line 418) | protected ServerRunnable createServerRunnable(final int timeout) {
    method decodeParameters (line 433) | protected static Map<String, List<String>> decodeParameters(Map<String...
    method decodeParameters (line 450) | protected static Map<String, List<String>> decodeParameters(String que...
    method decodePercent (line 478) | public static String decodePercent(String str) {
    method getListeningPort (line 488) | public final int getListeningPort() {
    method isAlive (line 492) | public final boolean isAlive() {
    method getServerSocketFactory (line 496) | public IFactoryThrowing<ServerSocket, IOException> getServerSocketFact...
    method setServerSocketFactory (line 500) | public void setServerSocketFactory(IFactoryThrowing<ServerSocket, IOEx...
    method getHostname (line 504) | public String getHostname() {
    method getTempFileManagerFactory (line 508) | public IFactory<ITempFileManager> getTempFileManagerFactory() {
    method makeSecure (line 515) | public void makeSecure(SSLServerSocketFactory sslServerSocketFactory, ...
    method handle (line 529) | public Response handle(IHTTPSession session) {
    method serve (line 548) | @Deprecated
    method setAsyncRunner (line 559) | public void setAsyncRunner(IAsyncRunner asyncRunner) {
    method setTempFileManagerFactory (line 569) | public void setTempFileManagerFactory(IFactory<ITempFileManager> tempF...
    method start (line 579) | public void start() throws IOException {
    method start (line 586) | public void start(final int timeout) throws IOException {
    method start (line 600) | public void start(final int timeout, boolean daemon) throws IOException {
    method stop (line 626) | public void stop() {
    method wasStarted (line 638) | public final boolean wasStarted() {

FILE: core/src/main/java/org/nanohttpd/protocols/http/ServerRunnable.java
  class ServerRunnable (line 45) | public class ServerRunnable implements Runnable {
    method ServerRunnable (line 55) | public ServerRunnable(NanoHTTPD httpd, int timeout) {
    method run (line 60) | @Override
    method getBindException (line 83) | public IOException getBindException() {
    method hasBinded (line 87) | public boolean hasBinded() {

FILE: core/src/main/java/org/nanohttpd/protocols/http/content/ContentType.java
  class ContentType (line 39) | public class ContentType {
    method ContentType (line 65) | public ContentType(String contentTypeHeader) {
    method getDetailFromContentHeader (line 81) | private String getDetailFromContentHeader(String contentTypeHeader, Pa...
    method getContentTypeHeader (line 86) | public String getContentTypeHeader() {
    method getContentType (line 90) | public String getContentType() {
    method getEncoding (line 94) | public String getEncoding() {
    method getBoundary (line 98) | public String getBoundary() {
    method isMultipart (line 102) | public boolean isMultipart() {
    method tryUTF8 (line 106) | public ContentType tryUTF8() {

FILE: core/src/main/java/org/nanohttpd/protocols/http/content/Cookie.java
  class Cookie (line 46) | public class Cookie {
    method getHTTPTime (line 48) | public static String getHTTPTime(int days) {
    method Cookie (line 58) | public Cookie(String name, String value) {
    method Cookie (line 62) | public Cookie(String name, String value, int numDays) {
    method Cookie (line 68) | public Cookie(String name, String value, String expires) {
    method getHTTPHeader (line 74) | public String getHTTPHeader() {

FILE: core/src/main/java/org/nanohttpd/protocols/http/content/CookieHandler.java
  class CookieHandler (line 50) | public class CookieHandler implements Iterable<String> {
    method CookieHandler (line 56) | public CookieHandler(Map<String, String> httpHeaders) {
    method delete (line 76) | public void delete(String name) {
    method iterator (line 80) | @Override
    method read (line 92) | public String read(String name) {
    method set (line 96) | public void set(Cookie cookie) {
    method set (line 110) | public void set(String name, String value, int expires) {
    method unloadQueue (line 122) | public void unloadQueue(Response response) {

FILE: core/src/main/java/org/nanohttpd/protocols/http/request/Method.java
  type Method (line 40) | public enum Method {
    method lookup (line 60) | public static Method lookup(String method) {

FILE: core/src/main/java/org/nanohttpd/protocols/http/response/ChunkedOutputStream.java
  class ChunkedOutputStream (line 45) | public class ChunkedOutputStream extends FilterOutputStream {
    method ChunkedOutputStream (line 47) | public ChunkedOutputStream(OutputStream out) {
    method write (line 51) | @Override
    method write (line 59) | @Override
    method write (line 64) | @Override
    method finish (line 73) | public void finish() throws IOException {

FILE: core/src/main/java/org/nanohttpd/protocols/http/response/IStatus.java
  type IStatus (line 36) | public interface IStatus {
    method getDescription (line 38) | String getDescription();
    method getRequestStatus (line 40) | int getRequestStatus();

FILE: core/src/main/java/org/nanohttpd/protocols/http/response/Response.java
  class Response (line 66) | public class Response implements Closeable {
    method put (line 92) | public String put(String key, String value) {
    type GzipUsage (line 119) | private static enum GzipUsage {
    method Response (line 128) | @SuppressWarnings({
    method close (line 147) | @Override
    method addCookieHeader (line 158) | public void addCookieHeader(String cookie) {
    method getCookieHeaders (line 168) | public List<String> getCookieHeaders() {
    method addHeader (line 175) | public void addHeader(String name, String value) {
    method closeConnection (line 186) | public void closeConnection(boolean close) {
    method isCloseConnection (line 197) | public boolean isCloseConnection() {
    method getData (line 201) | public InputStream getData() {
    method getHeader (line 205) | public String getHeader(String name) {
    method getMimeType (line 209) | public String getMimeType() {
    method getRequestMethod (line 213) | public Method getRequestMethod() {
    method getStatus (line 217) | public IStatus getStatus() {
    method setKeepAlive (line 221) | public void setKeepAlive(boolean useKeepAlive) {
    method send (line 228) | public void send(OutputStream outputStream) {
    method printHeader (line 276) | @SuppressWarnings("static-method")
    method sendContentLengthHeaderIfNotAlreadyPresent (line 281) | protected long sendContentLengthHeaderIfNotAlreadyPresent(PrintWriter ...
    method sendBodyWithCorrectTransferAndEncoding (line 296) | private void sendBodyWithCorrectTransferAndEncoding(OutputStream outpu...
    method sendBodyWithCorrectEncoding (line 312) | private void sendBodyWithCorrectEncoding(OutputStream outputStream, lo...
    method sendBody (line 344) | private void sendBody(OutputStream outputStream, long pending) throws ...
    method setChunkedTransfer (line 367) | public void setChunkedTransfer(boolean chunkedTransfer) {
    method setData (line 371) | public void setData(InputStream data) {
    method setMimeType (line 375) | public void setMimeType(String mimeType) {
    method setRequestMethod (line 379) | public void setRequestMethod(Method requestMethod) {
    method setStatus (line 383) | public void setStatus(IStatus status) {
    method newChunkedResponse (line 390) | public static Response newChunkedResponse(IStatus status, String mimeT...
    method newFixedLengthResponse (line 394) | public static Response newFixedLengthResponse(IStatus status, String m...
    method newFixedLengthResponse (line 401) | public static Response newFixedLengthResponse(IStatus status, String m...
    method newFixedLengthResponse (line 408) | public static Response newFixedLengthResponse(IStatus status, String m...
    method newFixedLengthResponse (line 431) | public static Response newFixedLengthResponse(String msg) {
    method setUseGzip (line 435) | public Response setUseGzip(boolean useGzip) {
    method useGzipWhenAccepted (line 442) | public boolean useGzipWhenAccepted() {

FILE: core/src/main/java/org/nanohttpd/protocols/http/response/Status.java
  type Status (line 39) | public enum Status implements IStatus {
    method Status (line 88) | Status(int requestStatus, String description) {
    method lookup (line 93) | public static Status lookup(int requestStatus) {
    method getDescription (line 102) | @Override
    method getRequestStatus (line 107) | @Override

FILE: core/src/main/java/org/nanohttpd/protocols/http/sockets/DefaultServerSocketFactory.java
  class DefaultServerSocketFactory (line 44) | public class DefaultServerSocketFactory implements IFactoryThrowing<Serv...
    method create (line 46) | @Override

FILE: core/src/main/java/org/nanohttpd/protocols/http/sockets/SecureServerSocketFactory.java
  class SecureServerSocketFactory (line 47) | public class SecureServerSocketFactory implements IFactoryThrowing<Serve...
    method SecureServerSocketFactory (line 53) | public SecureServerSocketFactory(SSLServerSocketFactory sslServerSocke...
    method create (line 58) | @Override

FILE: core/src/main/java/org/nanohttpd/protocols/http/tempfiles/DefaultTempFile.java
  class DefaultTempFile (line 51) | public class DefaultTempFile implements ITempFile {
    method DefaultTempFile (line 57) | public DefaultTempFile(File tempdir) throws IOException {
    method delete (line 62) | @Override
    method getName (line 70) | @Override
    method open (line 75) | @Override

FILE: core/src/main/java/org/nanohttpd/protocols/http/tempfiles/DefaultTempFileManager.java
  class DefaultTempFileManager (line 53) | public class DefaultTempFileManager implements ITempFileManager {
    method DefaultTempFileManager (line 59) | public DefaultTempFileManager() {
    method clear (line 67) | @Override
    method createTempFile (line 79) | @Override

FILE: core/src/main/java/org/nanohttpd/protocols/http/tempfiles/DefaultTempFileManagerFactory.java
  class DefaultTempFileManagerFactory (line 41) | public class DefaultTempFileManagerFactory implements IFactory<ITempFile...
    method create (line 43) | @Override

FILE: core/src/main/java/org/nanohttpd/protocols/http/tempfiles/ITempFile.java
  type ITempFile (line 46) | public interface ITempFile {
    method delete (line 48) | public void delete() throws Exception;
    method getName (line 50) | public String getName();
    method open (line 52) | public OutputStream open() throws Exception;

FILE: core/src/main/java/org/nanohttpd/protocols/http/tempfiles/ITempFileManager.java
  type ITempFileManager (line 44) | public interface ITempFileManager {
    method clear (line 46) | void clear();
    method createTempFile (line 48) | public ITempFile createTempFile(String filename_hint) throws Exception;

FILE: core/src/main/java/org/nanohttpd/protocols/http/threading/DefaultAsyncRunner.java
  class DefaultAsyncRunner (line 51) | public class DefaultAsyncRunner implements IAsyncRunner {
    method getRunning (line 60) | public List<ClientHandler> getRunning() {
    method closeAll (line 64) | @Override
    method closed (line 72) | @Override
    method exec (line 77) | @Override
    method createThread (line 84) | protected Thread createThread(ClientHandler clientHandler) {

FILE: core/src/main/java/org/nanohttpd/protocols/http/threading/IAsyncRunner.java
  type IAsyncRunner (line 41) | public interface IAsyncRunner {
    method closeAll (line 43) | void closeAll();
    method closed (line 45) | void closed(ClientHandler clientHandler);
    method exec (line 47) | void exec(ClientHandler code);

FILE: core/src/main/java/org/nanohttpd/util/IFactory.java
  type IFactory (line 43) | public interface IFactory<T> {
    method create (line 45) | T create();

FILE: core/src/main/java/org/nanohttpd/util/IFactoryThrowing.java
  type IFactoryThrowing (line 46) | public interface IFactoryThrowing<T, E extends Throwable> {
    method create (line 48) | T create() throws E;

FILE: core/src/main/java/org/nanohttpd/util/IHandler.java
  type IHandler (line 46) | public interface IHandler<I, O> {
    method handle (line 48) | public O handle(I input);

FILE: core/src/main/java/org/nanohttpd/util/ServerRunner.java
  class ServerRunner (line 42) | public class ServerRunner {
    method executeInstance (line 49) | public static void executeInstance(NanoHTTPD server) {
    method run (line 68) | public static <T extends NanoHTTPD> void run(Class<T> serverClass) {

FILE: core/src/test/java/org/nanohttpd/junit/protocols/http/BadRequestTest.java
  class BadRequestTest (line 41) | public class BadRequestTest extends HttpServerTest {
    method testEmptyRequest (line 43) | @Test
    method testInvalidMethod (line 52) | @Test
    method testMissingURI (line 61) | @Test

FILE: core/src/test/java/org/nanohttpd/junit/protocols/http/CookieHandlerTest.java
  class CookieHandlerTest (line 55) | public class CookieHandlerTest extends HttpServerTest {
    method testCookieHeaderCorrectlyParsed (line 57) | @Test
    method testCookieHeaderWithSpecialCharactersCorrectlyParsed (line 78) | @Test
    method testUnloadQueue (line 101) | @Test
    method testDelete (line 118) | @Test

FILE: core/src/test/java/org/nanohttpd/junit/protocols/http/CookieTest.java
  class CookieTest (line 44) | public class CookieTest {
    method testGetHTTPTime (line 46) | @Test
    method testCookieWithNoExplicitExpirationTime (line 53) | @Test
    method testCookieWithExplicitExpirationTime (line 60) | @Test
    method testCookieWithExpiresString (line 69) | @Test

FILE: core/src/test/java/org/nanohttpd/junit/protocols/http/HttpChunkedResponseTest.java
  class HttpChunkedResponseTest (line 43) | public class HttpChunkedResponseTest extends HttpServerTest {
    class ChunkedInputStream (line 45) | private static class ChunkedInputStream extends PipedInputStream {
      method ChunkedInputStream (line 51) | private ChunkedInputStream(String[] chunks) {
      method read (line 55) | @Override
    method thatChunkedContentIsChunked (line 65) | @org.junit.Test

FILE: core/src/test/java/org/nanohttpd/junit/protocols/http/HttpDeleteRequestTest.java
  class HttpDeleteRequestTest (line 44) | public class HttpDeleteRequestTest extends HttpServerTest {
    method testDeleteRequestThatDoesntSendBackResponseBody_EmptyString (line 46) | @Test
    method testDeleteRequestThatDoesntSendBackResponseBody_NullInputStream (line 64) | @Test
    method testDeleteRequestThatDoesntSendBackResponseBody_NullString (line 82) | @Test
    method testDeleteRequestThatSendsBackResponseBody_Accepted (line 100) | @Test
    method testDeleteRequestThatSendsBackResponseBody_Success (line 119) | @Test

FILE: core/src/test/java/org/nanohttpd/junit/protocols/http/HttpGetRequestTest.java
  class HttpGetRequestTest (line 48) | public class HttpGetRequestTest extends HttpServerTest {
    method testDecodingFieldWithEmptyValueAndFieldWithMissingValueGiveDifferentResults (line 50) | @Test
    method testDecodingMixtureOfParameters (line 60) | @Test
    method testDecodingParametersFromParameterMap (line 74) | @Test
    method testDecodingParametersWithSingleValue (line 83) | @Test
    method testDecodingParametersWithSingleValueAndMissingValue (line 95) | @Test
    method testDecodingSingleFieldRepeated (line 106) | @Test
    method testEmptyHeadersSuppliedToServeMethodFromSimpleWorkingGetRequest (line 115) | @Test
    method testFullyQualifiedWorkingGetRequest (line 125) | @Test
    method testMultipleGetParameters (line 141) | @Test
    method testMultipleGetParametersWithMissingValue (line 150) | @Test
    method testMultipleGetParametersWithMissingValueAndRequestHeaders (line 159) | @Test
    method testMultipleHeaderSuppliedToServeMethodFromSimpleWorkingGetRequest (line 169) | @Test
    method testOutputOfServeSentBackToClient (line 178) | @Test
    method testSingleGetParameter (line 197) | @Test
    method testMultipleValueGetParameter (line 204) | @Test
    method testSingleGetParameterWithNoValue (line 213) | @Test
    method testSingleUserAgentHeaderSuppliedToServeMethodFromSimpleWorkingGetRequest (line 220) | @Test
    method testGetQueryParameterContainsSpace (line 229) | @Test
    method testGetQueryParameterContainsQuestionMark (line 236) | @Test
    method testGetQueryParameterContainsAmpersand (line 243) | @Test
    method testGetQueryParameterContainsSpecialCharactersSingleFieldRepeated (line 250) | @Test

FILE: core/src/test/java/org/nanohttpd/junit/protocols/http/HttpHeadRequestTest.java
  class HttpHeadRequestTest (line 47) | public class HttpHeadRequestTest extends HttpServerTest {
    method setUp (line 49) | @Override
    method testDecodingFieldWithEmptyValueAndFieldWithMissingValueGiveDifferentResults (line 56) | @Test
    method testDecodingMixtureOfParameters (line 66) | @Test
    method testDecodingParametersFromParameterMap (line 80) | @Test
    method testDecodingParametersWithSingleValue (line 89) | @Test
    method testDecodingParametersWithSingleValueAndMissingValue (line 101) | @Test
    method testDecodingSingleFieldRepeated (line 112) | @Test
    method testEmptyHeadersSuppliedToServeMethodFromSimpleWorkingGetRequest (line 121) | @Test
    method testHeadRequestDoesntSendBackResponseBody (line 131) | @Test
    method testMultipleGetParameters (line 147) | @Test
    method testMultipleGetParametersWithMissingValue (line 156) | @Test
    method testMultipleGetParametersWithMissingValueAndRequestHeaders (line 165) | @Test
    method testMultipleHeaderSuppliedToServeMethodFromSimpleWorkingGetRequest (line 175) | @Test
    method testSingleGetParameter (line 184) | @Test
    method testMultipleValueGetParameter (line 191) | @Test
    method testSingleGetParameterWithNoValue (line 200) | @Test
    method testSingleUserAgentHeaderSuppliedToServeMethodFromSimpleWorkingGetRequest (line 207) | @Test

FILE: core/src/test/java/org/nanohttpd/junit/protocols/http/HttpKeepAliveTest.java
  class HttpKeepAliveTest (line 46) | public class HttpKeepAliveTest extends HttpServerTest {
    method testManyGetRequests (line 50) | @Test
    method testManyPutRequests (line 64) | @Test
    method testManyRequests (line 89) | public void testManyRequests(final String request, final String[] expe...

FILE: core/src/test/java/org/nanohttpd/junit/protocols/http/HttpParsingTest.java
  class HttpParsingTest (line 40) | public class HttpParsingTest extends HttpServerTest {
    method testMultibyteCharacterSupport (line 42) | @Test
    method testNormalCharacters (line 49) | @Test
    method testPlusInQueryParams (line 59) | @Test

FILE: core/src/test/java/org/nanohttpd/junit/protocols/http/HttpPostRequestTest.java
  class HttpPostRequestTest (line 47) | public class HttpPostRequestTest extends HttpServerTest {
    method preparePostWithMultipartForm (line 73) | private String preparePostWithMultipartForm(String fileName, String fi...
    method testPostWithMultipartFormUpload (line 87) | @Test
    method testPostWithMultipartFormUploadFilenameHasSpaces (line 104) | @Test
    method testPostWithMultipleMultipartFormFields (line 119) | @Test
    method testPostWithMultipleMultipartFormFieldsWhereContentTypeWasSeparatedByComma (line 142) | @Test
    method testSimplePostWithSingleMultipartFormField (line 165) | @Test
    method testSimpleRawPostData (line 185) | @Test
    method testPostWithMultipartFormFieldsAndFile (line 200) | @Test
    method testPostWithMultipartFormUploadMultipleFiles (line 228) | @Test
    method testPostWithMultipartFormUploadFileWithMultilineContent (line 274) | @Test

FILE: core/src/test/java/org/nanohttpd/junit/protocols/http/HttpPutRequestTest.java
  class HttpPutRequestTest (line 45) | public class HttpPutRequestTest extends HttpServerTest {
    method testPutRequestSendsContent (line 47) | @Test

FILE: core/src/test/java/org/nanohttpd/junit/protocols/http/HttpSSLServerTest.java
  class HttpSSLServerTest (line 50) | public class HttpSSLServerTest extends HttpServerTest {
    method testSSLConnection (line 52) | @Test
    method testHttpOnSSLConnection (line 70) | @Test(expected = ClientProtocolException.class)
    method setUp (line 77) | @Before
    method tearDown (line 97) | @After

FILE: core/src/test/java/org/nanohttpd/junit/protocols/http/HttpServerTest.java
  class HttpServerTest (line 79) | public class HttpServerTest {
    class TestServer (line 81) | public static class TestServer extends NanoHTTPD {
      method TestServer (line 103) | public TestServer() {
      method TestServer (line 107) | public TestServer(int port) {
      method createSession (line 111) | public HTTPSession createSession(ITempFileManager tempFileManager, I...
      method createSession (line 115) | public HTTPSession createSession(ITempFileManager tempFileManager, I...
      method serve (line 119) | @Override
    class TestTempFileManager (line 140) | public static class TestTempFileManager extends DefaultTempFileManager {
      method _clear (line 142) | public void _clear() {
      method clear (line 146) | @Override
    method assertLinesOfText (line 158) | protected void assertLinesOfText(String[] expected, List<String> lines) {
    method assertResponse (line 166) | protected void assertResponse(ByteArrayOutputStream outputStream, Stri...
    method getOutputLines (line 171) | protected List<String> getOutputLines(ByteArrayOutputStream outputStre...
    method invokeServer (line 176) | protected ByteArrayOutputStream invokeServer(String request) {
    method readLinesFromFile (line 189) | protected List<String> readLinesFromFile(BufferedReader reader) throws...
    method setUp (line 201) | @Before
    method tearDown (line 207) | @After
    method testServerExists (line 212) | @Test
    method testMultipartFormData (line 217) | @Test
    method testTempFileInterface (line 276) | @Test

FILE: core/src/test/java/org/nanohttpd/junit/protocols/http/HttpSessionHeadersTest.java
  class HttpSessionHeadersTest (line 46) | public class HttpSessionHeadersTest extends HttpServerTest {
    method testHeadersRemoteIp (line 52) | @Test

FILE: core/src/test/java/org/nanohttpd/junit/protocols/http/HttpSessionTest.java
  class HttpSessionTest (line 46) | public class HttpSessionTest extends HttpServerTest {
    method testSessionRemoteIPAddress (line 52) | @Test

FILE: core/src/test/java/org/nanohttpd/junit/protocols/http/InvalidRequestTest.java
  class InvalidRequestTest (line 40) | public class InvalidRequestTest extends HttpServerTest {
    method testGetRequestWithoutProtocol (line 42) | @Test
    method testGetRequestWithProtocol (line 53) | @Test
    method testPostRequestWithoutProtocol (line 64) | @Test
    method testPostRequestWithProtocol (line 74) | @Test

FILE: core/src/test/java/org/nanohttpd/junit/protocols/http/JavaIOTempDirExistTest.java
  class JavaIOTempDirExistTest (line 48) | public class JavaIOTempDirExistTest {
    method testJavaIoTempDefault (line 50) | @Test
    method testJavaIoTempSpecific (line 70) | @Test

FILE: core/src/test/java/org/nanohttpd/junit/protocols/http/LoadKeyStoreTest.java
  class LoadKeyStoreTest (line 49) | public class LoadKeyStoreTest {
    method loadKeyStoreFromResources (line 54) | @Test
    method loadKeyStoreFromResourcesWrongPassword (line 64) | @Test
    method loadNonExistentKeyStoreFromResources (line 74) | @Test

FILE: core/src/test/java/org/nanohttpd/junit/protocols/http/MimeTest.java
  class MimeTest (line 40) | public class MimeTest {
    method testExistingMimeType (line 42) | @Test
    method testNotExistingMimeType (line 47) | @Test
    method testOverwritenMimeType (line 53) | @Test
    method testManualMimeType (line 58) | @Test

FILE: core/src/test/java/org/nanohttpd/junit/protocols/http/SSLServerSocketFactoryTest.java
  class SSLServerSocketFactoryTest (line 55) | public class SSLServerSocketFactoryTest extends HttpServerTest {
    method testSSLConnection (line 57) | @Test
    method testCreatePassesTheProtocolsToServerSocket (line 69) | @Test
    method setUp (line 87) | @Before
    method tearDown (line 107) | @After

FILE: core/src/test/java/org/nanohttpd/junit/protocols/http/ServerSocketFactoryTest.java
  class ServerSocketFactoryTest (line 47) | public class ServerSocketFactoryTest extends NanoHTTPD {
    method ServerSocketFactoryTest (line 51) | public ServerSocketFactoryTest() {
    method isCustomServerSocketFactory (line 57) | @Test
    method testCreateServerSocket (line 63) | @Test
    method testSSLServerSocketFail (line 74) | @Test
    class TestFactory (line 90) | private class TestFactory implements IFactoryThrowing<ServerSocket, IO...
      method create (line 92) | @Override

FILE: core/src/test/java/org/nanohttpd/junit/protocols/http/StatusTest.java
  class StatusTest (line 43) | public class StatusTest {
    method testMessages (line 45) | @Test
    method getExpectedMessage (line 71) | private String getExpectedMessage(Status status) {
    method testLookup (line 87) | @Test

FILE: core/src/test/java/org/nanohttpd/junit/protocols/http/integration/CookieIntegrationTest.java
  class CookieIntegrationTest (line 59) | public class CookieIntegrationTest extends IntegrationTestBase<CookieInt...
    class CookieTestServer (line 61) | public static class CookieTestServer extends NanoHTTPD {
      method CookieTestServer (line 67) | public CookieTestServer() {
      method serve (line 71) | @Override
    method createTestServer (line 84) | @Override
    method testCookieSentBackToClient (line 89) | @Test
    method testMultipleCookieSentBackToClient (line 102) | @Test
    method testNoCookies (line 115) | @Test
    method testServerReceivesCookiesSentFromClient (line 125) | @Test
    method testServerReceivesMultipleCookiesSentFromClient (line 141) | @Test

FILE: core/src/test/java/org/nanohttpd/junit/protocols/http/integration/GZipIntegrationTest.java
  class GZipIntegrationTest (line 58) | public class GZipIntegrationTest extends IntegrationTestBase<GZipIntegra...
    class TestServer (line 60) | public static class TestServer extends NanoHTTPD {
      method TestServer (line 64) | public TestServer() {
      method serve (line 68) | @Override
    method createTestServer (line 74) | @Override
    method contentEncodingShouldBeAddedToFixedLengthResponses (line 79) | @Test
    method contentEncodingShouldBeAddedToChunkedResponses (line 90) | @Test
    method shouldFindCorrectAcceptEncodingAmongMany (line 102) | @Test
    method contentLengthShouldBeRemovedFromZippedResponses (line 113) | @Test
    method fixedLengthContentIsEncodedProperly (line 123) | @Test
    method chunkedContentIsEncodedProperly (line 132) | @Test
    method noGzipWithoutAcceptEncoding (line 142) | @Test
    method contentShouldNotBeGzippedIfContentLengthIsAddedManually (line 152) | @Test

FILE: core/src/test/java/org/nanohttpd/junit/protocols/http/integration/GetAndPostIntegrationTest.java
  class GetAndPostIntegrationTest (line 70) | public class GetAndPostIntegrationTest extends IntegrationTestBase<GetAn...
    class TestServer (line 72) | public static class TestServer extends NanoHTTPD {
      method TestServer (line 76) | public TestServer() {
      method serve (line 80) | @Override
    method createTestServer (line 115) | @Override
    method testGetRequestWithParameters (line 120) | @Test
    method testPostRequestWithFormEncodedParameters (line 131) | @Test
    method testPostRequestWithMultipartEncodedParameters (line 147) | @Test
    method testPostWithNoParameters (line 163) | @Test
    method testSimpleGetRequest (line 174) | @Test
    method testPostRequestWithMultipartExtremEncodedParameters (line 185) | @Test
    method testPostRequestWithEncodedParameters (line 208) | @Test

FILE: core/src/test/java/org/nanohttpd/junit/protocols/http/integration/IntegrationTestBase.java
  class IntegrationTestBase (line 46) | public abstract class IntegrationTestBase<T extends NanoHTTPD> {
    method createTestServer (line 52) | public abstract T createTestServer();
    method setUp (line 54) | @Before
    method tearDown (line 65) | @After

FILE: core/src/test/java/org/nanohttpd/junit/protocols/http/integration/PutStreamIntegrationTest.java
  class PutStreamIntegrationTest (line 53) | public class PutStreamIntegrationTest extends IntegrationTestBase<PutStr...
    class TestServer (line 55) | public static class TestServer extends NanoHTTPD {
      method TestServer (line 57) | public TestServer() {
      method serve (line 61) | @Override
    method createTestServer (line 81) | @Override
    method testSimplePutRequest (line 86) | @Test

FILE: core/src/test/java/org/nanohttpd/junit/protocols/http/integration/ShutdownTest.java
  class ShutdownTest (line 49) | public class ShutdownTest {
    class TestServer (line 51) | private class TestServer extends NanoHTTPD {
      method TestServer (line 53) | public TestServer() {
      method serve (line 57) | @Override
    method connectionsAreClosedWhenServerStops (line 63) | @Test
    method makeRequest (line 77) | private void makeRequest() throws MalformedURLException, IOException {

FILE: fileupload/src/main/java/org/nanohttpd/fileupload/NanoFileUpload.java
  class NanoFileUpload (line 54) | public class NanoFileUpload extends FileUpload {
    class NanoHttpdContext (line 56) | public static class NanoHttpdContext implements UploadContext {
      method NanoHttpdContext (line 60) | public NanoHttpdContext(IHTTPSession session) {
      method contentLength (line 64) | @Override
      method getCharacterEncoding (line 77) | @Override
      method getContentType (line 82) | @Override
      method getContentLength (line 87) | @Override
      method getInputStream (line 92) | @Override
    method isMultipartContent (line 98) | public static final boolean isMultipartContent(IHTTPSession session) {
    method NanoFileUpload (line 102) | public NanoFileUpload(FileItemFactory fileItemFactory) {
    method parseRequest (line 106) | public List<FileItem> parseRequest(IHTTPSession session) throws FileUp...
    method parseParameterMap (line 110) | public Map<String, List<FileItem>> parseParameterMap(IHTTPSession sess...
    method getItemIterator (line 114) | public FileItemIterator getItemIterator(IHTTPSession session) throws F...

FILE: fileupload/src/test/java/org/nanohttpd/junit/fileupload/TestNanoFileUpLoad.java
  class TestNanoFileUpLoad (line 83) | @FixMethodOrder
    class TestServer (line 90) | public static class TestServer extends NanoHTTPD {
      method TestServer (line 110) | public TestServer() {
      method createSession (line 115) | public HTTPSession createSession(ITempFileManager tempFileManager, I...
      method createSession (line 119) | public HTTPSession createSession(ITempFileManager tempFileManager, I...
      method serve (line 125) | @Override
    method testNormalRequest (line 173) | @Test
    method testPostWithMultipartFormUpload1 (line 182) | @Test
    method testPostWithMultipartFormUpload2 (line 193) | @Test
    method testPostWithMultipartFormUpload3 (line 204) | @Test
    method executeUpload (line 215) | private void executeUpload(CloseableHttpClient httpclient, String text...
    method setUp (line 230) | @Before
    method tearDown (line 247) | @After

FILE: markdown-plugin/src/main/java/org/nanohttpd/markdown/MarkdownWebServerPlugin.java
  class MarkdownWebServerPlugin (line 56) | public class MarkdownWebServerPlugin implements WebServerPlugin {
    method MarkdownWebServerPlugin (line 65) | public MarkdownWebServerPlugin() {
    method canServeUri (line 69) | @Override
    method initialize (line 75) | @Override
    method readSource (line 79) | private String readSource(File file) {
    method serveFile (line 112) | @Override

FILE: markdown-plugin/src/main/java/org/nanohttpd/markdown/MarkdownWebServerPluginInfo.java
  class MarkdownWebServerPluginInfo (line 42) | public class MarkdownWebServerPluginInfo implements WebServerPluginInfo {
    method getIndexFilesForMimeType (line 44) | @Override
    method getMimeTypes (line 51) | @Override
    method getWebServerPlugin (line 58) | @Override

FILE: nanolets/src/main/java/org/nanohttpd/router/RouterNanoHTTPD.java
  class RouterNanoHTTPD (line 64) | public class RouterNanoHTTPD extends NanoHTTPD {
    type UriResponder (line 71) | public interface UriResponder {
      method get (line 73) | public Response get(UriResource uriResource, Map<String, String> url...
      method put (line 75) | public Response put(UriResource uriResource, Map<String, String> url...
      method post (line 77) | public Response post(UriResource uriResource, Map<String, String> ur...
      method delete (line 79) | public Response delete(UriResource uriResource, Map<String, String> ...
      method other (line 81) | public Response other(String method, UriResource uriResource, Map<St...
    class DefaultStreamHandler (line 88) | public static abstract class DefaultStreamHandler implements UriRespon...
      method getMimeType (line 90) | public abstract String getMimeType();
      method getStatus (line 92) | public abstract IStatus getStatus();
      method getData (line 94) | public abstract InputStream getData();
      method get (line 96) | public Response get(UriResource uriResource, Map<String, String> url...
      method post (line 100) | public Response post(UriResource uriResource, Map<String, String> ur...
      method put (line 104) | public Response put(UriResource uriResource, Map<String, String> url...
      method delete (line 108) | public Response delete(UriResource uriResource, Map<String, String> ...
      method other (line 112) | public Response other(String method, UriResource uriResource, Map<St...
    class DefaultHandler (line 121) | public static abstract class DefaultHandler extends DefaultStreamHandl...
      method getText (line 123) | public abstract String getText();
      method getStatus (line 125) | public abstract IStatus getStatus();
      method get (line 127) | public Response get(UriResource uriResource, Map<String, String> url...
      method getData (line 131) | @Override
    class GeneralHandler (line 140) | public static class GeneralHandler extends DefaultHandler {
      method getText (line 142) | @Override
      method getMimeType (line 147) | @Override
      method getStatus (line 152) | @Override
      method get (line 157) | public Response get(UriResource uriResource, Map<String, String> url...
    class StaticPageHandler (line 183) | public static class StaticPageHandler extends DefaultHandler {
      method getPathArray (line 185) | private static String[] getPathArray(String uri) {
      method getText (line 198) | @Override
      method getMimeType (line 203) | @Override
      method getStatus (line 208) | @Override
      method get (line 213) | public Response get(UriResource uriResource, Map<String, String> url...
      method fileToInputStream (line 243) | protected BufferedInputStream fileToInputStream(File fileOrdirectory...
    class Error404UriHandler (line 251) | public static class Error404UriHandler extends DefaultHandler {
      method getText (line 253) | public String getText() {
      method getMimeType (line 257) | @Override
      method getStatus (line 262) | @Override
    class IndexHandler (line 271) | public static class IndexHandler extends DefaultHandler {
      method getText (line 273) | public String getText() {
      method getMimeType (line 277) | @Override
      method getStatus (line 282) | @Override
    class NotImplementedHandler (line 289) | public static class NotImplementedHandler extends DefaultHandler {
      method getText (line 291) | public String getText() {
      method getMimeType (line 295) | @Override
      method getStatus (line 300) | @Override
    method normalizeUri (line 306) | public static String normalizeUri(String value) {
    class UriResource (line 320) | public static class UriResource implements Comparable<UriResource> {
      method UriResource (line 340) | public UriResource(String uri, int priority, Class<?> handler, Objec...
      method UriResource (line 345) | public UriResource(String uri, Class<?> handler, Object... initParam...
      method parse (line 358) | private void parse() {
      method createUriPattern (line 361) | private Pattern createUriPattern() {
      method process (line 376) | public Response process(Map<String, String> urlParams, IHTTPSession ...
      method toString (line 411) | @Override
      method getUri (line 419) | public String getUri() {
      method initParameter (line 423) | public <T> T initParameter(Class<T> paramClazz) {
      method initParameter (line 427) | public <T> T initParameter(int parameterIndex, Class<T> paramClazz) {
      method match (line 435) | public Map<String, String> match(String url) {
      method compareTo (line 451) | @Override
      method setPriority (line 464) | public void setPriority(int priority) {
    type IRoutePrioritizer (line 470) | public static interface IRoutePrioritizer {
      method addRoute (line 472) | void addRoute(String url, int priority, Class<?> handler, Object... ...
      method removeRoute (line 474) | void removeRoute(String url);
      method getPrioritizedRoutes (line 476) | Collection<UriResource> getPrioritizedRoutes();
      method setNotImplemented (line 478) | void setNotImplemented(Class<?> notImplemented);
    class BaseRoutePrioritizer (line 481) | public static abstract class BaseRoutePrioritizer implements IRoutePri...
      method BaseRoutePrioritizer (line 487) | public BaseRoutePrioritizer() {
      method addRoute (line 492) | @Override
      method removeRoute (line 503) | public void removeRoute(String url) {
      method getPrioritizedRoutes (line 515) | @Override
      method setNotImplemented (line 520) | @Override
      method newMappingCollection (line 525) | protected abstract Collection<UriResource> newMappingCollection();
    class ProvidedPriorityRoutePrioritizer (line 528) | public static class ProvidedPriorityRoutePrioritizer extends BaseRoute...
      method addRoute (line 530) | @Override
      method newMappingCollection (line 545) | @Override
    class DefaultRoutePrioritizer (line 552) | public static class DefaultRoutePrioritizer extends BaseRoutePrioritiz...
      method newMappingCollection (line 554) | protected Collection<UriResource> newMappingCollection() {
    class InsertionOrderRoutePrioritizer (line 559) | public static class InsertionOrderRoutePrioritizer extends BaseRoutePr...
      method newMappingCollection (line 561) | protected Collection<UriResource> newMappingCollection() {
    class UriRouter (line 566) | public static class UriRouter {
      method UriRouter (line 572) | public UriRouter() {
      method process (line 586) | public Response process(IHTTPSession session) {
      method addRoute (line 600) | private void addRoute(String url, int priority, Class<?> handler, Ob...
      method removeRoute (line 604) | private void removeRoute(String url) {
      method setNotFoundHandler (line 608) | public void setNotFoundHandler(Class<?> handler) {
      method setNotImplemented (line 612) | public void setNotImplemented(Class<?> handler) {
      method setRoutePrioritizer (line 616) | public void setRoutePrioritizer(IRoutePrioritizer routePrioritizer) {
    method RouterNanoHTTPD (line 624) | public RouterNanoHTTPD(int port) {
    method RouterNanoHTTPD (line 629) | public RouterNanoHTTPD(String hostname, int port) {
    method addMappings (line 642) | public void addMappings() {
    method addRoute (line 649) | public void addRoute(String url, Class<?> handler, Object... initParam...
    method setNotImplementedHandler (line 653) | public <T extends UriResponder> void setNotImplementedHandler(Class<T>...
    method setNotFoundHandler (line 657) | public <T extends UriResponder> void setNotFoundHandler(Class<T> handl...
    method removeRoute (line 661) | public void removeRoute(String url) {
    method setRoutePrioritizer (line 665) | public void setRoutePrioritizer(IRoutePrioritizer routePrioritizer) {
    method serve (line 669) | @Override

FILE: nanolets/src/test/java/org/nanohttpd/junit/router/AppNanolets.java
  class AppNanolets (line 62) | public class AppNanolets extends RouterNanoHTTPD {
    class UserHandler (line 66) | public static class UserHandler extends DefaultHandler {
      method getText (line 68) | @Override
      method getText (line 73) | public String getText(Map<String, String> urlParams, IHTTPSession se...
      method getMimeType (line 92) | @Override
      method getStatus (line 97) | @Override
      method get (line 102) | public Response get(UriResource uriResource, Map<String, String> url...
    class StreamUrl (line 111) | static public class StreamUrl extends DefaultStreamHandler {
      method getMimeType (line 113) | @Override
      method getStatus (line 118) | @Override
      method getData (line 123) | @Override
    class StaticPageTestHandler (line 130) | public static class StaticPageTestHandler extends StaticPageHandler {
      method fileToInputStream (line 132) | @Override
    method AppNanolets (line 144) | public AppNanolets() throws IOException {
    method addMappings (line 155) | @Override
    method main (line 179) | public static void main(String[] args) {

FILE: nanolets/src/test/java/org/nanohttpd/junit/router/TestNanolets.java
  class TestNanolets (line 75) | public class TestNanolets {
    method setUp (line 81) | @BeforeClass
    method main (line 98) | public static void main(String[] args) {
    method doSomeBasicMethodTest (line 119) | @Test
    method doEncodedRequest (line 156) | @Test
    method doNonRouterRequest (line 164) | @Test
    method doExceptionRequest (line 176) | @Test
    method doDeletedRoute (line 188) | @Test
    method doUriSelection1 (line 200) | @Test
    method doStreamOfData (line 212) | @Test
    method illegalMethod1 (line 224) | @Test(expected = IllegalStateException.class)
    method illegalMethod2 (line 229) | @Test(expected = IllegalStateException.class)
    method illegalMethod3 (line 234) | @Test(expected = IllegalStateException.class)
    method illegalMethod4 (line 239) | @Test(expected = IllegalStateException.class)
    method checkIniParameter1 (line 244) | @Test(expected = ClassCastException.class)
    method checkIniParameter2 (line 250) | @Test
    method doGeneralParams (line 256) | @Test
    method doIndexHandler (line 269) | @Test
    method doMissingHandler (line 281) | @Test
    method uriToString (line 293) | @Test
    method doOtherMethod (line 300) | @Test
    method normalize (line 312) | @Test
    method readContents (line 320) | private byte[] readContents(HttpEntity entity) throws IOException {
    method readContents (line 325) | private byte[] readContents(InputStream instream) throws IOException {
    method staticFiles (line 342) | @Test
    method tearDown (line 389) | @AfterClass
    method testGeneralHandlerGetStatus (line 396) | @Test
    method testStaticPageHandlerGetStatus (line 401) | @Test
    method testError404UriHandlerGetStatus (line 406) | @Test
    method testError404UriHandlerGetMimeType (line 411) | @Test
    method testNotImplementedHandlerGetStatus (line 416) | @Test
    method testIndexHandlerGetStatus (line 421) | @Test
    method testIndexHandlerGetMimeType (line 426) | @Test
    method testNotImplementedHandlerGetMimeType (line 431) | @Test
    method testBaseRoutePrioritizerAddNullRoute (line 436) | @Test
    method testInsertionOrderRoutePrioritizer (line 443) | @Test
    method testProvidedPriorityRoutePrioritizerNullUri (line 476) | @Test
    method testProvidedPriorityRoutePrioritizerNullHandler (line 484) | @Test
    method testProvidedPriorityRoutePrioritizer (line 492) | @Test
    method testUriResourceComparator (line 524) | @Test
    method testUriResourceMatch (line 541) | @Test
    method testRoutePrioritizerRemoveRouteNoRouteMatches (line 548) | @Test
    method testHandlerSetters (line 557) | @Test
    class TestRouter (line 579) | private static final class TestRouter extends UriRouter {
      method setNotFoundHandler (line 585) | @Override
      method setNotImplemented (line 590) | @Override

FILE: samples/src/main/java/org/nanohttpd/samples/http/DebugServer.java
  class DebugServer (line 45) | public class DebugServer extends NanoHTTPD {
    method main (line 47) | public static void main(String[] args) {
    method DebugServer (line 51) | public DebugServer() {
    method listItem (line 55) | private void listItem(StringBuilder sb, Map.Entry<String, ? extends Ob...
    method serve (line 59) | @Override
    method toString (line 92) | private String toString(Map<String, ? extends Object> map) {
    method unsortedList (line 99) | private String unsortedList(Map<String, ? extends Object> map) {

FILE: samples/src/main/java/org/nanohttpd/samples/http/HelloServer.java
  class HelloServer (line 48) | public class HelloServer extends NanoHTTPD {
    method main (line 55) | public static void main(String[] args) {
    method HelloServer (line 59) | public HelloServer() {
    method serve (line 63) | @Override

FILE: samples/src/main/java/org/nanohttpd/samples/tempfiles/TempFilesServer.java
  class TempFilesServer (line 50) | public class TempFilesServer extends DebugServer {
    class ExampleManager (line 52) | private static class ExampleManager implements ITempFileManager {
      method ExampleManager (line 58) | private ExampleManager() {
      method clear (line 63) | @Override
      method createTempFile (line 78) | @Override
    class ExampleManagerFactory (line 87) | private static class ExampleManagerFactory implements IFactory<ITempFi...
      method create (line 89) | @Override
    method main (line 95) | public static void main(String[] args) {

FILE: webserver/src/main/java/org/nanohttpd/webserver/InternalRewrite.java
  class InternalRewrite (line 46) | public class InternalRewrite extends Response {
    method InternalRewrite (line 52) | public InternalRewrite(Map<String, String> headers, String uri) {
    method getHeaders (line 58) | public Map<String, String> getHeaders() {
    method getUri (line 62) | public String getUri() {

FILE: webserver/src/main/java/org/nanohttpd/webserver/SimpleWebServer.java
  class SimpleWebServer (line 62) | public class SimpleWebServer extends NanoHTTPD {
    method main (line 103) | public static void main(String[] args) {
    method registerPluginForMimeType (line 179) | protected static void registerPluginForMimeType(String[] indexFiles, S...
    method SimpleWebServer (line 204) | public SimpleWebServer(String host, int port, File wwwroot, boolean qu...
    method SimpleWebServer (line 208) | public SimpleWebServer(String host, int port, File wwwroot, boolean qu...
    method SimpleWebServer (line 212) | public SimpleWebServer(String host, int port, List<File> wwwroots, boo...
    method SimpleWebServer (line 216) | public SimpleWebServer(String host, int port, List<File> wwwroots, boo...
    method canServeUri (line 225) | private boolean canServeUri(String uri, File homeDir) {
    method encodeUri (line 242) | private String encodeUri(String uri) {
    method findIndexFileInDirectory (line 261) | private String findIndexFileInDirectory(File directory) {
    method getForbiddenResponse (line 271) | protected Response getForbiddenResponse(String s) {
    method getInternalErrorResponse (line 275) | protected Response getInternalErrorResponse(String s) {
    method getNotFoundResponse (line 279) | protected Response getNotFoundResponse() {
    method init (line 286) | public void init() {
    method listDirectory (line 289) | protected String listDirectory(String uri, File f) {
    method newFixedLengthResponse (line 357) | public static Response newFixedLengthResponse(IStatus status, String m...
    method respond (line 363) | private Response respond(Map<String, String> headers, IHTTPSession ses...
    method defaultRespond (line 378) | private Response defaultRespond(Map<String, String> headers, IHTTPSess...
    method serve (line 440) | @Override
    method serveFile (line 474) | Response serveFile(String uri, Map<String, String> header, File file, ...
    method newFixedFileResponse (line 573) | private Response newFixedFileResponse(File file, String mime) throws F...
    method addCORSHeaders (line 580) | protected Response addCORSHeaders(Map<String, String> queryHeaders, Re...
    method calculateAllowHeaders (line 590) | private String calculateAllowHeaders(Map<String, String> queryHeaders) {

FILE: webserver/src/main/java/org/nanohttpd/webserver/WebServerPlugin.java
  type WebServerPlugin (line 45) | public interface WebServerPlugin {
    method canServeUri (line 47) | boolean canServeUri(String uri, File rootDir);
    method initialize (line 49) | void initialize(Map<String, String> commandLineOptions);
    method serveFile (line 51) | Response serveFile(String uri, Map<String, String> headers, IHTTPSessi...

FILE: webserver/src/main/java/org/nanohttpd/webserver/WebServerPluginInfo.java
  type WebServerPluginInfo (line 39) | public interface WebServerPluginInfo {
    method getIndexFilesForMimeType (line 41) | String[] getIndexFilesForMimeType(String mime);
    method getMimeTypes (line 43) | String[] getMimeTypes();
    method getWebServerPlugin (line 45) | WebServerPlugin getWebServerPlugin(String mimeType);

FILE: webserver/src/test/java/org/nanohttpd/junit/webserver/AbstractTestHttpServer.java
  class AbstractTestHttpServer (line 45) | public class AbstractTestHttpServer {
    method readContents (line 47) | protected byte[] readContents(HttpEntity entity) throws IOException {
    method readContents (line 52) | protected byte[] readContents(InputStream instream) throws IOException {

FILE: webserver/src/test/java/org/nanohttpd/junit/webserver/DummyPlugin.java
  class DummyPlugin (line 47) | public class DummyPlugin implements WebServerPlugin {
    method canServeUri (line 49) | @Override
    method initialize (line 54) | @Override
    method serveFile (line 58) | @Override

FILE: webserver/src/test/java/org/nanohttpd/junit/webserver/DummyPluginInfo.java
  class DummyPluginInfo (line 39) | public class DummyPluginInfo implements WebServerPluginInfo {
    method getIndexFilesForMimeType (line 41) | @Override
    method getMimeTypes (line 49) | @Override
    method getWebServerPlugin (line 56) | @Override

FILE: webserver/src/test/java/org/nanohttpd/junit/webserver/TestCorsHttpServer.java
  class TestCorsHttpServer (line 54) | public class TestCorsHttpServer extends AbstractTestHttpServer {
    method setUp (line 60) | @BeforeClass
    method tearDown (line 85) | @AfterClass
    method doTestOption (line 92) | @Test
    method doSomeBasicTest (line 103) | @Test
    method testAccessControlAllowHeaderUsesDefaultsWithoutSystemProperty (line 117) | @Test
    method testAccessControlAllowHeaderUsesSystemPropertyWhenSet (line 131) | @Test

FILE: webserver/src/test/java/org/nanohttpd/junit/webserver/TestCorsHttpServerWithSingleOrigin.java
  class TestCorsHttpServerWithSingleOrigin (line 54) | public class TestCorsHttpServerWithSingleOrigin extends AbstractTestHttp...
    method setUp (line 60) | @BeforeClass
    method tearDown (line 85) | @AfterClass
    method doTestOption (line 92) | @Test
    method doSomeBasicTest (line 104) | @Test

FILE: webserver/src/test/java/org/nanohttpd/junit/webserver/TestHttpServer.java
  class TestHttpServer (line 57) | public class TestHttpServer extends AbstractTestHttpServer {
    method setUp (line 63) | @BeforeClass
    method tearDown (line 87) | @AfterClass
    method doTest404 (line 94) | @Test
    method doPlugin (line 103) | @Test
    method doSomeBasicTest (line 119) | @Test
    method doArgumentTest (line 154) | @Test
    method testURLContainsParentDirectory (line 191) | @Test
    method testIndexFileIsShownWhenURLEndsWithDirectory (line 207) | @Test
    method testPluginInternalRewrite (line 225) | @Test
    method testRangeHeaderWithStartPositionOnly (line 243) | @Test
    method testRangeStartGreaterThanFileLength (line 268) | @Test
    method testRangeHeaderWithStartAndEndPosition (line 287) | @Test
    method testIfNoneMatchHeader (line 312) | @Test
    method testRangeHeaderAndIfNoneMatchHeader (line 329) | @Test

FILE: websocket/src/main/java/org/nanohttpd/protocols/websockets/CloseCode.java
  type CloseCode (line 36) | public enum CloseCode {
    method find (line 50) | public static CloseCode find(int value) {
    method CloseCode (line 61) | private CloseCode(int code) {
    method getValue (line 65) | public int getValue() {

FILE: websocket/src/main/java/org/nanohttpd/protocols/websockets/CloseFrame.java
  class CloseFrame (line 38) | public class CloseFrame extends WebSocketFrame {
    method generatePayload (line 40) | private static byte[] generatePayload(CloseCode code, String closeReas...
    method CloseFrame (line 57) | public CloseFrame(CloseCode code, String closeReason) throws Character...
    method CloseFrame (line 61) | public CloseFrame(WebSocketFrame wrap) throws CharacterCodingException {
    method getCloseCode (line 70) | public CloseCode getCloseCode() {
    method getCloseReason (line 74) | public String getCloseReason() {

FILE: websocket/src/main/java/org/nanohttpd/protocols/websockets/NanoWSD.java
  class NanoWSD (line 47) | public abstract class NanoWSD extends NanoHTTPD {
    method encodeBase64 (line 88) | private static String encodeBase64(byte[] buf) {
    method makeAcceptKey (line 113) | public static String makeAcceptKey(String key) throws NoSuchAlgorithmE...
    class Interceptor (line 121) | protected final class Interceptor implements IHandler<IHTTPSession, Re...
      method Interceptor (line 123) | public Interceptor() {
      method handle (line 126) | @Override
    method NanoWSD (line 132) | public NanoWSD(int port) {
    method NanoWSD (line 137) | public NanoWSD(String hostname, int port) {
    method isWebSocketConnectionHeader (line 142) | private boolean isWebSocketConnectionHeader(Map<String, String> header...
    method isWebsocketRequested (line 147) | protected boolean isWebsocketRequested(IHTTPSession session) {
    method openWebSocket (line 157) | protected abstract WebSocket openWebSocket(IHTTPSession handshake);
    method handleWebSocket (line 159) | public Response handleWebSocket(final IHTTPSession session) {

FILE: websocket/src/main/java/org/nanohttpd/protocols/websockets/OpCode.java
  type OpCode (line 36) | public enum OpCode {
    method find (line 44) | public static OpCode find(byte value) {
    method OpCode (line 55) | private OpCode(int code) {
    method getValue (line 59) | public byte getValue() {
    method isControlFrame (line 63) | public boolean isControlFrame() {

FILE: websocket/src/main/java/org/nanohttpd/protocols/websockets/State.java
  type State (line 36) | public enum State {

FILE: websocket/src/main/java/org/nanohttpd/protocols/websockets/WebSocket.java
  class WebSocket (line 48) | public abstract class WebSocket {
    method send (line 66) | @Override
    method WebSocket (line 77) | public WebSocket(IHTTPSession handshakeRequest) {
    method isOpen (line 86) | public boolean isOpen() {
    method onOpen (line 90) | protected abstract void onOpen();
    method onClose (line 92) | protected abstract void onClose(CloseCode code, String reason, boolean...
    method onMessage (line 94) | protected abstract void onMessage(WebSocketFrame message);
    method onPong (line 96) | protected abstract void onPong(WebSocketFrame pong);
    method onException (line 98) | protected abstract void onException(IOException exception);
    method debugFrameReceived (line 106) | protected void debugFrameReceived(WebSocketFrame frame) {
    method debugFrameSent (line 116) | protected void debugFrameSent(WebSocketFrame frame) {
    method close (line 119) | public void close(CloseCode code, String reason, boolean initiatedByRe...
    method doClose (line 129) | private void doClose(CloseCode code, String reason, boolean initiatedB...
    method getHandshakeRequest (line 153) | public IHTTPSession getHandshakeRequest() {
    method getHandshakeResponse (line 157) | public Response getHandshakeResponse() {
    method handleCloseFrame (line 161) | private void handleCloseFrame(WebSocketFrame frame) throws IOException {
    method handleFrameFragment (line 176) | private void handleFrameFragment(WebSocketFrame frame) throws IOExcept...
    method handleWebsocketFrame (line 203) | private void handleWebsocketFrame(WebSocketFrame frame) throws IOExcep...
    method ping (line 224) | public void ping(byte[] payload) throws IOException {
    method readWebsocket (line 231) | private void readWebsocket() {
    method send (line 249) | public void send(byte[] payload) throws IOException {
    method send (line 253) | public void send(String payload) throws IOException {
    method sendFrame (line 257) | public synchronized void sendFrame(WebSocketFrame frame) throws IOExce...

FILE: websocket/src/main/java/org/nanohttpd/protocols/websockets/WebSocketException.java
  class WebSocketException (line 38) | public class WebSocketException extends IOException {
    method WebSocketException (line 46) | public WebSocketException(CloseCode code, String reason) {
    method WebSocketException (line 50) | public WebSocketException(CloseCode code, String reason, Exception cau...
    method WebSocketException (line 56) | public WebSocketException(Exception cause) {
    method getCode (line 60) | public CloseCode getCode() {
    method getReason (line 64) | public String getReason() {

FILE: websocket/src/main/java/org/nanohttpd/protocols/websockets/WebSocketFrame.java
  class WebSocketFrame (line 45) | public class WebSocketFrame {
    method binary2Text (line 49) | public static String binary2Text(byte[] payload) throws CharacterCodin...
    method binary2Text (line 53) | public static String binary2Text(byte[] payload, int offset, int lengt...
    method checkedRead (line 57) | private static int checkedRead(int read) throws IOException {
    method read (line 64) | public static WebSocketFrame read(InputStream in) throws IOException {
    method text2Binary (line 87) | public static byte[] text2Binary(String payload) throws CharacterCodin...
    method WebSocketFrame (line 105) | private WebSocketFrame(OpCode opCode, boolean fin) {
    method WebSocketFrame (line 110) | public WebSocketFrame(OpCode opCode, boolean fin, byte[] payload) {
    method WebSocketFrame (line 114) | public WebSocketFrame(OpCode opCode, boolean fin, byte[] payload, byte...
    method WebSocketFrame (line 120) | public WebSocketFrame(OpCode opCode, boolean fin, String payload) thro...
    method WebSocketFrame (line 124) | public WebSocketFrame(OpCode opCode, boolean fin, String payload, byte...
    method WebSocketFrame (line 130) | public WebSocketFrame(OpCode opCode, List<WebSocketFrame> fragments) t...
    method WebSocketFrame (line 151) | public WebSocketFrame(WebSocketFrame clone) {
    method getBinaryPayload (line 158) | public byte[] getBinaryPayload() {
    method getMaskingKey (line 162) | public byte[] getMaskingKey() {
    method getOpCode (line 166) | public OpCode getOpCode() {
    method getTextPayload (line 172) | public String getTextPayload() {
    method isFin (line 183) | public boolean isFin() {
    method isMasked (line 187) | public boolean isMasked() {
    method payloadToString (line 191) | private String payloadToString() {
    method readPayload (line 217) | private void readPayload(InputStream in) throws IOException {
    method readPayloadInfo (line 238) | private void readPayloadInfo(InputStream in) throws IOException {
    method setBinaryPayload (line 280) | public void setBinaryPayload(byte[] payload) {
    method setFin (line 286) | public void setFin(boolean fin) {
    method setMaskingKey (line 290) | public void setMaskingKey(byte[] maskingKey) {
    method setOpCode (line 297) | public void setOpCode(OpCode opcode) {
    method setTextPayload (line 301) | public void setTextPayload(String payload) throws CharacterCodingExcep...
    method setUnmasked (line 309) | public void setUnmasked() {
    method toString (line 313) | @Override
    method write (line 326) | public void write(OutputStream out) throws IOException {

FILE: websocket/src/main/java/org/nanohttpd/samples/websockets/DebugWebSocketServer.java
  class DebugWebSocketServer (line 49) | public class DebugWebSocketServer extends NanoWSD {
    method DebugWebSocketServer (line 58) | public DebugWebSocketServer(int port, boolean debug) {
    method openWebSocket (line 63) | @Override
    class DebugWebSocket (line 68) | private static class DebugWebSocket extends WebSocket {
      method DebugWebSocket (line 72) | public DebugWebSocket(DebugWebSocketServer server, IHTTPSession hand...
      method onOpen (line 77) | @Override
      method onClose (line 81) | @Override
      method onMessage (line 89) | @Override
      method onPong (line 99) | @Override
      method onException (line 106) | @Override
      method debugFrameReceived (line 111) | @Override
      method debugFrameSent (line 118) | @Override

FILE: websocket/src/main/java/org/nanohttpd/samples/websockets/EchoSocketSample.java
  class EchoSocketSample (line 40) | public class EchoSocketSample {
    method main (line 42) | public static void main(String[] args) throws IOException {

FILE: websocket/src/test/java/org/nanohttpd/junit/protocols/websockets/EchoWebSocketsTest.java
  class EchoWebSocketsTest (line 55) | public class EchoWebSocketsTest {
    method setUp (line 59) | @BeforeClass
    method tearDown (line 65) | @AfterClass
    method testDirectoryArgument (line 70) | @Test
    method testWebsocketClient (line 100) | @Test
    method createString (line 132) | private String createString(int i) {

FILE: websocket/src/test/java/org/nanohttpd/junit/protocols/websockets/SimpleEchoSocket.java
  class SimpleEchoSocket (line 52) | @WebSocket(maxTextMessageSize = 64 * 1024)
    method SimpleEchoSocket (line 61) | public SimpleEchoSocket() {
    method awaitClose (line 65) | public boolean awaitClose(int duration, TimeUnit unit) throws Interrup...
    method getReceivedMessages (line 69) | public List<String> getReceivedMessages() {
    method getToSendMessages (line 73) | public List<String> getToSendMessages() {
    method onClose (line 77) | @OnWebSocketClose
    method onConnect (line 83) | @OnWebSocketConnect
    method onMessage (line 99) | @OnWebSocketMessage

FILE: websocket/src/test/java/org/nanohttpd/junit/protocols/websockets/WebSocketResponseHandlerTest.java
  class WebSocketResponseHandlerTest (line 65) | @RunWith(MockitoJUnitRunner.class)
    class MockedWSD (line 75) | private static class MockedWSD extends NanoWSD {
      method MockedWSD (line 77) | public MockedWSD(int port) {
      method MockedWSD (line 81) | public MockedWSD(String hostname, int port) {
      method initialize (line 86) | public void initialize() {
      method openWebSocket (line 99) | @Override
    method setUp (line 126) | @Before
    method testConnectionHeaderHandlesKeepAlive_FixingFirefoxConnectIssue (line 147) | @Test
    method testHandshakeReturnsResponseWithExpectedHeaders (line 155) | @Test
    method testMissingKeyReturnsErrorResponse (line 165) | @Test
    method testWrongConnectionHeaderReturnsNullResponse (line 175) | @Test
    method testWrongUpgradeHeaderReturnsNullResponse (line 182) | @Test
    method testWrongWebsocketVersionReturnsErrorResponse (line 189) | @Test
    method testSetMaskingKeyThrowsExceptionMaskingKeyLengthIsNotFour (line 199) | @Test
    method testIsMasked (line 214) | @Test
    method testWriteWhenNotMasked (line 224) | @Test
    method testWriteWhenMasked (line 246) | @Test
    method testWriteWhenNotMaskedPayloadLengthGreaterThan125 (line 278) | @Test
    method testWriteWhenMaskedPayloadLengthGreaterThan125 (line 297) | @Test
    method testWriteWhenNotMaskedPayloadLengthGreaterThan65535 (line 322) | @Test
Condensed preview — 155 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (660K chars).
[
  {
    "path": ".gitignore",
    "chars": 173,
    "preview": "out\nbuild\ntarget\n\n*.iml\n*.ipr\n*.iws\n*.class\n\n.idea\n.classpath\n.project\n.gradle\ngradle/\ngradlew\ngradlew.bat\n\n# Vim Backup"
  },
  {
    "path": ".travis.yml",
    "chars": 962,
    "preview": "language: java\njdk:\n- openjdk7\n\nbefore_install:\n  - cat ~/.m2/settings.xml\n  - rm  ~/.m2/settings.xml\n\ninstall:\n  - mvn "
  },
  {
    "path": "LICENSE.md",
    "chars": 1555,
    "preview": "Copyright (c) 2012-2013 by Paul S. Hawke, 2001,2005-2013 by Jarno Elonen, 2010 by Konstantinos Togias\nAll rights reserve"
  },
  {
    "path": "README.md",
    "chars": 11550,
    "preview": "## NanoHTTPD – a tiny web server in Java\n\n*NanoHTTPD* is a light-weight HTTP server designed for embedding in other appl"
  },
  {
    "path": "build.gradle",
    "chars": 381,
    "preview": "allprojects {\n\tapply plugin: 'java'\n\tapply plugin: 'idea'\n\t\n\tgroup = 'org.nanohttpd'\n\tversion = '2.3.2-SNAPSHOT'\n}\n\nsubp"
  },
  {
    "path": "core/.gitignore",
    "chars": 25,
    "preview": "/.settings/\n/LICENSE.txt\n"
  },
  {
    "path": "core/build.gradle",
    "chars": 277,
    "preview": "description = 'NanoHttpd-Core'\n\ndependencies {\n\ttestCompile group: 'org.apache.httpcomponents', name: 'httpclient', vers"
  },
  {
    "path": "core/pom.xml",
    "chars": 924,
    "preview": "<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocat"
  },
  {
    "path": "core/src/main/java/org/nanohttpd/protocols/http/ClientHandler.java",
    "chars": 3841,
    "preview": "package org.nanohttpd.protocols.http;\n\n/*\n * #%L\n * NanoHttpd-Core\n * %%\n * Copyright (C) 2012 - 2016 nanohttpd\n * %%\n *"
  },
  {
    "path": "core/src/main/java/org/nanohttpd/protocols/http/HTTPSession.java",
    "chars": 27952,
    "preview": "package org.nanohttpd.protocols.http;\n\n/*\n * #%L\n * NanoHttpd-Core\n * %%\n * Copyright (C) 2012 - 2016 nanohttpd\n * %%\n *"
  },
  {
    "path": "core/src/main/java/org/nanohttpd/protocols/http/IHTTPSession.java",
    "chars": 3043,
    "preview": "package org.nanohttpd.protocols.http;\n\n/*\n * #%L\n * NanoHttpd-Core\n * %%\n * Copyright (C) 2012 - 2016 nanohttpd\n * %%\n *"
  },
  {
    "path": "core/src/main/java/org/nanohttpd/protocols/http/NanoHTTPD.java",
    "chars": 23296,
    "preview": "package org.nanohttpd.protocols.http;\n\n/*\n * #%L\n * NanoHttpd-Core\n * %%\n * Copyright (C) 2012 - 2016 nanohttpd\n * %%\n *"
  },
  {
    "path": "core/src/main/java/org/nanohttpd/protocols/http/ServerRunnable.java",
    "chars": 3272,
    "preview": "package org.nanohttpd.protocols.http;\n\n/*\n * #%L\n * NanoHttpd-Core\n * %%\n * Copyright (C) 2012 - 2016 nanohttpd\n * %%\n *"
  },
  {
    "path": "core/src/main/java/org/nanohttpd/protocols/http/content/ContentType.java",
    "chars": 4221,
    "preview": "package org.nanohttpd.protocols.http.content;\n\n/*\n * #%L\n * NanoHttpd-Core\n * %%\n * Copyright (C) 2012 - 2016 nanohttpd\n"
  },
  {
    "path": "core/src/main/java/org/nanohttpd/protocols/http/content/Cookie.java",
    "chars": 2834,
    "preview": "package org.nanohttpd.protocols.http.content;\n\n/*\n * #%L\n * NanoHttpd-Core\n * %%\n * Copyright (C) 2012 - 2016 nanohttpd\n"
  },
  {
    "path": "core/src/main/java/org/nanohttpd/protocols/http/content/CookieHandler.java",
    "chars": 4231,
    "preview": "package org.nanohttpd.protocols.http.content;\n\n/*\n * #%L\n * NanoHttpd-Core\n * %%\n * Copyright (C) 2012 - 2016 nanohttpd\n"
  },
  {
    "path": "core/src/main/java/org/nanohttpd/protocols/http/request/Method.java",
    "chars": 2256,
    "preview": "package org.nanohttpd.protocols.http.request;\n\n/*\n * #%L\n * NanoHttpd-Core\n * %%\n * Copyright (C) 2012 - 2016 nanohttpd\n"
  },
  {
    "path": "core/src/main/java/org/nanohttpd/protocols/http/response/ChunkedOutputStream.java",
    "chars": 2695,
    "preview": "package org.nanohttpd.protocols.http.response;\n\n/*\n * #%L\n * NanoHttpd-Core\n * %%\n * Copyright (C) 2012 - 2016 nanohttpd"
  },
  {
    "path": "core/src/main/java/org/nanohttpd/protocols/http/response/IStatus.java",
    "chars": 1735,
    "preview": "package org.nanohttpd.protocols.http.response;\n\n/*\n * #%L\n * NanoHttpd-Core\n * %%\n * Copyright (C) 2012 - 2016 nanohttpd"
  },
  {
    "path": "core/src/main/java/org/nanohttpd/protocols/http/response/Response.java",
    "chars": 15278,
    "preview": "package org.nanohttpd.protocols.http.response;\n\n/*\n * #%L\n * NanoHttpd-Core\n * %%\n * Copyright (C) 2012 - 2016 nanohttpd"
  },
  {
    "path": "core/src/main/java/org/nanohttpd/protocols/http/response/Status.java",
    "chars": 4099,
    "preview": "package org.nanohttpd.protocols.http.response;\n\n/*\n * #%L\n * NanoHttpd-Core\n * %%\n * Copyright (C) 2012 - 2016 nanohttpd"
  },
  {
    "path": "core/src/main/java/org/nanohttpd/protocols/http/sockets/DefaultServerSocketFactory.java",
    "chars": 2021,
    "preview": "package org.nanohttpd.protocols.http.sockets;\n\n/*\n * #%L\n * NanoHttpd-Core\n * %%\n * Copyright (C) 2012 - 2016 nanohttpd\n"
  },
  {
    "path": "core/src/main/java/org/nanohttpd/protocols/http/sockets/SecureServerSocketFactory.java",
    "chars": 2797,
    "preview": "package org.nanohttpd.protocols.http.sockets;\n\n/*\n * #%L\n * NanoHttpd-Core\n * %%\n * Copyright (C) 2012 - 2016 nanohttpd\n"
  },
  {
    "path": "core/src/main/java/org/nanohttpd/protocols/http/tempfiles/DefaultTempFile.java",
    "chars": 2773,
    "preview": "package org.nanohttpd.protocols.http.tempfiles;\n\n/*\n * #%L\n * NanoHttpd-Core\n * %%\n * Copyright (C) 2012 - 2016 nanohttp"
  },
  {
    "path": "core/src/main/java/org/nanohttpd/protocols/http/tempfiles/DefaultTempFileManager.java",
    "chars": 3119,
    "preview": "package org.nanohttpd.protocols.http.tempfiles;\n\n/*\n * #%L\n * NanoHttpd-Core\n * %%\n * Copyright (C) 2012 - 2016 nanohttp"
  },
  {
    "path": "core/src/main/java/org/nanohttpd/protocols/http/tempfiles/DefaultTempFileManagerFactory.java",
    "chars": 1949,
    "preview": "package org.nanohttpd.protocols.http.tempfiles;\n\n/*\n * #%L\n * NanoHttpd-Core\n * %%\n * Copyright (C) 2012 - 2016 nanohttp"
  },
  {
    "path": "core/src/main/java/org/nanohttpd/protocols/http/tempfiles/ITempFile.java",
    "chars": 2005,
    "preview": "package org.nanohttpd.protocols.http.tempfiles;\n\n/*\n * #%L\n * NanoHttpd-Core\n * %%\n * Copyright (C) 2012 - 2016 nanohttp"
  },
  {
    "path": "core/src/main/java/org/nanohttpd/protocols/http/tempfiles/ITempFileManager.java",
    "chars": 1986,
    "preview": "package org.nanohttpd.protocols.http.tempfiles;\n\n/*\n * #%L\n * NanoHttpd-Core\n * %%\n * Copyright (C) 2012 - 2016 nanohttp"
  },
  {
    "path": "core/src/main/java/org/nanohttpd/protocols/http/threading/DefaultAsyncRunner.java",
    "chars": 3200,
    "preview": "package org.nanohttpd.protocols.http.threading;\n\n/*\n * #%L\n * NanoHttpd-Core\n * %%\n * Copyright (C) 2012 - 2016 nanohttp"
  },
  {
    "path": "core/src/main/java/org/nanohttpd/protocols/http/threading/IAsyncRunner.java",
    "chars": 1908,
    "preview": "package org.nanohttpd.protocols.http.threading;\n\n/*\n * #%L\n * NanoHttpd-Core\n * %%\n * Copyright (C) 2012 - 2016 nanohttp"
  },
  {
    "path": "core/src/main/java/org/nanohttpd/util/IFactory.java",
    "chars": 1799,
    "preview": "package org.nanohttpd.util;\n\n/*\n * #%L\n * NanoHttpd-Core\n * %%\n * Copyright (C) 2012 - 2016 nanohttpd\n * %%\n * Redistrib"
  },
  {
    "path": "core/src/main/java/org/nanohttpd/util/IFactoryThrowing.java",
    "chars": 1975,
    "preview": "package org.nanohttpd.util;\n\n/*\n * #%L\n * NanoHttpd-Core\n * %%\n * Copyright (C) 2012 - 2016 nanohttpd\n * %%\n * Redistrib"
  },
  {
    "path": "core/src/main/java/org/nanohttpd/util/IHandler.java",
    "chars": 1914,
    "preview": "package org.nanohttpd.util;\n\n/*\n * #%L\n * NanoHttpd-Core\n * %%\n * Copyright (C) 2012 - 2016 nanohttpd\n * %%\n * Redistrib"
  },
  {
    "path": "core/src/main/java/org/nanohttpd/util/ServerRunner.java",
    "chars": 2723,
    "preview": "package org.nanohttpd.util;\n\n/*\n * #%L\n * NanoHttpd-Webserver\n * %%\n * Copyright (C) 2012 - 2015 nanohttpd\n * %%\n * Redi"
  },
  {
    "path": "core/src/main/resources/META-INF/nanohttpd/default-mimetypes.properties",
    "chars": 667,
    "preview": "#default mime types for nanohttpd, use META-INF/mimetypes.properties for user defined mimetypes\ncss=text/css\nhtm=text/ht"
  },
  {
    "path": "core/src/main/resources/META-INF/nanohttpd/mimetypes.properties",
    "chars": 74,
    "preview": "#mime types for nanohttpd, use a file like this for user defined mimetypes"
  },
  {
    "path": "core/src/site/site.xml",
    "chars": 1126,
    "preview": "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n<project name=\"${project.name}\">\n\t<skin>\n\t\t<groupId>org.apache.maven.skins</"
  },
  {
    "path": "core/src/test/java/org/nanohttpd/junit/protocols/http/BadRequestTest.java",
    "chars": 2648,
    "preview": "package org.nanohttpd.junit.protocols.http;\n\n/*\n * #%L\n * NanoHttpd-Core\n * %%\n * Copyright (C) 2012 - 2016 nanohttpd\n *"
  },
  {
    "path": "core/src/test/java/org/nanohttpd/junit/protocols/http/CookieHandlerTest.java",
    "chars": 7264,
    "preview": "package org.nanohttpd.junit.protocols.http;\n\n/*\n * #%L\n * NanoHttpd-Core\n * %%\n * Copyright (C) 2012 - 2016 nanohttpd\n *"
  },
  {
    "path": "core/src/test/java/org/nanohttpd/junit/protocols/http/CookieTest.java",
    "chars": 3831,
    "preview": "package org.nanohttpd.junit.protocols.http;\n\n/*\n * #%L\n * NanoHttpd-Core\n * %%\n * Copyright (C) 2012 - 2016 nanohttpd\n *"
  },
  {
    "path": "core/src/test/java/org/nanohttpd/junit/protocols/http/HttpChunkedResponseTest.java",
    "chars": 3554,
    "preview": "package org.nanohttpd.junit.protocols.http;\n\n/*\n * #%L\n * NanoHttpd-Core\n * %%\n * Copyright (C) 2012 - 2016 nanohttpd\n *"
  },
  {
    "path": "core/src/test/java/org/nanohttpd/junit/protocols/http/HttpDeleteRequestTest.java",
    "chars": 5068,
    "preview": "package org.nanohttpd.junit.protocols.http;\n\n/*\n * #%L\n * NanoHttpd-Core\n * %%\n * Copyright (C) 2012 - 2015 nanohttpd\n *"
  },
  {
    "path": "core/src/test/java/org/nanohttpd/junit/protocols/http/HttpGetRequestTest.java",
    "chars": 12422,
    "preview": "package org.nanohttpd.junit.protocols.http;\n\n/*\n * #%L\n * NanoHttpd-Core\n * %%\n * Copyright (C) 2012 - 2015 nanohttpd\n *"
  },
  {
    "path": "core/src/test/java/org/nanohttpd/junit/protocols/http/HttpHeadRequestTest.java",
    "chars": 10083,
    "preview": "package org.nanohttpd.junit.protocols.http;\n\n/*\n * #%L\n * NanoHttpd-Core\n * %%\n * Copyright (C) 2012 - 2015 nanohttpd\n *"
  },
  {
    "path": "core/src/test/java/org/nanohttpd/junit/protocols/http/HttpKeepAliveTest.java",
    "chars": 5695,
    "preview": "package org.nanohttpd.junit.protocols.http;\n\n/*\n * #%L\n * NanoHttpd-Core\n * %%\n * Copyright (C) 2012 - 2015 nanohttpd\n *"
  },
  {
    "path": "core/src/test/java/org/nanohttpd/junit/protocols/http/HttpParsingTest.java",
    "chars": 2518,
    "preview": "package org.nanohttpd.junit.protocols.http;\n\n/*\n * #%L\n * NanoHttpd-Core\n * %%\n * Copyright (C) 2012 - 2015 nanohttpd\n *"
  },
  {
    "path": "core/src/test/java/org/nanohttpd/junit/protocols/http/HttpPostRequestTest.java",
    "chars": 15885,
    "preview": "package org.nanohttpd.junit.protocols.http;\n\n/*\n * #%L\n * NanoHttpd-Core\n * %%\n * Copyright (C) 2012 - 2015 nanohttpd\n *"
  },
  {
    "path": "core/src/test/java/org/nanohttpd/junit/protocols/http/HttpPutRequestTest.java",
    "chars": 2975,
    "preview": "package org.nanohttpd.junit.protocols.http;\n\n/*\n * #%L\n * NanoHttpd-Core\n * %%\n * Copyright (C) 2012 - 2015 nanohttpd\n *"
  },
  {
    "path": "core/src/test/java/org/nanohttpd/junit/protocols/http/HttpSSLServerTest.java",
    "chars": 4055,
    "preview": "package org.nanohttpd.junit.protocols.http;\n\n/*\n * #%L\n * NanoHttpd-Core\n * %%\n * Copyright (C) 2012 - 2015 nanohttpd\n *"
  },
  {
    "path": "core/src/test/java/org/nanohttpd/junit/protocols/http/HttpServerTest.java",
    "chars": 12084,
    "preview": "package org.nanohttpd.junit.protocols.http;\n\nimport static org.junit.Assert.assertEquals;\n\n/*\n * #%L\n * NanoHttpd-Core\n "
  },
  {
    "path": "core/src/test/java/org/nanohttpd/junit/protocols/http/HttpSessionHeadersTest.java",
    "chars": 2872,
    "preview": "package org.nanohttpd.junit.protocols.http;\n\n/*\n * #%L\n * NanoHttpd-Core\n * %%\n * Copyright (C) 2012 - 2015 nanohttpd\n *"
  },
  {
    "path": "core/src/test/java/org/nanohttpd/junit/protocols/http/HttpSessionTest.java",
    "chars": 2703,
    "preview": "package org.nanohttpd.junit.protocols.http;\n\n/*\n * #%L\n * NanoHttpd-Core\n * %%\n * Copyright (C) 2012 - 2015 nanohttpd\n *"
  },
  {
    "path": "core/src/test/java/org/nanohttpd/junit/protocols/http/InvalidRequestTest.java",
    "chars": 3406,
    "preview": "package org.nanohttpd.junit.protocols.http;\n\n/*\n * #%L\n * NanoHttpd-Core\n * %%\n * Copyright (C) 2012 - 2015 nanohttpd\n *"
  },
  {
    "path": "core/src/test/java/org/nanohttpd/junit/protocols/http/JavaIOTempDirExistTest.java",
    "chars": 3318,
    "preview": "package org.nanohttpd.junit.protocols.http;\n\n/*\n * #%L\n * NanoHttpd-Core\n * %%\n * Copyright (C) 2012 - 2015 nanohttpd\n *"
  },
  {
    "path": "core/src/test/java/org/nanohttpd/junit/protocols/http/LoadKeyStoreTest.java",
    "chars": 3312,
    "preview": "package org.nanohttpd.junit.protocols.http;\n\nimport static org.junit.Assert.assertNotNull;\nimport static org.junit.Asser"
  },
  {
    "path": "core/src/test/java/org/nanohttpd/junit/protocols/http/MimeTest.java",
    "chars": 2587,
    "preview": "package org.nanohttpd.junit.protocols.http;\n\n/*\n * #%L\n * NanoHttpd-Core\n * %%\n * Copyright (C) 2012 - 2015 nanohttpd\n *"
  },
  {
    "path": "core/src/test/java/org/nanohttpd/junit/protocols/http/SSLServerSocketFactoryTest.java",
    "chars": 4824,
    "preview": "package org.nanohttpd.junit.protocols.http;\n\nimport java.io.File;\n\n/*\n * #%L\n * NanoHttpd-Core\n * %%\n * Copyright (C) 20"
  },
  {
    "path": "core/src/test/java/org/nanohttpd/junit/protocols/http/ServerSocketFactoryTest.java",
    "chars": 3521,
    "preview": "package org.nanohttpd.junit.protocols.http;\n\nimport java.io.File;\n\n/*\n * #%L\n * NanoHttpd-Core\n * %%\n * Copyright (C) 20"
  },
  {
    "path": "core/src/test/java/org/nanohttpd/junit/protocols/http/StatusTest.java",
    "chars": 6070,
    "preview": "package org.nanohttpd.junit.protocols.http;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\n/*\n * #%L\n * NanoHttpd-Cor"
  },
  {
    "path": "core/src/test/java/org/nanohttpd/junit/protocols/http/integration/CookieIntegrationTest.java",
    "chars": 7371,
    "preview": "package org.nanohttpd.junit.protocols.http.integration;\n\n/*\n * #%L\n * NanoHttpd-Core\n * %%\n * Copyright (C) 2012 - 2015 "
  },
  {
    "path": "core/src/test/java/org/nanohttpd/junit/protocols/http/integration/GZipIntegrationTest.java",
    "chars": 7602,
    "preview": "package org.nanohttpd.junit.protocols.http.integration;\n\n/*\n * #%L\n * NanoHttpd-Core\n * %%\n * Copyright (C) 2012 - 2015 "
  },
  {
    "path": "core/src/test/java/org/nanohttpd/junit/protocols/http/integration/GetAndPostIntegrationTest.java",
    "chars": 9406,
    "preview": "package org.nanohttpd.junit.protocols.http.integration;\n\n/*\n * #%L\n * NanoHttpd-Core\n * %%\n * Copyright (C) 2012 - 2015 "
  },
  {
    "path": "core/src/test/java/org/nanohttpd/junit/protocols/http/integration/IntegrationTestBase.java",
    "chars": 2507,
    "preview": "package org.nanohttpd.junit.protocols.http.integration;\n\n/*\n * #%L\n * NanoHttpd-Core\n * %%\n * Copyright (C) 2012 - 2015 "
  },
  {
    "path": "core/src/test/java/org/nanohttpd/junit/protocols/http/integration/PutStreamIntegrationTest.java",
    "chars": 3947,
    "preview": "package org.nanohttpd.junit.protocols.http.integration;\n\n/*\n * #%L\n * NanoHttpd-Core\n * %%\n * Copyright (C) 2012 - 2015 "
  },
  {
    "path": "core/src/test/java/org/nanohttpd/junit/protocols/http/integration/ShutdownTest.java",
    "chars": 3183,
    "preview": "package org.nanohttpd.junit.protocols.http.integration;\n\n/*\n * #%L\n * NanoHttpd-Core\n * %%\n * Copyright (C) 2012 - 2015 "
  },
  {
    "path": "core/src/test/resources/META-INF/nanohttpd/mimetypes.properties",
    "chars": 73,
    "preview": "#test mime types for nanohttpd\nblabla=text/blabla\nts=video/wrongOverwrite"
  },
  {
    "path": "core/src/test/resources/file-upload-test.htm",
    "chars": 2250,
    "preview": "<!--\n  #%L\n  NanoHttpd-Core\n  %%\n  Copyright (C) 2012 - 2015 nanohttpd\n  %%\n  Redistribution and use in source and binar"
  },
  {
    "path": "core/src/test/resources/multipart-form-test.htm",
    "chars": 2099,
    "preview": "<!--\n  #%L\n  NanoHttpd-Core\n  %%\n  Copyright (C) 2012 - 2015 nanohttpd\n  %%\n  Redistribution and use in source and binar"
  },
  {
    "path": "fileupload/.gitignore",
    "chars": 25,
    "preview": "/.settings/\n/LICENSE.txt\n"
  },
  {
    "path": "fileupload/build.gradle",
    "chars": 606,
    "preview": "description = 'NanoHttpd-apache file upload integration'\n\ndependencies {\n\tcompile group: 'commons-fileupload', name: 'co"
  },
  {
    "path": "fileupload/pom.xml",
    "chars": 1569,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2"
  },
  {
    "path": "fileupload/src/main/java/org/nanohttpd/fileupload/NanoFileUpload.java",
    "chars": 4210,
    "preview": "package org.nanohttpd.fileupload;\n\n/*\n * #%L\n * NanoHttpd-apache file upload integration\n * %%\n * Copyright (C) 2012 - 2"
  },
  {
    "path": "fileupload/src/test/java/org/nanohttpd/junit/fileupload/TestNanoFileUpLoad.java",
    "chars": 10553,
    "preview": "package org.nanohttpd.junit.fileupload;\n\n/*\n * #%L\n * NanoHttpd-apache file upload integration\n * %%\n * Copyright (C) 20"
  },
  {
    "path": "markdown-plugin/.gitignore",
    "chars": 25,
    "preview": "/.settings/\n/LICENSE.txt\n"
  },
  {
    "path": "markdown-plugin/build.gradle",
    "chars": 273,
    "preview": "description = 'NanoHttpd-Webserver-Markdown-Plugin'\n\ndependencies {\n\tcompile group: 'org.pegdown', name: 'pegdown', vers"
  },
  {
    "path": "markdown-plugin/pom.xml",
    "chars": 1809,
    "preview": "<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocat"
  },
  {
    "path": "markdown-plugin/src/main/java/org/nanohttpd/markdown/MarkdownWebServerPlugin.java",
    "chars": 4672,
    "preview": "package org.nanohttpd.markdown;\n\n/*\n * #%L\n * NanoHttpd-Webserver-Markdown-Plugin\n * %%\n * Copyright (C) 2012 - 2016 nan"
  },
  {
    "path": "markdown-plugin/src/main/java/org/nanohttpd/markdown/MarkdownWebServerPluginInfo.java",
    "chars": 2311,
    "preview": "package org.nanohttpd.markdown;\n\nimport org.nanohttpd.webserver.WebServerPlugin;\nimport org.nanohttpd.webserver.WebServe"
  },
  {
    "path": "markdown-plugin/src/main/resources/META-INF/services/org.nanohttpd.webserver.WebServerPluginInfo",
    "chars": 50,
    "preview": "org.nanohttpd.markdown.MarkdownWebServerPluginInfo"
  },
  {
    "path": "markdown-plugin/src/site/site.xml",
    "chars": 1126,
    "preview": "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n<project name=\"${project.name}\">\n\t<skin>\n\t\t<groupId>org.apache.maven.skins</"
  },
  {
    "path": "nanohttpd release perform.launch",
    "chars": 1184,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<launchConfiguration type=\"org.eclipse.m2e.Maven2LaunchConfigurat"
  },
  {
    "path": "nanohttpd release prepare.launch",
    "chars": 1184,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<launchConfiguration type=\"org.eclipse.m2e.Maven2LaunchConfigurat"
  },
  {
    "path": "nanolets/.gitignore",
    "chars": 25,
    "preview": "/.settings/\n/LICENSE.txt\n"
  },
  {
    "path": "nanolets/build.gradle",
    "chars": 187,
    "preview": "description = 'NanoHttpd-nano application server'\n\ndependencies {\n\tcompile project(':nanohttpd')\n\t\n\ttestCompile group: '"
  },
  {
    "path": "nanolets/pom.xml",
    "chars": 1042,
    "preview": "<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocat"
  },
  {
    "path": "nanolets/src/main/java/org/nanohttpd/router/RouterNanoHTTPD.java",
    "chars": 23560,
    "preview": "package org.nanohttpd.router;\n\n/*\n * #%L\n * NanoHttpd-Samples\n * %%\n * Copyright (C) 2012 - 2015 nanohttpd\n * %%\n * Redi"
  },
  {
    "path": "nanolets/src/test/java/org/nanohttpd/junit/router/AppNanolets.java",
    "chars": 6792,
    "preview": "package org.nanohttpd.junit.router;\n\n/*\n * #%L\n * NanoHttpd-Samples\n * %%\n * Copyright (C) 2012 - 2015 nanohttpd\n * %%\n "
  },
  {
    "path": "nanolets/src/test/java/org/nanohttpd/junit/router/TestNanolets.java",
    "chars": 25341,
    "preview": "package org.nanohttpd.junit.router;\n\n/*\n * #%L\n * NanoHttpd nano application server\n * %%\n * Copyright (C) 2012 - 2015 n"
  },
  {
    "path": "nanolets/src/test/resources/blabla.html",
    "chars": 46,
    "preview": "<html><body><h3>just a page</h3></body></html>"
  },
  {
    "path": "nanolets/src/test/resources/dir/blabla.html",
    "chars": 53,
    "preview": "<html><body><h3>just an other page</h3></body></html>"
  },
  {
    "path": "nanolets/src/test/resources/dir/index.htm",
    "chars": 53,
    "preview": "<html><body><h3>just an index page</h3></body></html>"
  },
  {
    "path": "nanolets/src/test/resources/exception.html",
    "chars": 31,
    "preview": "this will throw an io exception"
  },
  {
    "path": "pom.xml",
    "chars": 14005,
    "preview": "<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocat"
  },
  {
    "path": "relocation/nanohttpd/pom.xml",
    "chars": 536,
    "preview": "<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\txsi:schemaLoca"
  },
  {
    "path": "relocation/nanohttpd/src/main/resources/relocated.txt",
    "chars": 83,
    "preview": "this project was relocated to the groupid org.nanohttpd starting with version 2.2.0"
  },
  {
    "path": "relocation/nanohttpd-samples/pom.xml",
    "chars": 544,
    "preview": "<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\txsi:schemaLoca"
  },
  {
    "path": "relocation/nanohttpd-samples/src/main/resources/relocated.txt",
    "chars": 83,
    "preview": "this project was relocated to the groupid org.nanohttpd starting with version 2.2.0"
  },
  {
    "path": "relocation/nanohttpd-webserver/pom.xml",
    "chars": 546,
    "preview": "<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\txsi:schemaLoca"
  },
  {
    "path": "relocation/nanohttpd-webserver/src/main/resources/relocated.txt",
    "chars": 83,
    "preview": "this project was relocated to the groupid org.nanohttpd starting with version 2.2.0"
  },
  {
    "path": "relocation/nanohttpd-webserver-markdown-plugin/pom.xml",
    "chars": 562,
    "preview": "<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\txsi:schemaLoca"
  },
  {
    "path": "relocation/nanohttpd-webserver-markdown-plugin/src/main/resources/relocated.txt",
    "chars": 83,
    "preview": "this project was relocated to the groupid org.nanohttpd starting with version 2.2.0"
  },
  {
    "path": "relocation/nanohttpd-websocket/pom.xml",
    "chars": 546,
    "preview": "<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\txsi:schemaLoca"
  },
  {
    "path": "relocation/nanohttpd-websocket/src/main/resources/relocated.txt",
    "chars": 83,
    "preview": "this project was relocated to the groupid org.nanohttpd starting with version 2.2.0"
  },
  {
    "path": "relocation/pom.xml",
    "chars": 1462,
    "preview": "<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\txsi:schemaLoca"
  },
  {
    "path": "samples/.gitignore",
    "chars": 25,
    "preview": "/.settings/\n/LICENSE.txt\n"
  },
  {
    "path": "samples/build.gradle",
    "chars": 182,
    "preview": "description = 'NanoHttpd-Samples'\n\ndependencies {\n\tcompile project(':nanohttpd')\n\tcompile project(':nanohttpd-webserver'"
  },
  {
    "path": "samples/pom.xml",
    "chars": 960,
    "preview": "<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocat"
  },
  {
    "path": "samples/src/main/java/org/nanohttpd/samples/http/DebugServer.java",
    "chars": 4249,
    "preview": "package org.nanohttpd.samples.http;\n\n/*\n * #%L\n * NanoHttpd-Samples\n * %%\n * Copyright (C) 2012 - 2015 nanohttpd\n * %%\n "
  },
  {
    "path": "samples/src/main/java/org/nanohttpd/samples/http/HelloServer.java",
    "chars": 3033,
    "preview": "package org.nanohttpd.samples.http;\n\n/*\n * #%L\n * NanoHttpd-Samples\n * %%\n * Copyright (C) 2012 - 2015 nanohttpd\n * %%\n "
  },
  {
    "path": "samples/src/main/java/org/nanohttpd/samples/tempfiles/TempFilesServer.java",
    "chars": 3715,
    "preview": "package org.nanohttpd.samples.tempfiles;\n\n/*\n * #%L\n * NanoHttpd-Samples\n * %%\n * Copyright (C) 2012 - 2015 nanohttpd\n *"
  },
  {
    "path": "samples/src/site/site.xml",
    "chars": 1126,
    "preview": "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n<project name=\"${project.name}\">\n\t<skin>\n\t\t<groupId>org.apache.maven.skins</"
  },
  {
    "path": "settings.gradle",
    "chars": 795,
    "preview": "rootProject.name = 'nanohttpd-project'\ninclude ':nanohttpd'\ninclude ':nanohttpd-samples'\ninclude ':nanohttpd-webserver'\n"
  },
  {
    "path": "settings.xml",
    "chars": 274,
    "preview": "<settings>\n\t<proxies>\n\t</proxies>\n\t<servers>\n\t\t<server>\n\t\t\t<id>sonatype-nexus-staging</id>\n\t\t\t<username>${env.CI_DEPLOY_"
  },
  {
    "path": "src/main/checkstyle/checkstyle-suppressions.xml",
    "chars": 1261,
    "preview": "<?xml version=\"1.0\"?>\n\n<!DOCTYPE suppressions PUBLIC\n     \"-//Puppy Crawl//DTD Suppressions 1.0//EN\"\n     \"http://www.pu"
  },
  {
    "path": "src/main/checkstyle/nanohttpd-style.xml",
    "chars": 5969,
    "preview": "<?xml version=\"1.0\"?>\n<!DOCTYPE module PUBLIC\n          \"-//Puppy Crawl//DTD Check Configuration 1.3//EN\"\n          \"htt"
  },
  {
    "path": "src/main/formatter/formatter.xml",
    "chars": 28487,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<profiles version=\"11\">\n<profile kind=\"CodeFormatterProfile\" name=\"CFC\" version=\""
  },
  {
    "path": "src/site/markdown/index.md",
    "chars": 11134,
    "preview": "## NanoHTTPD – a tiny web server in Java\n\n*NanoHTTPD* is a light-weight HTTP server designed for embedding in other appl"
  },
  {
    "path": "src/site/site.xml",
    "chars": 1117,
    "preview": "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n<project name=\"${project.name}\">\n\t<skin>\n\t\t<groupId>org.apache.maven.skins</"
  },
  {
    "path": "webserver/.gitignore",
    "chars": 25,
    "preview": "/.settings/\n/LICENSE.txt\n"
  },
  {
    "path": "webserver/build.gradle",
    "chars": 231,
    "preview": "description = 'NanoHttpd-Webserver'\n\ndependencies {\n\tcompile project(':nanohttpd')\n\t\n\ttestCompile group: 'org.apache.htt"
  },
  {
    "path": "webserver/pom.xml",
    "chars": 1661,
    "preview": "<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocat"
  },
  {
    "path": "webserver/src/main/java/org/nanohttpd/webserver/InternalRewrite.java",
    "chars": 2427,
    "preview": "package org.nanohttpd.webserver;\n\n/*\n * #%L\n * NanoHttpd-Webserver\n * %%\n * Copyright (C) 2012 - 2015 nanohttpd\n * %%\n *"
  },
  {
    "path": "webserver/src/main/java/org/nanohttpd/webserver/SimpleWebServer.java",
    "chars": 25068,
    "preview": "package org.nanohttpd.webserver;\n\n/*\n * #%L\n * NanoHttpd-Webserver\n * %%\n * Copyright (C) 2012 - 2015 nanohttpd\n * %%\n *"
  },
  {
    "path": "webserver/src/main/java/org/nanohttpd/webserver/WebServerPlugin.java",
    "chars": 2134,
    "preview": "package org.nanohttpd.webserver;\n\n/*\n * #%L\n * NanoHttpd-Webserver\n * %%\n * Copyright (C) 2012 - 2015 nanohttpd\n * %%\n *"
  },
  {
    "path": "webserver/src/main/java/org/nanohttpd/webserver/WebServerPluginInfo.java",
    "chars": 1899,
    "preview": "package org.nanohttpd.webserver;\n\n/*\n * #%L\n * NanoHttpd-Webserver\n * %%\n * Copyright (C) 2012 - 2015 nanohttpd\n * %%\n *"
  },
  {
    "path": "webserver/src/site/site.xml",
    "chars": 1126,
    "preview": "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n<project name=\"${project.name}\">\n\t<skin>\n\t\t<groupId>org.apache.maven.skins</"
  },
  {
    "path": "webserver/src/test/java/org/nanohttpd/junit/webserver/AbstractTestHttpServer.java",
    "chars": 2543,
    "preview": "package org.nanohttpd.junit.webserver;\n\n/*\n * #%L\n * NanoHttpd-Webserver\n * %%\n * Copyright (C) 2012 - 2015 nanohttpd\n *"
  },
  {
    "path": "webserver/src/test/java/org/nanohttpd/junit/webserver/DummyPlugin.java",
    "chars": 2715,
    "preview": "package org.nanohttpd.junit.webserver;\n\n/*\n * #%L\n * NanoHttpd-Webserver\n * %%\n * Copyright (C) 2012 - 2015 nanohttpd\n *"
  },
  {
    "path": "webserver/src/test/java/org/nanohttpd/junit/webserver/DummyPluginInfo.java",
    "chars": 2197,
    "preview": "package org.nanohttpd.junit.webserver;\n\nimport org.nanohttpd.webserver.WebServerPlugin;\nimport org.nanohttpd.webserver.W"
  },
  {
    "path": "webserver/src/test/java/org/nanohttpd/junit/webserver/TestCorsHttpServer.java",
    "chars": 7039,
    "preview": "package org.nanohttpd.junit.webserver;\n\n/*\n * #%L\n * NanoHttpd-Webserver\n * %%\n * Copyright (C) 2012 - 2016 nanohttpd\n *"
  },
  {
    "path": "webserver/src/test/java/org/nanohttpd/junit/webserver/TestCorsHttpServerWithSingleOrigin.java",
    "chars": 5080,
    "preview": "package org.nanohttpd.junit.webserver;\n\n/*\n * #%L\n * NanoHttpd-Webserver\n * %%\n * Copyright (C) 2012 - 2016 nanohttpd\n *"
  },
  {
    "path": "webserver/src/test/java/org/nanohttpd/junit/webserver/TestHttpServer.java",
    "chars": 15850,
    "preview": "package org.nanohttpd.junit.webserver;\n\n/*\n * #%L\n * NanoHttpd-Webserver\n * %%\n * Copyright (C) 2012 - 2015 nanohttpd\n *"
  },
  {
    "path": "webserver/src/test/resources/META-INF/services/org.nanohttpd.webserver.WebServerPluginInfo",
    "chars": 45,
    "preview": "org.nanohttpd.junit.webserver.DummyPluginInfo"
  },
  {
    "path": "webserver/src/test/resources/testdir/test.html",
    "chars": 84,
    "preview": "<html>\n<head>\n<title>dummy</title>\n</head>\n<body>\n\t<h1>it works</h1>\n</body>\n</html>"
  },
  {
    "path": "webserver/src/test/resources/testdir/testdir/different.xml",
    "chars": 40,
    "preview": "<xml>\n\tThis sould not show up ;-)\n</xml>"
  },
  {
    "path": "webserver/src/test/resources/testdir/testdir/index.html",
    "chars": 62,
    "preview": "<html>\n<head>\n<title>Simple index file</title>\n</head>\n</html>"
  },
  {
    "path": "websocket/.gitignore",
    "chars": 25,
    "preview": "/.settings/\n/LICENSE.txt\n"
  },
  {
    "path": "websocket/build.gradle",
    "chars": 313,
    "preview": "description = 'NanoHttpd-Websocket'\n\ndependencies {\n\tcompile project(':nanohttpd')\n\ttestCompile group: 'org.mockito', na"
  },
  {
    "path": "websocket/pom.xml",
    "chars": 1996,
    "preview": "<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocat"
  },
  {
    "path": "websocket/src/main/java/org/nanohttpd/protocols/websockets/CloseCode.java",
    "chars": 2360,
    "preview": "package org.nanohttpd.protocols.websockets;\n\n/*\n * #%L\n * NanoHttpd-Websocket\n * %%\n * Copyright (C) 2012 - 2016 nanohtt"
  },
  {
    "path": "websocket/src/main/java/org/nanohttpd/protocols/websockets/CloseFrame.java",
    "chars": 3138,
    "preview": "package org.nanohttpd.protocols.websockets;\n\n/*\n * #%L\n * NanoHttpd-Websocket\n * %%\n * Copyright (C) 2012 - 2016 nanohtt"
  },
  {
    "path": "websocket/src/main/java/org/nanohttpd/protocols/websockets/NanoWSD.java",
    "chars": 7588,
    "preview": "package org.nanohttpd.protocols.websockets;\n\n/*\n * #%L\n * NanoHttpd-Websocket\n * %%\n * Copyright (C) 2012 - 2016 nanohtt"
  },
  {
    "path": "websocket/src/main/java/org/nanohttpd/protocols/websockets/OpCode.java",
    "chars": 2246,
    "preview": "package org.nanohttpd.protocols.websockets;\n\n/*\n * #%L\n * NanoHttpd-Websocket\n * %%\n * Copyright (C) 2012 - 2016 nanohtt"
  },
  {
    "path": "websocket/src/main/java/org/nanohttpd/protocols/websockets/State.java",
    "chars": 1738,
    "preview": "package org.nanohttpd.protocols.websockets;\n\n/*\n * #%L\n * NanoHttpd-Websocket\n * %%\n * Copyright (C) 2012 - 2016 nanohtt"
  },
  {
    "path": "websocket/src/main/java/org/nanohttpd/protocols/websockets/WebSocket.java",
    "chars": 9662,
    "preview": "package org.nanohttpd.protocols.websockets;\n\n/*\n * #%L\n * NanoHttpd-Websocket\n * %%\n * Copyright (C) 2012 - 2016 nanohtt"
  },
  {
    "path": "websocket/src/main/java/org/nanohttpd/protocols/websockets/WebSocketException.java",
    "chars": 2407,
    "preview": "package org.nanohttpd.protocols.websockets;\n\n/*\n * #%L\n * NanoHttpd-Websocket\n * %%\n * Copyright (C) 2012 - 2016 nanohtt"
  },
  {
    "path": "websocket/src/main/java/org/nanohttpd/protocols/websockets/WebSocketFrame.java",
    "chars": 13527,
    "preview": "package org.nanohttpd.protocols.websockets;\n\n/*\n * #%L\n * NanoHttpd-Websocket\n * %%\n * Copyright (C) 2012 - 2016 nanohtt"
  },
  {
    "path": "websocket/src/main/java/org/nanohttpd/samples/websockets/DebugWebSocketServer.java",
    "chars": 4333,
    "preview": "package org.nanohttpd.samples.websockets;\n\n/*\n * #%L\n * NanoHttpd-Websocket\n * %%\n * Copyright (C) 2012 - 2015 nanohttpd"
  },
  {
    "path": "websocket/src/main/java/org/nanohttpd/samples/websockets/EchoSocketSample.java",
    "chars": 2284,
    "preview": "package org.nanohttpd.samples.websockets;\n\n/*\n * #%L\n * NanoHttpd-Websocket\n * %%\n * Copyright (C) 2012 - 2015 nanohttpd"
  },
  {
    "path": "websocket/src/site/site.xml",
    "chars": 1126,
    "preview": "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n<project name=\"${project.name}\">\n\t<skin>\n\t\t<groupId>org.apache.maven.skins</"
  },
  {
    "path": "websocket/src/test/java/org/nanohttpd/junit/protocols/websockets/EchoWebSocketsTest.java",
    "chars": 5108,
    "preview": "package org.nanohttpd.junit.protocols.websockets;\n\n/*\n * #%L\n * NanoHttpd-Websocket\n * %%\n * Copyright (C) 2012 - 2015 n"
  },
  {
    "path": "websocket/src/test/java/org/nanohttpd/junit/protocols/websockets/SimpleEchoSocket.java",
    "chars": 3788,
    "preview": "package org.nanohttpd.junit.protocols.websockets;\n\n/*\n * #%L\n * NanoHttpd-Websocket\n * %%\n * Copyright (C) 2012 - 2015 n"
  },
  {
    "path": "websocket/src/test/java/org/nanohttpd/junit/protocols/websockets/WebSocketResponseHandlerTest.java",
    "chars": 12553,
    "preview": "package org.nanohttpd.junit.protocols.websockets;\n\n/*\n * #%L\n * NanoHttpd-Websocket\n * %%\n * Copyright (C) 2012 - 2015 n"
  },
  {
    "path": "websocket/src/test/resources/echo-test.html",
    "chars": 3353,
    "preview": "<!--\n  #%L\n  NanoHttpd-Websocket\n  %%\n  Copyright (C) 2012 - 2015 nanohttpd\n  %%\n  Redistribution and use in source and "
  }
]

// ... and 1 more files (download for full content)

About this extraction

This page contains the full source code of the NanoHttpd/nanohttpd GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 155 files (606.7 KB), approximately 144.9k tokens, and a symbol index with 817 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!