Requestpublic class Request extends Object Represents an HTTP request for a given host.
{@hide} |
Fields Summary |
---|
EventHandler | mEventHandlerThe eventhandler to call as the request progresses | private Connection | mConnection | BasicHttpRequest | mHttpRequestThe Apache http request | String | mPathThe path component of this request | HttpHost | mHostHost serving this request | HttpHost | mProxyHostSet if I'm using a proxy server | boolean | mHighPriorityTrue if request is .html, .js, .css | volatile boolean | mCancelledTrue if request has been cancelled | int | mFailCount | private InputStream | mBodyProvider | private int | mBodyLength | private static final String | HOST_HEADER | private static final String | ACCEPT_ENCODING_HEADER | private static final String | CONTENT_LENGTH_HEADER | private final Object | mClientResource | private static RequestContent | requestContentProcessorProcessor used to set content-length and transfer-encoding
headers. |
Constructors Summary |
---|
Request(String method, HttpHost host, HttpHost proxyHost, String path, InputStream bodyProvider, int bodyLength, EventHandler eventHandler, Map headers, boolean highPriority)Instantiates a new Request.
mEventHandler = eventHandler;
mHost = host;
mProxyHost = proxyHost;
mPath = path;
mHighPriority = highPriority;
mBodyProvider = bodyProvider;
mBodyLength = bodyLength;
if (bodyProvider == null) {
mHttpRequest = new BasicHttpRequest(method, getUri());
} else {
mHttpRequest = new BasicHttpEntityEnclosingRequest(
method, getUri());
setBodyProvider(bodyProvider, bodyLength);
}
addHeader(HOST_HEADER, getHostPort());
/* FIXME: if webcore will make the root document a
high-priority request, we can ask for gzip encoding only on
high priority reqs (saving the trouble for images, etc) */
addHeader(ACCEPT_ENCODING_HEADER, "gzip");
addHeaders(headers);
|
Methods Summary |
---|
void | addHeader(java.lang.String name, java.lang.String value)Add header represented by given pair to request. Header will
be formatted in request as "name: value\r\n".
if (name == null) {
String damage = "Null http header name";
HttpLog.e(damage);
throw new NullPointerException(damage);
}
if (value == null || value.length() == 0) {
String damage = "Null or empty value for header \"" + name + "\"";
HttpLog.e(damage);
throw new RuntimeException(damage);
}
mHttpRequest.addHeader(name, value);
| void | addHeaders(java.util.Map headers)Add all headers in given map to this request. This is a helper
method: it calls addHeader for each pair in the map.
if (headers == null) {
return;
}
Entry<String, String> entry;
Iterator<Entry<String, String>> i = headers.entrySet().iterator();
while (i.hasNext()) {
entry = i.next();
addHeader(entry.getKey(), entry.getValue());
}
| private static boolean | canResponseHaveBody(org.apache.http.HttpRequest request, int status)Decide whether a response comes with an entity.
The implementation in this class is based on RFC 2616.
Unknown methods and response codes are supposed to
indicate responses with an entity.
Derived executors can override this method to handle
methods and response codes not specified in RFC 2616.
if ("HEAD".equalsIgnoreCase(request.getRequestLine().getMethod())) {
return false;
}
return status >= HttpStatus.SC_OK
&& status != HttpStatus.SC_NO_CONTENT
&& status != HttpStatus.SC_NOT_MODIFIED
&& status != HttpStatus.SC_RESET_CONTENT;
| void | cancel()Data will not be sent to or received from server after cancel()
call. Does not close connection--use close() below for that.
Called by RequestHandle from non-network thread
if (HttpLog.LOGV) {
HttpLog.v("Request.cancel(): " + getUri());
}
mCancelled = true;
if (mConnection != null) {
mConnection.cancel();
}
| void | complete()
synchronized (mClientResource) {
mClientResource.notifyAll();
}
| void | error(int errorId, int resourceId)Helper: calls error() on eventhandler with appropriate message
This should not be called before the mConnection is set.
mEventHandler.error(
errorId,
mConnection.mContext.getText(
resourceId).toString());
| EventHandler | getEventHandler()
return mEventHandler;
| java.lang.String | getHostPort()
String myScheme = mHost.getSchemeName();
int myPort = mHost.getPort();
// Only send port when we must... many servers can't deal with it
if (myPort != 80 && myScheme.equals("http") ||
myPort != 443 && myScheme.equals("https")) {
return mHost.toHostString();
} else {
return mHost.getHostName();
}
| java.lang.String | getUri()
if (mProxyHost == null ||
mHost.getSchemeName().equals("https")) {
return mPath;
}
return mHost.getSchemeName() + "://" + getHostPort() + mPath;
| public void | handleSslErrorResponse(boolean proceed)Handles SSL error(s) on the way down from the user (the user
has already provided their feedback).
HttpsConnection connection = (HttpsConnection)(mConnection);
if (connection != null) {
connection.restartConnection(proceed);
}
| void | readResponse(AndroidHttpClientConnection httpClientConnection)Receive a single http response.
if (mCancelled) return; // don't send cancelled requests
StatusLine statusLine = null;
boolean hasBody = false;
boolean reuse = false;
httpClientConnection.flush();
int statusCode = 0;
Headers header = new Headers();
do {
statusLine = httpClientConnection.parseResponseHeader(header);
statusCode = statusLine.getStatusCode();
} while (statusCode < HttpStatus.SC_OK);
if (HttpLog.LOGV) HttpLog.v(
"Request.readResponseStatus() " +
statusLine.toString().length() + " " + statusLine);
ProtocolVersion v = statusLine.getProtocolVersion();
mEventHandler.status(v.getMajor(), v.getMinor(),
statusCode, statusLine.getReasonPhrase());
mEventHandler.headers(header);
HttpEntity entity = null;
hasBody = canResponseHaveBody(mHttpRequest, statusCode);
if (hasBody)
entity = httpClientConnection.receiveResponseEntity(header);
if (entity != null) {
InputStream is = entity.getContent();
// process gzip content encoding
Header contentEncoding = entity.getContentEncoding();
InputStream nis = null;
try {
if (contentEncoding != null &&
contentEncoding.getValue().equals("gzip")) {
nis = new GZIPInputStream(is);
} else {
nis = is;
}
/* accumulate enough data to make it worth pushing it
* up the stack */
byte[] buf = mConnection.getBuf();
int len = 0;
int count = 0;
int lowWater = buf.length / 2;
while (len != -1) {
len = nis.read(buf, count, buf.length - count);
if (len != -1) {
count += len;
}
if (len == -1 || count >= lowWater) {
if (HttpLog.LOGV) HttpLog.v("Request.readResponse() " + count);
mEventHandler.data(buf, count);
count = 0;
}
}
} catch (EOFException e) {
/* InflaterInputStream throws an EOFException when the
server truncates gzipped content. Handle this case
as we do truncated non-gzipped content: no error */
if (HttpLog.LOGV) HttpLog.v( "readResponse() handling " + e);
} catch(IOException e) {
// don't throw if we have a non-OK status code
if (statusCode == HttpStatus.SC_OK) {
throw e;
}
} finally {
if (nis != null) {
nis.close();
}
}
}
mConnection.setCanPersist(entity, statusLine.getProtocolVersion(),
header.getConnectionType());
mEventHandler.endData();
complete();
if (HttpLog.LOGV) HttpLog.v("Request.readResponse(): done " +
mHost.getSchemeName() + "://" + getHostPort() + mPath);
| void | reset()If this request has been sent once and failed, it must be reset
before it can be sent again.
/* clear content-length header */
mHttpRequest.removeHeaders(CONTENT_LENGTH_HEADER);
if (mBodyProvider != null) {
try {
mBodyProvider.reset();
} catch (IOException ex) {
if (HttpLog.LOGV) HttpLog.v(
"failed to reset body provider " +
getUri());
}
setBodyProvider(mBodyProvider, mBodyLength);
}
| void | sendRequest(AndroidHttpClientConnection httpClientConnection)Send the request line and headers
if (mCancelled) return; // don't send cancelled requests
if (HttpLog.LOGV) {
HttpLog.v("Request.sendRequest() " + mHost.getSchemeName() + "://" + getHostPort());
// HttpLog.v(mHttpRequest.getRequestLine().toString());
if (false) {
Iterator i = mHttpRequest.headerIterator();
while (i.hasNext()) {
Header header = (Header)i.next();
HttpLog.v(header.getName() + ": " + header.getValue());
}
}
}
requestContentProcessor.process(mHttpRequest,
mConnection.getHttpContext());
httpClientConnection.sendRequestHeader(mHttpRequest);
if (mHttpRequest instanceof HttpEntityEnclosingRequest) {
httpClientConnection.sendRequestEntity(
(HttpEntityEnclosingRequest) mHttpRequest);
}
if (HttpLog.LOGV) {
HttpLog.v("Request.requestSent() " + mHost.getSchemeName() + "://" + getHostPort() + mPath);
}
| private void | setBodyProvider(java.io.InputStream bodyProvider, int bodyLength)Supply an InputStream that provides the body of a request. It's
not great that the caller must also provide the length of the data
returned by that InputStream, but the client needs to know up
front, and I'm not sure how to get this out of the InputStream
itself without a costly readthrough. I'm not sure skip() would
do what we want. If you know a better way, please let me know.
if (!bodyProvider.markSupported()) {
throw new IllegalArgumentException(
"bodyProvider must support mark()");
}
// Mark beginning of stream
bodyProvider.mark(Integer.MAX_VALUE);
((BasicHttpEntityEnclosingRequest)mHttpRequest).setEntity(
new InputStreamEntity(bodyProvider, bodyLength));
| void | setConnection(Connection connection)
mConnection = connection;
| public java.lang.String | toString()for debugging
return (mHighPriority ? "P*" : "") + mPath;
| void | waitUntilComplete()Pause thread request completes. Used for synchronous requests,
and testing
synchronized (mClientResource) {
try {
if (HttpLog.LOGV) HttpLog.v("Request.waitUntilComplete()");
mClientResource.wait();
if (HttpLog.LOGV) HttpLog.v("Request.waitUntilComplete() done waiting");
} catch (InterruptedException e) {
}
}
|
|