/* * Reads an entry from an input stream. A typical entry looks like this: * http://google.com/foo * GET * 2 * Accept-Language: fr-CA * Accept-Charset: UTF-8 * HTTP/1.1 200 OK * 3 * Content-Type: image/png * Content-Length: 100 * Cache-Control: max-age=600 * * A typical HTTPS file looks like this: * https://google.com/foo * GET * 2 * Accept-Language: fr-CA * Accept-Charset: UTF-8 * HTTP/1.1 200 OK * 3 * Content-Type: image/png * Content-Length: 100 * Cache-Control: max-age=600 * * AES_256_WITH_MD5 * 2 * base64-encoded peerCertificate[0] * base64-encoded peerCertificate[1] * -1 * * The file is newline separated. The first two lines are the URL and * the request method. Next is the number of HTTP Vary request header * lines, followed by those lines. * * Next is the response status line, followed by the number of HTTP * response header lines, followed by those lines. * * HTTPS responses also contain SSL session information. This begins * with a blank line, and then a line containing the cipher suite. Next * is the length of the peer certificate chain. These certificates are * base64-encoded and appear each on their own line. The next line * contains the length of the local certificate chain. These * certificates are also base64-encoded and appear each on their own * line. A length of -1 is used to encode a null array. */ public Entry(InputStream in) throws IOException { try { StrictLineReader reader = new StrictLineReader(in, Charsets.US_ASCII); uri = reader.readLine(); requestMethod = reader.readLine(); varyHeaders = new RawHeaders(); int varyRequestHeaderLineCount = reader.readInt(); for (int i = 0; i < varyRequestHeaderLineCount; i++) { varyHeaders.addLine(reader.readLine()); } responseHeaders = new RawHeaders(); responseHeaders.setStatusLine(reader.readLine()); int responseHeaderLineCount = reader.readInt(); for (int i = 0; i < responseHeaderLineCount; i++) { responseHeaders.addLine(reader.readLine()); } // if (isHttps()) { // String blank = reader.readLine(); // if (blank.length() != 0) { // throw new IOException("expected \"\" but was \"" + blank + "\""); // } // cipherSuite = reader.readLine(); // peerCertificates = readCertArray(reader); // localCertificates = readCertArray(reader); // } else { cipherSuite = null; peerCertificates = null; localCertificates = null; // } } finally { in.close(); } }
public void writeTo(DiskLruCache.Editor editor) throws IOException { OutputStream out = editor.newOutputStream(ENTRY_METADATA); Writer writer = new BufferedWriter(new OutputStreamWriter(out, Charsets.UTF_8)); writer.write(uri + '\n'); writer.write(requestMethod + '\n'); writer.write(Integer.toString(varyHeaders.length()) + '\n'); for (int i = 0; i < varyHeaders.length(); i++) { writer.write(varyHeaders.getFieldName(i) + ": " + varyHeaders.getValue(i) + '\n'); } writer.write(responseHeaders.getStatusLine() + '\n'); writer.write(Integer.toString(responseHeaders.length()) + '\n'); for (int i = 0; i < responseHeaders.length(); i++) { writer.write(responseHeaders.getFieldName(i) + ": " + responseHeaders.getValue(i) + '\n'); } if (isHttps()) { writer.write('\n'); writer.write(cipherSuite + '\n'); writeCertArray(writer, peerCertificates); writeCertArray(writer, localCertificates); } writer.close(); }
@Override public void onHeaders(RawHeaders headers) { if (headers.getResponseCode() == 401) { Log.e(TAG, "Refresh failed:\n" + headers.toHeaderString()); AccountManager am = AccountManager.get(mContext); if (am != null) { am.invalidateAuthToken("com.google", mAuthToken); } removeRnrse(); } }
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; }
public boolean matches( URI uri, String requestMethod, Map<String, List<String>> requestHeaders) { return this.uri.equals(uri.toString()) && this.requestMethod.equals(requestMethod) && new ResponseHeaders(uri, responseHeaders) .varyMatches(varyHeaders.toMultimap(), requestHeaders); }
public static AsyncHttpRequestBody getBody( DataEmitter emitter, CompletedCallback reporter, RawHeaders headers) { String contentType = headers.get("Content-Type"); if (contentType != null) { String[] values = contentType.split(";"); for (int i = 0; i < values.length; i++) { values[i] = values[i].trim(); } for (String ct : values) { if (UrlEncodedFormBody.CONTENT_TYPE.equals(ct)) { return new UrlEncodedFormBody(); } if (JSONObjectBody.CONTENT_TYPE.equals(ct)) { return new JSONObjectBody(); } if (StringBody.CONTENT_TYPE.equals(ct)) { return new StringBody(); } if (MultipartFormDataBody.CONTENT_TYPE.equals(ct)) { return new MultipartFormDataBody(contentType, values); } } } return null; }
@Override public void onStringAvailable(String s) { try { if (mRawHeaders.getStatusLine() == null) { mRawHeaders.setStatusLine(s); } else if (!"\r".equals(s)) { mRawHeaders.addLine(s); } else { mHeaders = new ResponseHeaders(mRequest.getUri(), mRawHeaders); onHeadersReceived(); // socket may get detached after headers (websocket) if (mSocket == null) return; DataEmitter emitter = Util.getBodyDecoder(mSocket, mRawHeaders, false, mReporter); setDataEmitter(emitter); } } catch (Exception ex) { report(ex); } }
public static DataEmitter getBodyDecoder( DataEmitter emitter, RawHeaders headers, boolean server) { long _contentLength; try { _contentLength = Long.parseLong(headers.get("Content-Length")); } catch (Exception ex) { _contentLength = -1; } final long contentLength = _contentLength; if (-1 != contentLength) { if (contentLength < 0) { EndEmitter ender = EndEmitter.create( emitter.getServer(), new BodyDecoderException( "not using chunked encoding, and no content-length found.")); ender.setDataEmitter(emitter); emitter = ender; return emitter; } if (contentLength == 0) { EndEmitter ender = EndEmitter.create(emitter.getServer(), null); ender.setDataEmitter(emitter); emitter = ender; return emitter; } ContentLengthFilter contentLengthWatcher = new ContentLengthFilter(contentLength); contentLengthWatcher.setDataEmitter(emitter); emitter = contentLengthWatcher; } else if ("chunked".equalsIgnoreCase(headers.get("Transfer-Encoding"))) { ChunkedInputFilter chunker = new ChunkedInputFilter(); chunker.setDataEmitter(emitter); emitter = chunker; } else { if ((server || headers.getStatusLine().contains("HTTP/1.1")) && !"close".equalsIgnoreCase(headers.get("Connection"))) { // if this is the server, and the client has not indicated a request body, the client is // done EndEmitter ender = EndEmitter.create(emitter.getServer(), null); ender.setDataEmitter(emitter); emitter = ender; return emitter; } } if ("gzip".equals(headers.get("Content-Encoding"))) { GZIPInputFilter gunzipper = new GZIPInputFilter(); gunzipper.setDataEmitter(emitter); emitter = gunzipper; } else if ("deflate".equals(headers.get("Content-Encoding"))) { InflaterInputFilter inflater = new InflaterInputFilter(); inflater.setDataEmitter(emitter); emitter = inflater; } // conversely, if this is the client (http 1.0), and the server has not indicated a request // body, we do not report // the close/end event until the server actually closes the connection. return emitter; }
// step 1) see if we can serve request from the cache directly. // also see if this can be turned into a conditional cache request. @Override public Cancellable getSocket(final GetSocketData data) { if (cache == null) return null; if (!caching) return null; if (data.request.getHeaders().isNoCache()) return null; // Log.i(LOGTAG, "getting cache socket: " + request.getUri().toString()); String key = uriToKey(data.request.getUri()); DiskLruCache.Snapshot snapshot; Entry entry; try { snapshot = cache.get(key); if (snapshot == null) { // Log.i(LOGTAG, "snapshot fail"); return null; } entry = new Entry(snapshot.getInputStream(ENTRY_METADATA)); } catch (IOException e) { // Give up because the cache cannot be read. return null; } if (!entry.matches( data.request.getUri(), data.request.getMethod(), data.request.getHeaders().getHeaders().toMultimap())) { snapshot.close(); return null; } ResponseSource responseSource = ResponseSource.NETWORK; CacheResponse candidate = entry.isHttps() ? new EntrySecureCacheResponse(entry, snapshot) : new EntryCacheResponse(entry, snapshot); Map<String, List<String>> responseHeadersMap; InputStream cachedResponseBody; try { responseHeadersMap = candidate.getHeaders(); cachedResponseBody = candidate.getBody(); } catch (Exception e) { return null; } if (responseHeadersMap == null || cachedResponseBody == null) { try { cachedResponseBody.close(); } catch (Exception e) { } return null; } RawHeaders rawResponseHeaders = RawHeaders.fromMultimap(responseHeadersMap); ResponseHeaders cachedResponseHeaders = new ResponseHeaders(data.request.getUri(), rawResponseHeaders); long now = System.currentTimeMillis(); responseSource = cachedResponseHeaders.chooseResponseSource(now, data.request.getHeaders()); if (responseSource == ResponseSource.CACHE) { cacheStoreCount++; final CachedSocket socket = entry.isHttps() ? new CachedSSLSocket((EntrySecureCacheResponse) candidate) : new CachedSocket((EntryCacheResponse) candidate); client .getServer() .post( new Runnable() { @Override public void run() { data.connectCallback.onConnectCompleted(null, socket); socket.spewInternal(); } }); } else if (responseSource == ResponseSource.CONDITIONAL_CACHE) { CacheData cacheData = new CacheData(); cacheData.cachedResponseHeaders = cachedResponseHeaders; cacheData.candidate = candidate; data.state.putParcelable("cache-data", cacheData); return null; } else { // NETWORK or other try { cachedResponseBody.close(); } catch (Exception e) { } return null; } return new SimpleCancelable(); }
protected AsyncHttpRequestBody onUnknownBody(RawHeaders headers) { return new UnknownRequestBody(headers.get("Content-Type")); }
@Override public AsyncHttpRequest createAsyncHttpRequest( URI uri, String method, RawHeaders headers) { if (!TextUtils.isEmpty(userAgent)) headers.set("User-Agent", userAgent); return new AsyncHttpRequest(uri, method, headers); }