public class HTTPServer extends Object
HTTPServer class implements a light-weight HTTP server.
This server implements all functionality required by RFC 2616 ("Hypertext Transfer Protocol -- HTTP/1.1"), as well as some of the optional functionality (this is termed "conditionally compliant" in the RFC). In fact, a couple of bugs in the RFC itself were discovered (and fixed) during the development of this server.
Feature Overview
Use Cases
Being a lightweight, standalone, easily embeddable and tiny-footprint server, it is well-suited for
Implementation Notes
The design and implementation of this server attempt to balance correctness, compliance, readability, size, features, extensibility and performance, and often prioritize them in this order, but some trade-offs must be made.
This server is multithreaded in its support for multiple concurrent HTTP connections, however most of its constituent classes are not thread-safe and require external synchronization if accessed by multiple threads concurrently.
Source Structure and Documentation
This server is intentionally written as a single source file, in order to make it as easy as possible to integrate into any existing project - by simply adding this single file to the project sources. It does, however, aim to maintain a structured and flexible design. There are no external package dependencies.
This file contains extensive documentation of its classes and methods, as well as implementation details and references to specific RFC sections which clarify the logic behind the code. It is recommended that anyone attempting to modify the protocol-level functionality become acquainted with the RFC, in order to make sure that protocol compliance is not broken.
Getting Started
For an example and a good starting point for learning how to use the API,
see the main method at the bottom of the file, and follow
the code into the API from there. Alternatively, you can just browse through
the classes and utility methods and read their documentation and code.
| 限定符和类型 | 类和说明 |
|---|---|
static class |
HTTPServer.ChunkedInputStream
The
ChunkedInputStream decodes an InputStream whose data has the
"chunked" transfer encoding applied to it, providing the underlying data. |
static class |
HTTPServer.ChunkedOutputStream
The
ChunkedOutputStream encodes an OutputStream with the
"chunked" transfer encoding. |
static interface |
HTTPServer.Context
The
Context annotation decorates methods which are mapped
to a context (path) within the server, and provide its contents. |
static interface |
HTTPServer.ContextHandler
A
ContextHandler serves the content of resources within a context. |
static class |
HTTPServer.FileContextHandler
The
FileContextHandler services a context by mapping it
to a file or folder (recursively) on disk. |
static class |
HTTPServer.Header
The
Header class encapsulates a single HTTP header. |
static class |
HTTPServer.Headers
The
Headers class encapsulates a collection of HTTP headers. |
static class |
HTTPServer.LimitedInputStream
The
LimitedInputStream provides access to a limited number
of consecutive bytes from the underlying InputStream, starting at its
current position. |
static class |
HTTPServer.MethodContextHandler
The
MethodContextHandler services a context
by invoking a handler method on a specified object. |
static class |
HTTPServer.MultipartInputStream
The
MultipartInputStream decodes an InputStream whose data has
a "multipart/*" content type (see RFC 2046), providing the underlying
data of its various parts. |
static class |
HTTPServer.MultipartIterator
The
MultipartIterator iterates over the parts of a multipart/form-data request. |
class |
HTTPServer.Request
The
Request class encapsulates a single HTTP request. |
class |
HTTPServer.Response
The
Response class encapsulates a single HTTP response. |
static class |
HTTPServer.ResponseOutputStream
The
ResponseOutputStream encompasses a single response over a connection,
and does not close the underlying stream so that it can be used by subsequent responses. |
protected class |
HTTPServer.SocketHandlerThread
The
SocketHandlerThread handles accepted sockets. |
static class |
HTTPServer.VirtualHost
The
VirtualHost class represents a virtual host in the server. |
| 限定符和类型 | 字段和说明 |
|---|---|
protected static String[] |
compressibleContentTypes
The MIME types that can be compressed (prefix/suffix wildcards allowed).
|
protected static Map<String,String> |
contentTypes
A mapping of path suffixes (e.g. file extensions) to their
corresponding MIME types.
|
static byte[] |
CRLF
A convenience array containing the carriage-return and line feed chars.
|
static String[] |
DATE_PATTERNS
The SimpleDateFormat-compatible formats of dates which must be supported.
|
protected static char[] |
DAYS
Date format strings.
|
protected Executor |
executor |
protected static TimeZone |
GMT
A GMT (UTC) timezone instance.
|
protected Map<String,HTTPServer.VirtualHost> |
hosts |
protected static int |
MAX_BODY_SIZE |
protected static int |
MAX_HEADER_SIZE |
protected static char[] |
MONTHS
Date format strings.
|
protected int |
port |
protected boolean |
secure |
protected ServerSocket |
serv |
protected ServerSocketFactory |
serverSocketFactory |
protected int |
socketTimeout |
protected static String[] |
statuses
The HTTP status description strings.
|
| 构造器和说明 |
|---|
HTTPServer()
Constructs an HTTPServer which can accept connections on the default HTTP port 80.
|
HTTPServer(int port)
Constructs an HTTPServer which can accept connections on the given port.
|
| 限定符和类型 | 方法和说明 |
|---|---|
static void |
addContentType(String contentType,
String... suffixes)
Adds a Content-Type mapping for the given path suffixes.
|
static void |
addContentTypes(InputStream in)
Adds Content-Type mappings from a standard mime.types file.
|
void |
addVirtualHost(HTTPServer.VirtualHost host)
Adds the given virtual host to the server.
|
static String |
createIndex(File dir,
String path)
Serves the contents of a directory as an HTML file index.
|
protected ServerSocket |
createServerSocket()
Creates the server socket used to accept connections, using the configured
ServerSocketFactory and port. |
static String |
detectLocalHostName()
Returns the local host's auto-detected name.
|
static String |
escapeHTML(String s)
Returns an HTML-escaped version of the given string for safe display
within a web page.
|
static String |
formatDate(long time)
Formats the given time value as a string in RFC 1123 format.
|
static byte[] |
getBytes(String... strings)
Converts strings to bytes by casting the chars to bytes.
|
static int |
getConditionalStatus(HTTPServer.Request req,
long lastModified,
String etag)
Calculates the appropriate response status for the given request and
its resource's last-modified time and ETag, based on the conditional
headers present in the request.
|
static String |
getContentType(String path,
String def)
Returns the content type for the given path, according to its suffix,
or the given default content type if none can be determined.
|
static String |
getParentPath(String path)
Returns the parent of the given path.
|
HTTPServer.VirtualHost |
getVirtualHost(String name)
Returns the virtual host with the given name.
|
Set<HTTPServer.VirtualHost> |
getVirtualHosts()
Returns all virtual hosts.
|
protected void |
handleConnection(InputStream in,
OutputStream out,
Socket sock)
Handles communications for a single connection over the given streams.
|
protected void |
handleMethod(HTTPServer.Request req,
HTTPServer.Response resp)
Handles a transaction according to the request method.
|
void |
handleTrace(HTTPServer.Request req,
HTTPServer.Response resp)
Handles a TRACE method request.
|
protected void |
handleTransaction(HTTPServer.Request req,
HTTPServer.Response resp)
Handles a single transaction on a connection.
|
static boolean |
isCompressible(String contentType)
Checks whether data of the given content type (MIME type) is compressible.
|
static <T> String |
join(String delim,
Iterable<T> items)
Returns a string constructed by joining the string representations of the
iterated objects (in order), with the delimiter inserted between them.
|
static void |
main(String[] args)
Starts a stand-alone HTTP server, serving files from disk.
|
static boolean |
match(boolean strong,
String[] etags,
String etag)
Matches the given ETag value against the given ETags.
|
static Date |
parseDate(String time)
Parses a date string in one of the supported
DATE_PATTERNS. |
static List<String[]> |
parseParamsList(String s)
Parses name-value pair parameters from the given "x-www-form-urlencoded"
MIME-type string.
|
static long[] |
parseRange(String range,
long length)
Returns the absolute (zero-based) content range value specified
by the given range string.
|
static long |
parseULong(String s,
int radix)
Parses an unsigned long value.
|
protected boolean |
preprocessTransaction(HTTPServer.Request req,
HTTPServer.Response resp)
Preprocesses a transaction, performing various validation checks
and required special header handling, possibly returning an
appropriate response.
|
static HTTPServer.Headers |
readHeaders(InputStream in)
Reads headers from the given stream.
|
static String |
readLine(InputStream in)
Reads the ISO-8859-1 encoded string starting at the current stream
position and ending at the first occurrence of the LF character.
|
static String |
readToken(InputStream in,
int delim,
String enc,
int maxLength)
Reads the token starting at the current stream position and ending at
the first occurrence of the given delimiter byte, in the given encoding.
|
protected void |
serve(HTTPServer.Request req,
HTTPServer.Response resp)
Serves the content for a request by invoking the context
handler for the requested context (path) and HTTP method.
|
static int |
serveFile(File base,
String context,
HTTPServer.Request req,
HTTPServer.Response resp)
Serves a context's contents from a file based resource.
|
static void |
serveFileContent(File file,
HTTPServer.Request req,
HTTPServer.Response resp)
Serves the contents of a file, with its corresponding content type,
last modification time, etc. conditional and partial retrievals are
handled according to the RFC.
|
void |
setExecutor(Executor executor)
Sets the executor used in servicing HTTP connections.
|
void |
setPort(int port)
Sets the port on which this server will accept connections.
|
void |
setServerSocketFactory(ServerSocketFactory factory)
Sets the factory used to create the server socket.
|
void |
setSocketTimeout(int timeout)
Sets the socket timeout for established connections.
|
static String[] |
split(String str,
String delimiters,
int limit)
Splits the given string into its constituent non-empty trimmed elements,
which are delimited by any of the given delimiter characters.
|
static String[] |
splitElements(String list,
boolean lower)
Splits the given element list string (comma-separated header value)
into its constituent non-empty trimmed elements.
|
void |
start()
Starts this server.
|
void |
stop()
Stops this server.
|
static <K,V> Map<K,V> |
toMap(Collection<? extends Object[]> pairs)
Converts a collection of pairs of objects (arrays of size two,
each representing a key and corresponding value) into a Map.
|
static String |
toSizeApproxString(long size)
Returns a human-friendly string approximating the given data size,
e.g. "316", "1.8K", "324M", etc.
|
static void |
transfer(InputStream in,
OutputStream out,
long len)
Transfers data from an input stream to an output stream.
|
static String |
trimDuplicates(String s,
char c)
Trims duplicate consecutive occurrences of the given character within the
given string, replacing them with a single instance of the character.
|
static String |
trimLeft(String s,
char c)
Returns the given string with all occurrences of the given character
removed from its left side.
|
static String |
trimRight(String s,
char c)
Returns the given string with all occurrences of the given character
removed from its right side.
|
protected static int MAX_BODY_SIZE
protected static int MAX_HEADER_SIZE
public static final String[] DATE_PATTERNS
protected static final TimeZone GMT
protected static final char[] DAYS
protected static final char[] MONTHS
public static final byte[] CRLF
protected static final String[] statuses
protected static final Map<String,String> contentTypes
protected static String[] compressibleContentTypes
protected volatile int port
protected volatile int socketTimeout
protected volatile ServerSocketFactory serverSocketFactory
protected volatile boolean secure
protected volatile Executor executor
protected volatile ServerSocket serv
protected final Map<String,HTTPServer.VirtualHost> hosts
public HTTPServer(int port)
start() method must be called to start accepting
connections.port - the port on which this server will accept connectionspublic HTTPServer()
start() method must be called to start accepting connections.public void setPort(int port)
port - the port on which this server will accept connectionspublic void setServerSocketFactory(ServerSocketFactory factory)
ServerSocketFactory.getDefault() is used.
For secure sockets (HTTPS), use an SSLServerSocketFactory instance.
The port should usually also be changed for HTTPS, e.g. port 443 instead of 80.
If using the default SSLServerSocketFactory returned by
SSLServerSocketFactory.getDefault(), the appropriate system properties
must be set to configure the default JSSE provider, such as
javax.net.ssl.keyStore and javax.net.ssl.keyStorePassword.
factory - the server socket factory to usepublic void setSocketTimeout(int timeout)
timeout - the socket timeout in millisecondspublic void setExecutor(Executor executor)
executor - the executor to usepublic HTTPServer.VirtualHost getVirtualHost(String name)
name - the name of the virtual host to return,
or null for the default virtual hostpublic Set<HTTPServer.VirtualHost> getVirtualHosts()
public void addVirtualHost(HTTPServer.VirtualHost host)
host - the virtual host to addprotected ServerSocket createServerSocket() throws IOException
ServerSocketFactory and port.
Cryptic errors seen here often mean the factory configuration details are wrong.
IOException - if the socket cannot be createdpublic void start()
throws IOException
IOException - if the server cannot begin accepting connectionspublic void stop()
Executor was set, it must be closed separately.protected void handleConnection(InputStream in, OutputStream out, Socket sock) throws IOException
in - the stream from which the incoming requests are readout - the stream into which the outgoing responses are writtensock - the connected socketIOException - if an error occursprotected void handleTransaction(HTTPServer.Request req, HTTPServer.Response resp) throws IOException
Subclasses can override this method to perform filtering on the request or response, apply wrappers to them, or further customize the transaction processing in some other way.
req - the transaction requestresp - the transaction response (into which the response is written)IOException - if and error occursprotected boolean preprocessTransaction(HTTPServer.Request req, HTTPServer.Response resp) throws IOException
req - the requestresp - the responseIOException - if an error occursprotected void handleMethod(HTTPServer.Request req, HTTPServer.Response resp) throws IOException
req - the transaction requestresp - the transaction response (into which the response is written)IOException - if and error occurspublic void handleTrace(HTTPServer.Request req, HTTPServer.Response resp) throws IOException
req - the requestresp - the response into which the content is writtenIOException - if an error occursprotected void serve(HTTPServer.Request req, HTTPServer.Response resp) throws IOException
req - the requestresp - the response into which the content is writtenIOException - if an error occurspublic static void addContentType(String contentType, String... suffixes)
contentType - the content type (MIME type) to be associated with
the given path suffixessuffixes - the path suffixes which will be associated with
the contentType, e.g. the file extensions of served files
(excluding the '.' character)public static void addContentTypes(InputStream in) throws IOException
in - a stream containing a mime.types fileIOException - if an error occursFileNotFoundException - if the file is not found or cannot be readpublic static String getContentType(String path, String def)
path - the path whose content type is requesteddef - a default content type which is returned if none can be
determinedpublic static boolean isCompressible(String contentType)
contentType - the content typepublic static String detectLocalHostName()
public static List<String[]> parseParamsList(String s)
The parameters are returned as a list of string arrays, each containing the parameter name as the first element and its corresponding value as the second element (or an empty string if there is no value).
The list retains the original order of the parameters.
s - an "application/x-www-form-urlencoded" stringpublic static <K,V> Map<K,V> toMap(Collection<? extends Object[]> pairs)
K - the key typeV - the value typepairs - a collection of arrays, each containing a key and corresponding valuepublic static long[] parseRange(String range, long length)
range - the string containing the range descriptionlength - the full length of the requested resourcepublic static long parseULong(String s, int radix) throws NumberFormatException
Long.parseLong(String, int), but considers the string invalid
if it starts with an ASCII minus sign ('-') or plus sign ('+').s - the String containing the long representation to be parsedradix - the radix to be used while parsing sNumberFormatException - if the string does not contain a parsable
long, or if it starts with an ASCII minus sign or plus signpublic static Date parseDate(String time)
DATE_PATTERNS.
Received date header values must be in one of the following formats: Sun, 06 Nov 1994 08:49:37 GMT ; RFC 822, updated by RFC 1123 Sunday, 06-Nov-94 08:49:37 GMT ; RFC 850, obsoleted by RFC 1036 Sun Nov 6 08:49:37 1994 ; ANSI C's asctime() format
time - a string representation of a time valueIllegalArgumentException - if the given string does not contain
a valid date format in any of the supported formatspublic static String formatDate(long time)
time - the time in milliseconds since January 1, 1970, 00:00:00 GMTpublic static String[] splitElements(String list, boolean lower)
list - the element list stringlower - specifies whether the list elements should be lower-casedpublic static String[] split(String str, String delimiters, int limit)
str - the string to splitdelimiters - the characters used as the delimiters between elementslimit - if positive, limits the returned array size (remaining of str in last element)public static <T> String join(String delim, Iterable<T> items)
T - the item typedelim - the delimiter that is inserted between the joined stringsitems - the items whose string representations are joinedpublic static String getParentPath(String path)
path - the path whose parent is returned (must start with '/')public static String trimRight(String s, char c)
s - the string to trimc - the character to removepublic static String trimLeft(String s, char c)
s - the string to trimc - the character to removepublic static String trimDuplicates(String s, char c)
s - the string to trimc - the character to trimpublic static String toSizeApproxString(long size)
size - the size to displaypublic static String escapeHTML(String s)
s - the string to escapepublic static byte[] getBytes(String... strings)
strings - the strings to convert (containing only ISO-8859-1 chars)public static void transfer(InputStream in, OutputStream out, long len) throws IOException
in - the input stream to transfer fromout - the output stream to transfer to (or null to discard output)len - the number of bytes to transfer. If negative, the entire
contents of the input stream are transferred.IOException - if an IO error occurs or the input stream ends
before the requested number of bytes have been readpublic static String readToken(InputStream in, int delim, String enc, int maxLength) throws IOException
in - the stream from which the token is readdelim - the byte value which marks the end of the token,
or -1 if the token ends at the end of the streamenc - a character-encoding namemaxLength - the maximum length (in bytes) to readUnsupportedEncodingException - if the encoding is not supportedEOFException - if the stream end is reached before a delimiter is foundIOException - if an IO error occurs, or the maximum length
is reached before the token end is reachedpublic static String readLine(InputStream in) throws IOException
in - the stream from which the line is readEOFException - if the stream end is reached before an LF character is foundIOException - if an IO error occurs, or the line is longer than 8192 bytesreadToken(InputStream, int, String, int)public static HTTPServer.Headers readHeaders(InputStream in) throws IOException
in - the stream from which the headers are readIOException - if an IO error occurs or the headers are malformed
or there are more than 100 header linespublic static boolean match(boolean strong,
String[] etags,
String etag)
strong - if true, strong comparison is used, otherwise weak
comparison is usedetags - the ETags to match againstetag - the ETag to matchpublic static int getConditionalStatus(HTTPServer.Request req, long lastModified, String etag)
req - the requestlastModified - the resource's last modified timeetag - the resource's ETagpublic static int serveFile(File base, String context, HTTPServer.Request req, HTTPServer.Response resp) throws IOException
The file is located by stripping the given context prefix from the request's path, and appending the result to the given base directory.
Missing, forbidden and otherwise invalid files return the appropriate error response. Directories are served as an HTML index page if the virtual host allows one, or a forbidden error otherwise. Files are sent with their corresponding content types, and handle conditional and partial retrievals according to the RFC.
base - the base directory to which the context is mappedcontext - the context which is mapped to the base directoryreq - the requestresp - the response into which the content is writtenIOException - if an error occurspublic static void serveFileContent(File file, HTTPServer.Request req, HTTPServer.Response resp) throws IOException
file - the existing and readable file whose contents are servedreq - the requestresp - the response into which the content is writtenIOException - if an error occurspublic static String createIndex(File dir, String path)
dir - the existing and readable directory whose contents are servedpath - the displayed base path corresponding to dirpublic static void main(String[] args)
args - the command line argumentsCopyright © 2022. All rights reserved.