aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKoushik Dutta <koushd@gmail.com>2013-09-01 10:12:30 -0700
committerKoushik Dutta <koushd@gmail.com>2013-09-01 12:06:13 -0700
commit00878f8111d1255278dc984266f8664d2573e553 (patch)
tree75644ee4242593346f71f2754f4db23dc9cd780c
parent5e7f1df069c288a32a5910fc147919bffe264100 (diff)
downloadAndroidAsync-00878f8111d1255278dc984266f8664d2573e553.tar.gz
AndroidAsync-00878f8111d1255278dc984266f8664d2573e553.tar.bz2
AndroidAsync-00878f8111d1255278dc984266f8664d2573e553.zip
Fix up keep-alive handling.
Fix up Range/Content-Length calculations. Fix up header logging. (TODO: dont call toHeaderString) Change-Id: I3cdcdca179a5b7ddcbdaa582590e60f52cd5c515
-rw-r--r--AndroidAsync/src/com/koushikdutta/async/http/AsyncHttpClient.java4
-rw-r--r--AndroidAsync/src/com/koushikdutta/async/http/AsyncHttpRequest.java29
-rw-r--r--AndroidAsync/src/com/koushikdutta/async/http/AsyncHttpResponseImpl.java5
-rw-r--r--AndroidAsync/src/com/koushikdutta/async/http/AsyncSocketMiddleware.java6
-rw-r--r--AndroidAsync/src/com/koushikdutta/async/http/HttpUtil.java13
-rw-r--r--AndroidAsync/src/com/koushikdutta/async/http/server/AsyncHttpServer.java8
-rw-r--r--AndroidAsync/src/com/koushikdutta/async/http/server/AsyncHttpServerResponseImpl.java25
-rw-r--r--AndroidAsyncTest/src/com/koushikdutta/async/test/HttpServerTests.java2
8 files changed, 61 insertions, 31 deletions
diff --git a/AndroidAsync/src/com/koushikdutta/async/http/AsyncHttpClient.java b/AndroidAsync/src/com/koushikdutta/async/http/AsyncHttpClient.java
index d5df003..0989fe8 100644
--- a/AndroidAsync/src/com/koushikdutta/async/http/AsyncHttpClient.java
+++ b/AndroidAsync/src/com/koushikdutta/async/http/AsyncHttpClient.java
@@ -255,7 +255,7 @@ public class AsyncHttpClient {
return;
}
- request.logv("Final (post cache response) headers: " + mHeaders.getHeaders().toHeaderString());
+ request.logv("Final (post cache response) headers:\n" + mHeaders.getHeaders().toHeaderString());
// at this point the headers are done being modified
reportConnectedCompleted(cancel, null, this, request, callback);
@@ -271,7 +271,7 @@ public class AsyncHttpClient {
mServer.removeAllCallbacks(cancel.scheduled);
// allow the middleware to massage the headers before the body is decoded
- request.logv("Received headers: " + mHeaders.getHeaders().toHeaderString());
+ request.logv("Received headers:\n" + mHeaders.getHeaders().toHeaderString());
data.headers = mHeaders;
synchronized (mMiddleware) {
diff --git a/AndroidAsync/src/com/koushikdutta/async/http/AsyncHttpRequest.java b/AndroidAsync/src/com/koushikdutta/async/http/AsyncHttpRequest.java
index 37957ae..2c77a0e 100644
--- a/AndroidAsync/src/com/koushikdutta/async/http/AsyncHttpRequest.java
+++ b/AndroidAsync/src/com/koushikdutta/async/http/AsyncHttpRequest.java
@@ -71,7 +71,7 @@ public class AsyncHttpRequest {
};
}
- protected final String getDefaultUserAgent() {
+ protected static String getDefaultUserAgent() {
String agent = System.getProperty("http.agent");
return agent != null ? agent : ("Java" + System.getProperty("java.version"));
}
@@ -93,23 +93,28 @@ public class AsyncHttpRequest {
this(uri, method, null);
}
+ public static void setDefaultHeaders(RawHeaders ret, URI uri) {
+ String host = uri.getHost();
+ if (uri.getPort() != -1)
+ host = host + ":" + uri.getPort();
+ ret.set("Host", host);
+ ret.set("User-Agent", getDefaultUserAgent());
+ ret.set("Accept-Encoding", "gzip, deflate");
+ ret.set("Connection", "keep-alive");
+ ret.set("Accept", "*/*");
+ }
+
public AsyncHttpRequest(URI uri, String method, RawHeaders headers) {
assert uri != null;
mMethod = method;
if (headers == null)
- headers = new RawHeaders();
- mRawHeaders = headers;
+ mRawHeaders = new RawHeaders();
+ else
+ mRawHeaders = headers;
+ if (headers == null)
+ setDefaultHeaders(mRawHeaders, uri);
mHeaders = new RequestHeaders(uri, mRawHeaders);
mRawHeaders.setStatusLine(getRequestLine().toString());
- String host = uri.getHost();
- if (uri.getPort() != -1)
- host = host + ":" + uri.getPort();
- mHeaders.setHost(host);
- if (mHeaders.getUserAgent() == null)
- mHeaders.setUserAgent(getDefaultUserAgent());
- mHeaders.setAcceptEncoding("gzip, deflate");
- mHeaders.setConnection("keep-alive");
- mHeaders.getHeaders().set("Accept", "*/*");
}
public URI getUri() {
diff --git a/AndroidAsync/src/com/koushikdutta/async/http/AsyncHttpResponseImpl.java b/AndroidAsync/src/com/koushikdutta/async/http/AsyncHttpResponseImpl.java
index 17593e2..192b5fb 100644
--- a/AndroidAsync/src/com/koushikdutta/async/http/AsyncHttpResponseImpl.java
+++ b/AndroidAsync/src/com/koushikdutta/async/http/AsyncHttpResponseImpl.java
@@ -38,7 +38,8 @@ abstract class AsyncHttpResponseImpl extends FilteredDataEmitter implements Asyn
mWriter = mRequest.getBody();
if (mWriter != null) {
- mRequest.getHeaders().setContentType(mWriter.getContentType());
+ if (mRequest.getHeaders().getContentType() == null)
+ mRequest.getHeaders().setContentType(mWriter.getContentType());
if (mWriter.length() != -1) {
mRequest.getHeaders().setContentLength(mWriter.length());
mSink = mSocket;
@@ -61,7 +62,7 @@ abstract class AsyncHttpResponseImpl extends FilteredDataEmitter implements Asyn
});
String rs = mRequest.getRequestString();
- mRequest.logv(rs);
+ mRequest.logv("\n" + rs);
com.koushikdutta.async.Util.writeAll(exchange, rs.getBytes(), new CompletedCallback() {
@Override
public void onCompleted(Exception ex) {
diff --git a/AndroidAsync/src/com/koushikdutta/async/http/AsyncSocketMiddleware.java b/AndroidAsync/src/com/koushikdutta/async/http/AsyncSocketMiddleware.java
index bced70e..ea63a7d 100644
--- a/AndroidAsync/src/com/koushikdutta/async/http/AsyncSocketMiddleware.java
+++ b/AndroidAsync/src/com/koushikdutta/async/http/AsyncSocketMiddleware.java
@@ -267,15 +267,15 @@ public class AsyncSocketMiddleware extends SimpleMiddleware {
idleSocket(data.socket);
if (data.exception != null || !data.socket.isOpen()) {
+ data.request.logv("closing out socket (exception)");
data.socket.close();
return;
}
- String kas = data.headers.getConnection();
- if (kas == null || !"keep-alive".toLowerCase().equals(kas.toLowerCase())) {
+ if (!HttpUtil.isKeepAlive(data.headers.getHeaders())) {
+ data.request.logv("closing out socket (not keep alive)");
data.socket.close();
return;
}
-
data.request.logd("Recycling keep-alive socket");
recycleSocket(data.socket, data.request);
}
diff --git a/AndroidAsync/src/com/koushikdutta/async/http/HttpUtil.java b/AndroidAsync/src/com/koushikdutta/async/http/HttpUtil.java
index 09926ef..9e6cd9c 100644
--- a/AndroidAsync/src/com/koushikdutta/async/http/HttpUtil.java
+++ b/AndroidAsync/src/com/koushikdutta/async/http/HttpUtil.java
@@ -117,4 +117,17 @@ public class HttpUtil {
// the close/end event until the server actually closes the connection.
return emitter;
}
+
+ public static boolean isKeepAlive(RawHeaders headers) {
+ boolean keepAlive;
+ String connection = headers.get("Connection");
+ if (connection != null) {
+ keepAlive = "keep-alive".equalsIgnoreCase(connection);
+ }
+ else {
+ keepAlive = headers.getHttpMinorVersion() >= 1;
+ }
+
+ return keepAlive;
+ }
}
diff --git a/AndroidAsync/src/com/koushikdutta/async/http/server/AsyncHttpServer.java b/AndroidAsync/src/com/koushikdutta/async/http/server/AsyncHttpServer.java
index 8964e8a..08ff1b1 100644
--- a/AndroidAsync/src/com/koushikdutta/async/http/server/AsyncHttpServer.java
+++ b/AndroidAsync/src/com/koushikdutta/async/http/server/AsyncHttpServer.java
@@ -15,6 +15,7 @@ import com.koushikdutta.async.callback.CompletedCallback;
import com.koushikdutta.async.callback.ListenCallback;
import com.koushikdutta.async.http.AsyncHttpGet;
import com.koushikdutta.async.http.AsyncHttpPost;
+import com.koushikdutta.async.http.HttpUtil;
import com.koushikdutta.async.http.Multimap;
import com.koushikdutta.async.http.WebSocket;
import com.koushikdutta.async.http.WebSocketImpl;
@@ -155,7 +156,12 @@ public class AsyncHttpServer {
private void handleOnCompleted() {
if (requestComplete && responseComplete) {
- onAccepted(socket);
+ if (HttpUtil.isKeepAlive(getHeaders().getHeaders())) {
+ onAccepted(socket);
+ }
+ else {
+ socket.close();
+ }
}
}
diff --git a/AndroidAsync/src/com/koushikdutta/async/http/server/AsyncHttpServerResponseImpl.java b/AndroidAsync/src/com/koushikdutta/async/http/server/AsyncHttpServerResponseImpl.java
index 9fd6737..afc0fee 100644
--- a/AndroidAsync/src/com/koushikdutta/async/http/server/AsyncHttpServerResponseImpl.java
+++ b/AndroidAsync/src/com/koushikdutta/async/http/server/AsyncHttpServerResponseImpl.java
@@ -2,21 +2,24 @@ package com.koushikdutta.async.http.server;
import android.text.TextUtils;
-import com.koushikdutta.async.*;
+import com.koushikdutta.async.AsyncServer;
+import com.koushikdutta.async.AsyncSocket;
+import com.koushikdutta.async.ByteBufferList;
+import com.koushikdutta.async.DataSink;
+import com.koushikdutta.async.Util;
import com.koushikdutta.async.callback.CompletedCallback;
import com.koushikdutta.async.callback.WritableCallback;
+import com.koushikdutta.async.http.HttpUtil;
import com.koushikdutta.async.http.filter.ChunkedOutputFilter;
import com.koushikdutta.async.http.libcore.RawHeaders;
import com.koushikdutta.async.http.libcore.ResponseHeaders;
+
import org.json.JSONObject;
import java.io.File;
import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer;
-import java.sql.Connection;
public class AsyncHttpServerResponseImpl implements AsyncHttpServerResponse {
private RawHeaders mRawHeaders = new RawHeaders();
@@ -37,7 +40,7 @@ public class AsyncHttpServerResponseImpl implements AsyncHttpServerResponse {
AsyncHttpServerResponseImpl(AsyncSocket socket, AsyncHttpServerRequestImpl req) {
mSocket = socket;
mRequest = req;
- if ("Keep-Alive".equalsIgnoreCase(req.getHeaders().getHeaders().get(" Connection ")))
+ if (HttpUtil.isKeepAlive(req.getHeaders().getHeaders()))
mRawHeaders.set("Connection", "Keep-Alive");
}
@@ -189,7 +192,7 @@ public class AsyncHttpServerResponseImpl implements AsyncHttpServerResponse {
public void sendFile(File file) {
int start = 0;
- int end = (int)file.length();
+ int end = (int)file.length() - 1;
String range = mRequest.getHeaders().getHeaders().get("Range");
if (range != null) {
@@ -210,12 +213,12 @@ public class AsyncHttpServerResponseImpl implements AsyncHttpServerResponse {
if (parts.length == 2 && !TextUtils.isEmpty(parts[1]))
end = Integer.parseInt(parts[1]);
else if (start != 0)
- end = (int)file.length();
+ end = (int)file.length() - 1;
else
- end = Math.min((int)file.length(), start + 50000);
+ end = Math.min((int)file.length() - 1, 50000);
responseCode(206);
- getHeaders().getHeaders().set("Content-Range", String.format("bytes %d-%d/%d", start, end - 1, file.length()));
+ getHeaders().getHeaders().set("Content-Range", String.format("bytes %d-%d/%d", start, end, file.length()));
}
catch (Exception e) {
responseCode(416);
@@ -228,11 +231,11 @@ public class AsyncHttpServerResponseImpl implements AsyncHttpServerResponse {
if (start != fin.skip(start))
throw new Exception("skip failed to skip requested amount");
mRawHeaders.set("Content-Type", AsyncHttpServer.getContentType(file.getAbsolutePath()));
- mContentLength = end - start;
+ mContentLength = end - start + 1;
mRawHeaders.set("Content-Length", "" + mContentLength);
if (getHeaders().getHeaders().getStatusLine() == null)
responseCode(200);
- Util.pump(fin, end - start, this, new CompletedCallback() {
+ Util.pump(fin, mContentLength, this, new CompletedCallback() {
@Override
public void onCompleted(Exception ex) {
onEnd();
diff --git a/AndroidAsyncTest/src/com/koushikdutta/async/test/HttpServerTests.java b/AndroidAsyncTest/src/com/koushikdutta/async/test/HttpServerTests.java
index d0cab89..3d6ca3c 100644
--- a/AndroidAsyncTest/src/com/koushikdutta/async/test/HttpServerTests.java
+++ b/AndroidAsyncTest/src/com/koushikdutta/async/test/HttpServerTests.java
@@ -48,6 +48,7 @@ public class HttpServerTests extends TestCase {
httpServer.get("/hello", new HttpServerRequestCallback() {
@Override
public void onRequest(AsyncHttpServerRequest request, AsyncHttpServerResponse response) {
+ assertNotNull(request.getHeaders().getHost());
response.send("hello");
}
});
@@ -56,6 +57,7 @@ public class HttpServerTests extends TestCase {
@Override
public void onRequest(AsyncHttpServerRequest request, final AsyncHttpServerResponse response) {
try {
+ assertNotNull(request.getHeaders().getHost());
JSONObject json = new JSONObject();
if (request.getBody() instanceof UrlEncodedFormBody) {
UrlEncodedFormBody body = (UrlEncodedFormBody)request.getBody();