diff options
author | Jarno Elonen <elonen@iki.fi> | 2015-05-24 14:57:04 +0300 |
---|---|---|
committer | Jarno Elonen <elonen@iki.fi> | 2015-05-24 14:57:04 +0300 |
commit | dde976d5b0ef7d237e32679bbe1a1a717bd0007e (patch) | |
tree | 309d7aff1514e19d02e1dfa8bdf9b021ddf30f93 /core/src/main/java | |
parent | a3481989f3cc7d7cd69685349fd6f3d2b370bbee (diff) | |
download | nanohttpd-dde976d5b0ef7d237e32679bbe1a1a717bd0007e.tar.gz |
Make 'Connection: Close' handling HTTP 1.1 compliant. Closes #133
Diffstat (limited to 'core/src/main/java')
-rw-r--r-- | core/src/main/java/fi/iki/elonen/NanoHTTPD.java | 42 |
1 files changed, 29 insertions, 13 deletions
diff --git a/core/src/main/java/fi/iki/elonen/NanoHTTPD.java b/core/src/main/java/fi/iki/elonen/NanoHTTPD.java index 50e074f..61e7d8d 100644 --- a/core/src/main/java/fi/iki/elonen/NanoHTTPD.java +++ b/core/src/main/java/fi/iki/elonen/NanoHTTPD.java @@ -468,6 +468,8 @@ public abstract class NanoHTTPD { private String remoteIp; + private String protocolVersion; + public HTTPSession(TempFileManager tempFileManager, InputStream inputStream, OutputStream outputStream) { this.tempFileManager = tempFileManager; this.inputStream = new PushbackInputStream(inputStream, HTTPSession.BUFSIZE); @@ -516,15 +518,14 @@ public abstract class NanoHTTPD { } // If there's another token, its protocol version, - // followed by HTTP headers. Ignore version but parse headers. + // followed by HTTP headers. // NOTE: this now forces header names lower case since they are // case insensitive and vary by client. if (st.hasMoreTokens()) { - if (!st.nextToken().equals("HTTP/1.1")) { - throw new ResponseException(Response.Status.UNSUPPORTED_HTTP_VERSION, "Only HTTP/1.1 is supported."); - } + protocolVersion = st.nextToken(); } else { - NanoHTTPD.LOG.log(Level.FINE, "no protocol version specified, strange.."); + 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().length() > 0) { @@ -716,6 +717,9 @@ public abstract class NanoHTTPD { this.cookies = new CookieHandler(this.headers); + String connection = this.headers.get("connection"); + boolean keepAlive = protocolVersion.equals("HTTP/1.1") && (connection == null || !connection.matches("(?i).*close.*")); + // Ok, now do the serve() Response r = serve(this); if (r == null) { @@ -725,8 +729,12 @@ public abstract class NanoHTTPD { this.cookies.unloadQueue(r); r.setRequestMethod(this.method); r.setGzipEncoding(acceptEncoding != null && acceptEncoding.contains("gzip")); + r.setKeepAlive(keepAlive); r.send(this.outputStream); } + if (!keepAlive || "close".equalsIgnoreCase(r.getHeader("connection"))) { + throw new SocketException("NanoHttpd Shutdown"); + } } catch (SocketException e) { // throw it out to close socket object (finalAccept) throw e; @@ -1170,6 +1178,8 @@ public abstract class NanoHTTPD { private boolean encodeAsGzip; + private boolean keepAlive; + /** * Creates a fixed length response if totalBytes>=0, otherwise chunked. */ @@ -1184,6 +1194,7 @@ public abstract class NanoHTTPD { this.contentLength = totalBytes; } this.chunkedTransfer = this.contentLength < 0; + keepAlive = true; } /** @@ -1198,7 +1209,12 @@ public abstract class NanoHTTPD { } public String getHeader(String name) { - return this.header.get(name); + for (String headerName : header.keySet()) { + if (headerName.equalsIgnoreCase(name)) { + return header.get(headerName); + } + } + return null; } public String getMimeType() { @@ -1217,6 +1233,10 @@ public abstract class NanoHTTPD { this.encodeAsGzip = encodeAsGzip; } + public void setKeepAlive(boolean useKeepAlive) { + this.keepAlive = useKeepAlive; + } + private boolean headerAlreadySent(Map<String, String> header, String name) { boolean alreadySent = false; for (String headerName : header.keySet()) { @@ -1255,7 +1275,9 @@ public abstract class NanoHTTPD { } } - sendConnectionHeaderIfNotAlreadyPresent(pw, this.header); + if (!headerAlreadySent(header, "connection")) { + pw.print("Connection: " + (this.keepAlive ? "keep-alive" : "close") + "\r\n"); + } if (headerAlreadySent(this.header, "content-length")) { encodeAsGzip = false; @@ -1331,12 +1353,6 @@ public abstract class NanoHTTPD { } } - protected void sendConnectionHeaderIfNotAlreadyPresent(PrintWriter pw, Map<String, String> header) { - if (!headerAlreadySent(header, "connection")) { - pw.print("Connection: keep-alive\r\n"); - } - } - protected long sendContentLengthHeaderIfNotAlreadyPresent(PrintWriter pw, Map<String, String> header, long size) { for (String headerName : header.keySet()) { if (headerName.equalsIgnoreCase("content-length")) { |