mirror of
https://github.com/square/okhttp.git
synced 2026-01-25 16:01:38 +03:00
Merge pull request #384 from square/jwilson_1230_rename_raw_headers
Rename RawHeaders to Headers.
This commit is contained in:
@@ -72,14 +72,10 @@ public final class Util {
|
||||
return specifiedPort != -1 ? specifiedPort : getDefaultPort(scheme);
|
||||
}
|
||||
|
||||
public static int getDefaultPort(String scheme) {
|
||||
if ("http".equalsIgnoreCase(scheme)) {
|
||||
return 80;
|
||||
} else if ("https".equalsIgnoreCase(scheme)) {
|
||||
return 443;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
public static int getDefaultPort(String protocol) {
|
||||
if ("http".equals(protocol)) return 80;
|
||||
if ("https".equals(protocol)) return 443;
|
||||
return -1;
|
||||
}
|
||||
|
||||
public static void checkOffsetAndCount(int arrayLength, int offset, int count) {
|
||||
|
||||
@@ -310,7 +310,7 @@ public final class Connection implements Closeable {
|
||||
Request request = tunnelRequest.getRequest();
|
||||
String requestLine = tunnelRequest.requestLine();
|
||||
while (true) {
|
||||
out.write(request.rawHeaders().toBytes(requestLine));
|
||||
HttpTransport.writeRequest(out, request.headers(), requestLine);
|
||||
Response response = HttpTransport.readResponse(request, in).build();
|
||||
|
||||
switch (response.code()) {
|
||||
|
||||
@@ -20,7 +20,7 @@ import com.squareup.okhttp.internal.Base64;
|
||||
import com.squareup.okhttp.internal.DiskLruCache;
|
||||
import com.squareup.okhttp.internal.StrictLineReader;
|
||||
import com.squareup.okhttp.internal.Util;
|
||||
import com.squareup.okhttp.internal.http.RawHeaders;
|
||||
import com.squareup.okhttp.internal.http.Headers;
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.File;
|
||||
@@ -356,10 +356,10 @@ public final class HttpResponseCache extends ResponseCache implements OkResponse
|
||||
|
||||
private static final class Entry {
|
||||
private final String url;
|
||||
private final RawHeaders varyHeaders;
|
||||
private final Headers varyHeaders;
|
||||
private final String requestMethod;
|
||||
private final String statusLine;
|
||||
private final RawHeaders responseHeaders;
|
||||
private final Headers responseHeaders;
|
||||
private final Handshake handshake;
|
||||
|
||||
/**
|
||||
@@ -416,7 +416,7 @@ public final class HttpResponseCache extends ResponseCache implements OkResponse
|
||||
StrictLineReader reader = new StrictLineReader(in, US_ASCII);
|
||||
url = reader.readLine();
|
||||
requestMethod = reader.readLine();
|
||||
RawHeaders.Builder varyHeadersBuilder = new RawHeaders.Builder();
|
||||
Headers.Builder varyHeadersBuilder = new Headers.Builder();
|
||||
int varyRequestHeaderLineCount = reader.readInt();
|
||||
for (int i = 0; i < varyRequestHeaderLineCount; i++) {
|
||||
varyHeadersBuilder.addLine(reader.readLine());
|
||||
@@ -424,7 +424,7 @@ public final class HttpResponseCache extends ResponseCache implements OkResponse
|
||||
varyHeaders = varyHeadersBuilder.build();
|
||||
|
||||
statusLine = reader.readLine();
|
||||
RawHeaders.Builder responseHeadersBuilder = new RawHeaders.Builder();
|
||||
Headers.Builder responseHeadersBuilder = new Headers.Builder();
|
||||
int responseHeaderLineCount = reader.readInt();
|
||||
for (int i = 0; i < responseHeaderLineCount; i++) {
|
||||
responseHeadersBuilder.addLine(reader.readLine());
|
||||
@@ -450,10 +450,10 @@ public final class HttpResponseCache extends ResponseCache implements OkResponse
|
||||
|
||||
public Entry(Response response) {
|
||||
this.url = response.request().urlString();
|
||||
this.varyHeaders = response.request().rawHeaders().getAll(response.getVaryFields());
|
||||
this.varyHeaders = response.request().headers().getAll(response.getVaryFields());
|
||||
this.requestMethod = response.request().method();
|
||||
this.statusLine = response.statusLine();
|
||||
this.responseHeaders = response.rawHeaders();
|
||||
this.responseHeaders = response.headers();
|
||||
this.handshake = response.handshake();
|
||||
}
|
||||
|
||||
@@ -529,7 +529,7 @@ public final class HttpResponseCache extends ResponseCache implements OkResponse
|
||||
String contentLength = responseHeaders.get("Content-Length");
|
||||
return new Response.Builder(request)
|
||||
.statusLine(statusLine)
|
||||
.rawHeaders(responseHeaders)
|
||||
.headers(responseHeaders)
|
||||
.body(new CacheResponseBody(snapshot, contentType, contentLength))
|
||||
.handshake(handshake)
|
||||
.build();
|
||||
|
||||
@@ -18,8 +18,8 @@ package com.squareup.okhttp;
|
||||
import com.squareup.okhttp.internal.Platform;
|
||||
import com.squareup.okhttp.internal.Util;
|
||||
import com.squareup.okhttp.internal.http.HeaderParser;
|
||||
import com.squareup.okhttp.internal.http.Headers;
|
||||
import com.squareup.okhttp.internal.http.HttpDate;
|
||||
import com.squareup.okhttp.internal.http.RawHeaders;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
@@ -45,7 +45,7 @@ import java.util.Set;
|
||||
public final class Request {
|
||||
private final URL url;
|
||||
private final String method;
|
||||
private final RawHeaders headers;
|
||||
private final Headers headers;
|
||||
private final Body body;
|
||||
private final Object tag;
|
||||
|
||||
@@ -93,7 +93,7 @@ public final class Request {
|
||||
return headers.names();
|
||||
}
|
||||
|
||||
RawHeaders rawHeaders() {
|
||||
Headers headers() {
|
||||
return headers;
|
||||
}
|
||||
|
||||
@@ -120,7 +120,7 @@ public final class Request {
|
||||
public Builder newBuilder() {
|
||||
return new Builder(url)
|
||||
.method(method, body)
|
||||
.rawHeaders(headers)
|
||||
.headers(headers)
|
||||
.tag(tag);
|
||||
}
|
||||
|
||||
@@ -132,7 +132,7 @@ public final class Request {
|
||||
return "close".equalsIgnoreCase(parsedHeaders().connection);
|
||||
}
|
||||
|
||||
public RawHeaders getHeaders() {
|
||||
public Headers getHeaders() {
|
||||
return headers;
|
||||
}
|
||||
|
||||
@@ -255,7 +255,7 @@ public final class Request {
|
||||
private String ifNoneMatch;
|
||||
private String proxyAuthorization;
|
||||
|
||||
public ParsedHeaders(RawHeaders headers) {
|
||||
public ParsedHeaders(Headers headers) {
|
||||
HeaderParser.CacheControlHandler handler = new HeaderParser.CacheControlHandler() {
|
||||
@Override public void handle(String directive, String parameter) {
|
||||
if ("no-cache".equalsIgnoreCase(directive)) {
|
||||
@@ -398,7 +398,7 @@ public final class Request {
|
||||
public static class Builder {
|
||||
private URL url;
|
||||
private String method = "GET";
|
||||
private RawHeaders.Builder headers = new RawHeaders.Builder();
|
||||
private Headers.Builder headers = new Headers.Builder();
|
||||
private Body body;
|
||||
private Object tag;
|
||||
|
||||
@@ -444,8 +444,8 @@ public final class Request {
|
||||
}
|
||||
|
||||
// TODO: this shouldn't be public.
|
||||
public Builder rawHeaders(RawHeaders rawHeaders) {
|
||||
headers = rawHeaders.newBuilder();
|
||||
public Builder headers(Headers headers) {
|
||||
this.headers = headers.newBuilder();
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
@@ -18,8 +18,8 @@ package com.squareup.okhttp;
|
||||
import com.squareup.okhttp.internal.Platform;
|
||||
import com.squareup.okhttp.internal.Util;
|
||||
import com.squareup.okhttp.internal.http.HeaderParser;
|
||||
import com.squareup.okhttp.internal.http.Headers;
|
||||
import com.squareup.okhttp.internal.http.HttpDate;
|
||||
import com.squareup.okhttp.internal.http.RawHeaders;
|
||||
import com.squareup.okhttp.internal.http.StatusLine;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.Closeable;
|
||||
@@ -65,7 +65,7 @@ public final class Response {
|
||||
private final Request request;
|
||||
private final StatusLine statusLine;
|
||||
private final Handshake handshake;
|
||||
private final RawHeaders headers;
|
||||
private final Headers headers;
|
||||
private final Body body;
|
||||
private final Response redirectedBy;
|
||||
|
||||
@@ -146,7 +146,7 @@ public final class Response {
|
||||
}
|
||||
|
||||
// TODO: this shouldn't be public.
|
||||
public RawHeaders rawHeaders() {
|
||||
public Headers headers() {
|
||||
return headers;
|
||||
}
|
||||
|
||||
@@ -162,7 +162,7 @@ public final class Response {
|
||||
return new Builder(request)
|
||||
.statusLine(statusLine)
|
||||
.handshake(handshake)
|
||||
.rawHeaders(headers)
|
||||
.headers(headers)
|
||||
.body(body)
|
||||
.redirectedBy(redirectedBy);
|
||||
}
|
||||
@@ -189,10 +189,6 @@ public final class Response {
|
||||
return "close".equalsIgnoreCase(parsedHeaders().connection);
|
||||
}
|
||||
|
||||
public RawHeaders getHeaders() {
|
||||
return headers;
|
||||
}
|
||||
|
||||
public Date getServedDate() {
|
||||
return parsedHeaders().servedDate;
|
||||
}
|
||||
@@ -267,7 +263,7 @@ public final class Response {
|
||||
* Returns true if none of the Vary headers on this response have changed
|
||||
* between {@code cachedRequest} and {@code newRequest}.
|
||||
*/
|
||||
public boolean varyMatches(RawHeaders varyHeaders, Request newRequest) {
|
||||
public boolean varyMatches(Headers varyHeaders, Request newRequest) {
|
||||
for (String field : parsedHeaders().varyFields) {
|
||||
if (!equal(varyHeaders.values(field), newRequest.headers(field))) return false;
|
||||
}
|
||||
@@ -301,7 +297,7 @@ public final class Response {
|
||||
* 13.5.3.
|
||||
*/
|
||||
public Response combine(Response network) throws IOException {
|
||||
RawHeaders.Builder result = new RawHeaders.Builder();
|
||||
Headers.Builder result = new Headers.Builder();
|
||||
|
||||
for (int i = 0; i < headers.length(); i++) {
|
||||
String fieldName = headers.getFieldName(i);
|
||||
@@ -321,7 +317,7 @@ public final class Response {
|
||||
}
|
||||
}
|
||||
|
||||
return newBuilder().rawHeaders(result.build()).build();
|
||||
return newBuilder().headers(result.build()).build();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -506,7 +502,7 @@ public final class Response {
|
||||
private String connection;
|
||||
private String contentType;
|
||||
|
||||
private ParsedHeaders(RawHeaders headers) {
|
||||
private ParsedHeaders(Headers headers) {
|
||||
HeaderParser.CacheControlHandler handler = new HeaderParser.CacheControlHandler() {
|
||||
@Override public void handle(String directive, String parameter) {
|
||||
if ("no-cache".equalsIgnoreCase(directive)) {
|
||||
@@ -619,7 +615,7 @@ public final class Response {
|
||||
private final Request request;
|
||||
private StatusLine statusLine;
|
||||
private Handshake handshake;
|
||||
private RawHeaders.Builder headers = new RawHeaders.Builder();
|
||||
private Headers.Builder headers = new Headers.Builder();
|
||||
private Body body;
|
||||
private Response redirectedBy;
|
||||
|
||||
@@ -666,8 +662,8 @@ public final class Response {
|
||||
}
|
||||
|
||||
// TODO: this shouldn't be public.
|
||||
public Builder rawHeaders(RawHeaders rawHeaders) {
|
||||
headers = rawHeaders.newBuilder();
|
||||
public Builder headers(Headers headers) {
|
||||
this.headers = headers.newBuilder();
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
@@ -20,13 +20,10 @@ package com.squareup.okhttp.internal.http;
|
||||
import com.squareup.okhttp.internal.Util;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.TreeMap;
|
||||
@@ -48,7 +45,7 @@ import java.util.TreeSet;
|
||||
* <p>This class trims whitespace from values. It never returns values with
|
||||
* leading or trailing whitespace.
|
||||
*/
|
||||
public final class RawHeaders {
|
||||
public final class Headers {
|
||||
private static final Comparator<String> FIELD_NAME_COMPARATOR = new Comparator<String>() {
|
||||
// @FindBugsSuppressWarnings("ES_COMPARING_PARAMETER_STRING_WITH_EQ")
|
||||
@Override public int compare(String a, String b) {
|
||||
@@ -66,7 +63,7 @@ public final class RawHeaders {
|
||||
|
||||
private final List<String> namesAndValues;
|
||||
|
||||
private RawHeaders(Builder builder) {
|
||||
private Headers(Builder builder) {
|
||||
this.namesAndValues = Util.immutableList(builder.namesAndValues);
|
||||
}
|
||||
|
||||
@@ -122,7 +119,7 @@ public final class RawHeaders {
|
||||
}
|
||||
|
||||
/** @param fieldNames a case-insensitive set of HTTP header field names. */
|
||||
public RawHeaders getAll(Set<String> fieldNames) {
|
||||
public Headers getAll(Set<String> fieldNames) {
|
||||
Builder result = new Builder();
|
||||
for (int i = 0; i < namesAndValues.size(); i += 2) {
|
||||
String fieldName = namesAndValues.get(i);
|
||||
@@ -133,20 +130,6 @@ public final class RawHeaders {
|
||||
return result.build();
|
||||
}
|
||||
|
||||
/** Returns bytes of a request header for sending on an HTTP transport. */
|
||||
public byte[] toBytes(String requestLine) throws UnsupportedEncodingException {
|
||||
StringBuilder result = new StringBuilder(256);
|
||||
result.append(requestLine).append("\r\n");
|
||||
for (int i = 0; i < namesAndValues.size(); i += 2) {
|
||||
result.append(namesAndValues.get(i))
|
||||
.append(": ")
|
||||
.append(namesAndValues.get(i + 1))
|
||||
.append("\r\n");
|
||||
}
|
||||
result.append("\r\n");
|
||||
return result.toString().getBytes("ISO-8859-1");
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an immutable map containing each field to its list of values.
|
||||
*
|
||||
@@ -173,45 +156,6 @@ public final class RawHeaders {
|
||||
return Collections.unmodifiableMap(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of alternating names and values. Names are all lower case.
|
||||
* No names are repeated. If any name has multiple values, they are
|
||||
* concatenated using "\0" as a delimiter.
|
||||
*/
|
||||
public List<String> toNameValueBlock() {
|
||||
Set<String> names = new HashSet<String>();
|
||||
List<String> result = new ArrayList<String>();
|
||||
for (int i = 0; i < namesAndValues.size(); i += 2) {
|
||||
String name = namesAndValues.get(i).toLowerCase(Locale.US);
|
||||
String value = namesAndValues.get(i + 1);
|
||||
|
||||
// Drop headers that are forbidden when layering HTTP over SPDY.
|
||||
if (name.equals("connection")
|
||||
|| name.equals("host")
|
||||
|| name.equals("keep-alive")
|
||||
|| name.equals("proxy-connection")
|
||||
|| name.equals("transfer-encoding")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// If we haven't seen this name before, add the pair to the end of the list...
|
||||
if (names.add(name)) {
|
||||
result.add(name);
|
||||
result.add(value);
|
||||
continue;
|
||||
}
|
||||
|
||||
// ...otherwise concatenate the existing values and this value.
|
||||
for (int j = 0; j < result.size(); j += 2) {
|
||||
if (name.equals(result.get(j))) {
|
||||
result.set(j + 1, result.get(j + 1) + "\0" + value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public Builder newBuilder() {
|
||||
Builder result = new Builder();
|
||||
result.namesAndValues.addAll(namesAndValues);
|
||||
@@ -232,7 +176,7 @@ public final class RawHeaders {
|
||||
|
||||
/** Equivalent to {@code build().get(fieldName)}, but potentially faster. */
|
||||
public String get(String fieldName) {
|
||||
return RawHeaders.get(namesAndValues, fieldName);
|
||||
return Headers.get(namesAndValues, fieldName);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -300,8 +244,8 @@ public final class RawHeaders {
|
||||
return this;
|
||||
}
|
||||
|
||||
public RawHeaders build() {
|
||||
return new RawHeaders(this);
|
||||
public Headers build() {
|
||||
return new Headers(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -102,7 +102,7 @@ public final class HttpAuthenticator {
|
||||
} else {
|
||||
throw new IllegalArgumentException(); // TODO: ProtocolException?
|
||||
}
|
||||
List<Challenge> challenges = parseChallenges(response.rawHeaders(), responseField);
|
||||
List<Challenge> challenges = parseChallenges(response.headers(), responseField);
|
||||
if (challenges.isEmpty()) return null; // Could not find a challenge so end the request cycle.
|
||||
|
||||
Request request = response.request();
|
||||
@@ -119,7 +119,7 @@ public final class HttpAuthenticator {
|
||||
* Parse RFC 2617 challenges. This API is only interested in the scheme
|
||||
* name and realm.
|
||||
*/
|
||||
private static List<Challenge> parseChallenges(RawHeaders responseHeaders,
|
||||
private static List<Challenge> parseChallenges(Headers responseHeaders,
|
||||
String challengeHeader) {
|
||||
// auth-scheme = token
|
||||
// auth-param = token "=" ( token | quoted-string )
|
||||
|
||||
@@ -19,7 +19,6 @@ package com.squareup.okhttp.internal.http;
|
||||
|
||||
import com.squareup.okhttp.Address;
|
||||
import com.squareup.okhttp.Connection;
|
||||
import com.squareup.okhttp.Handshake;
|
||||
import com.squareup.okhttp.MediaType;
|
||||
import com.squareup.okhttp.OkHttpClient;
|
||||
import com.squareup.okhttp.OkResponseCache;
|
||||
@@ -336,17 +335,8 @@ public class HttpEngine {
|
||||
return response;
|
||||
}
|
||||
|
||||
public final int getResponseCode() {
|
||||
if (response == null) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
return response.code();
|
||||
}
|
||||
|
||||
public final InputStream getResponseBody() {
|
||||
if (response == null) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
if (response == null) throw new IllegalStateException();
|
||||
return responseBodyIn;
|
||||
}
|
||||
|
||||
@@ -434,13 +424,12 @@ public class HttpEngine {
|
||||
* See RFC 2616 section 4.3.
|
||||
*/
|
||||
public final boolean hasResponseBody() {
|
||||
int responseCode = response.code();
|
||||
|
||||
// HEAD requests never yield a body regardless of the response headers.
|
||||
if (request.method().equals("HEAD")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int responseCode = response.code();
|
||||
if ((responseCode < HTTP_CONTINUE || responseCode >= 200)
|
||||
&& responseCode != HTTP_NO_CONTENT
|
||||
&& responseCode != HTTP_NOT_MODIFIED) {
|
||||
@@ -471,7 +460,7 @@ public class HttpEngine {
|
||||
}
|
||||
|
||||
if (request.getHost() == null) {
|
||||
result.setHost(getOriginAddress(request.url()));
|
||||
result.setHost(getHostHeader(request.url()));
|
||||
}
|
||||
|
||||
if ((connection == null || connection.getHttpMinorVersion() != 0)
|
||||
@@ -496,26 +485,15 @@ public class HttpEngine {
|
||||
request = result.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the TLS handshake created when this engine connected, or null if
|
||||
* no TLS connection was made.
|
||||
*/
|
||||
public Handshake getHandshake() {
|
||||
return response.handshake();
|
||||
}
|
||||
|
||||
public static String getDefaultUserAgent() {
|
||||
String agent = System.getProperty("http.agent");
|
||||
return agent != null ? agent : ("Java" + System.getProperty("java.version"));
|
||||
}
|
||||
|
||||
public static String getOriginAddress(URL url) {
|
||||
int port = url.getPort();
|
||||
String result = url.getHost();
|
||||
if (port > 0 && port != getDefaultPort(url.getProtocol())) {
|
||||
result = result + ":" + port;
|
||||
}
|
||||
return result;
|
||||
public static String getHostHeader(URL url) {
|
||||
return getEffectivePort(url) != getDefaultPort(url.getProtocol())
|
||||
? url.getHost() + ":" + url.getPort()
|
||||
: url.getHost();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -524,6 +502,7 @@ public class HttpEngine {
|
||||
*/
|
||||
public final void readResponse() throws IOException {
|
||||
if (hasResponse()) {
|
||||
// TODO: this doesn't make much sense.
|
||||
response = response.newBuilder().setResponseSource(responseSource).build();
|
||||
return;
|
||||
}
|
||||
@@ -599,7 +578,7 @@ public class HttpEngine {
|
||||
request.getProxyAuthorization());
|
||||
}
|
||||
|
||||
public void receiveHeaders(RawHeaders headers) throws IOException {
|
||||
public void receiveHeaders(Headers headers) throws IOException {
|
||||
CookieHandler cookieHandler = client.getCookieHandler();
|
||||
if (cookieHandler != null) {
|
||||
cookieHandler.put(request.uri(), headers.toMultimap(null));
|
||||
|
||||
@@ -135,12 +135,11 @@ public final class HttpTransport implements Transport {
|
||||
*/
|
||||
public void writeRequestHeaders() throws IOException {
|
||||
httpEngine.writingRequestHeaders();
|
||||
RawHeaders headersToSend = httpEngine.getRequest().getHeaders();
|
||||
Headers headersToSend = httpEngine.getRequest().getHeaders();
|
||||
String requestLine = RequestLine.get(httpEngine.getRequest(),
|
||||
httpEngine.connection.getRoute().getProxy().type(),
|
||||
httpEngine.connection.getHttpMinorVersion());
|
||||
byte[] bytes = headersToSend.toBytes(requestLine);
|
||||
requestOut.write(bytes);
|
||||
writeRequest(requestOut, headersToSend, requestLine);
|
||||
}
|
||||
|
||||
@Override public Response readResponseHeaders() throws IOException {
|
||||
@@ -148,10 +147,25 @@ public final class HttpTransport implements Transport {
|
||||
.handshake(httpEngine.connection.getHandshake())
|
||||
.build();
|
||||
httpEngine.connection.setHttpMinorVersion(response.httpMinorVersion());
|
||||
httpEngine.receiveHeaders(response.rawHeaders());
|
||||
httpEngine.receiveHeaders(response.headers());
|
||||
return response;
|
||||
}
|
||||
|
||||
/** Returns bytes of a request header for sending on an HTTP transport. */
|
||||
public static void writeRequest(OutputStream out, Headers headers, String requestLine)
|
||||
throws IOException {
|
||||
StringBuilder result = new StringBuilder(256);
|
||||
result.append(requestLine).append("\r\n");
|
||||
for (int i = 0; i < headers.length(); i ++) {
|
||||
result.append(headers.getFieldName(i))
|
||||
.append(": ")
|
||||
.append(headers.getValue(i))
|
||||
.append("\r\n");
|
||||
}
|
||||
result.append("\r\n");
|
||||
out.write(result.toString().getBytes("ISO-8859-1"));
|
||||
}
|
||||
|
||||
/** Parses bytes of a response header from an HTTP transport. */
|
||||
public static Response.Builder readResponse(Request request, InputStream in) throws IOException {
|
||||
while (true) {
|
||||
@@ -162,9 +176,9 @@ public final class HttpTransport implements Transport {
|
||||
responseBuilder.statusLine(statusLine);
|
||||
responseBuilder.header(Response.SELECTED_TRANSPORT, "http/1.1");
|
||||
|
||||
RawHeaders.Builder headersBuilder = new RawHeaders.Builder();
|
||||
Headers.Builder headersBuilder = new Headers.Builder();
|
||||
headersBuilder.readHeaders(in);
|
||||
responseBuilder.rawHeaders(headersBuilder.build());
|
||||
responseBuilder.headers(headersBuilder.build());
|
||||
|
||||
if (statusLine.code() != HTTP_CONTINUE) return responseBuilder;
|
||||
}
|
||||
@@ -498,7 +512,7 @@ public final class HttpTransport implements Transport {
|
||||
}
|
||||
if (bytesRemainingInChunk == 0) {
|
||||
hasMoreChunks = false;
|
||||
RawHeaders trailers = new RawHeaders.Builder()
|
||||
Headers trailers = new Headers.Builder()
|
||||
.readHeaders(transport.socketIn)
|
||||
.build();
|
||||
httpEngine.receiveHeaders(trailers);
|
||||
|
||||
@@ -69,7 +69,7 @@ public class HttpURLConnectionImpl extends HttpURLConnection implements Policy {
|
||||
|
||||
final OkHttpClient client;
|
||||
|
||||
private RawHeaders.Builder requestHeaders = new RawHeaders.Builder();
|
||||
private Headers.Builder requestHeaders = new Headers.Builder();
|
||||
|
||||
/** Like the superclass field of the same name, but a long and available on all platforms. */
|
||||
private long fixedContentLength = -1;
|
||||
@@ -113,7 +113,7 @@ public class HttpURLConnectionImpl extends HttpURLConnection implements Policy {
|
||||
@Override public final InputStream getErrorStream() {
|
||||
try {
|
||||
HttpEngine response = getResponse();
|
||||
if (response.hasResponseBody() && response.getResponseCode() >= HTTP_BAD_REQUEST) {
|
||||
if (response.hasResponseBody() && response.getResponse().code() >= HTTP_BAD_REQUEST) {
|
||||
return response.getResponseBody();
|
||||
}
|
||||
return null;
|
||||
@@ -128,7 +128,7 @@ public class HttpURLConnectionImpl extends HttpURLConnection implements Policy {
|
||||
*/
|
||||
@Override public final String getHeaderField(int position) {
|
||||
try {
|
||||
return getResponse().getResponse().getHeaders().getValue(position);
|
||||
return getResponse().getResponse().headers().getValue(position);
|
||||
} catch (IOException e) {
|
||||
return null;
|
||||
}
|
||||
@@ -142,7 +142,7 @@ public class HttpURLConnectionImpl extends HttpURLConnection implements Policy {
|
||||
@Override public final String getHeaderField(String fieldName) {
|
||||
try {
|
||||
Response response = getResponse().getResponse();
|
||||
return fieldName == null ? response.statusLine() : response.getHeaders().get(fieldName);
|
||||
return fieldName == null ? response.statusLine() : response.headers().get(fieldName);
|
||||
} catch (IOException e) {
|
||||
return null;
|
||||
}
|
||||
@@ -150,7 +150,7 @@ public class HttpURLConnectionImpl extends HttpURLConnection implements Policy {
|
||||
|
||||
@Override public final String getHeaderFieldKey(int position) {
|
||||
try {
|
||||
return getResponse().getResponse().getHeaders().getFieldName(position);
|
||||
return getResponse().getResponse().headers().getFieldName(position);
|
||||
} catch (IOException e) {
|
||||
return null;
|
||||
}
|
||||
@@ -159,7 +159,7 @@ public class HttpURLConnectionImpl extends HttpURLConnection implements Policy {
|
||||
@Override public final Map<String, List<String>> getHeaderFields() {
|
||||
try {
|
||||
Response response = getResponse().getResponse();
|
||||
return response.getHeaders().toMultimap(response.statusLine());
|
||||
return response.headers().toMultimap(response.statusLine());
|
||||
} catch (IOException e) {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
@@ -273,7 +273,7 @@ public class HttpURLConnectionImpl extends HttpURLConnection implements Policy {
|
||||
RetryableOutputStream requestBody) throws IOException {
|
||||
Request request = new Request.Builder(getURL())
|
||||
.method(method, null) // No body: that's provided later!
|
||||
.rawHeaders(requestHeaders.build())
|
||||
.headers(requestHeaders.build())
|
||||
.build();
|
||||
|
||||
// If we're currently not using caches, make sure the engine's client doesn't have one.
|
||||
@@ -315,7 +315,7 @@ public class HttpURLConnectionImpl extends HttpURLConnection implements Policy {
|
||||
// Although RFC 2616 10.3.2 specifies that a HTTP_MOVED_PERM
|
||||
// redirect should keep the same method, Chrome, Firefox and the
|
||||
// RI all issue GETs when following any redirect.
|
||||
int responseCode = httpEngine.getResponseCode();
|
||||
int responseCode = httpEngine.getResponse().code();
|
||||
if (responseCode == HTTP_MULT_CHOICE
|
||||
|| responseCode == HTTP_MOVED_PERM
|
||||
|| responseCode == HTTP_MOVED_TEMP
|
||||
@@ -501,7 +501,7 @@ public class HttpURLConnectionImpl extends HttpURLConnection implements Policy {
|
||||
}
|
||||
|
||||
@Override public final int getResponseCode() throws IOException {
|
||||
return getResponse().getResponseCode();
|
||||
return getResponse().getResponse().code();
|
||||
}
|
||||
|
||||
@Override public final void setRequestProperty(String field, String newValue) {
|
||||
|
||||
@@ -76,7 +76,7 @@ public final class HttpsURLConnectionImpl extends HttpsURLConnection {
|
||||
if (delegate.httpEngine == null) {
|
||||
throw new IllegalStateException("Connection has not yet been established");
|
||||
}
|
||||
return delegate.httpEngine.getHandshake();
|
||||
return delegate.httpEngine.getResponse().handshake();
|
||||
}
|
||||
|
||||
@Override public void disconnect() {
|
||||
|
||||
@@ -27,7 +27,11 @@ import java.io.OutputStream;
|
||||
import java.net.CacheRequest;
|
||||
import java.net.ProtocolException;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
|
||||
public final class SpdyTransport implements Transport {
|
||||
private final HttpEngine httpEngine;
|
||||
@@ -45,7 +49,7 @@ public final class SpdyTransport implements Transport {
|
||||
String version = RequestLine.version(httpEngine.connection.getHttpMinorVersion());
|
||||
URL url = request.url();
|
||||
builder.addSpdyRequestHeaders(request.method(), RequestLine.requestPath(url), version,
|
||||
HttpEngine.getOriginAddress(url), httpEngine.getRequest().url().getProtocol());
|
||||
HttpEngine.getHostHeader(url), httpEngine.getRequest().url().getProtocol());
|
||||
|
||||
if (httpEngine.hasRequestBody()) {
|
||||
long fixedContentLength = httpEngine.policy.getFixedContentLength();
|
||||
@@ -69,7 +73,7 @@ public final class SpdyTransport implements Transport {
|
||||
httpEngine.writingRequestHeaders();
|
||||
boolean hasRequestBody = httpEngine.hasRequestBody();
|
||||
boolean hasResponseBody = true;
|
||||
stream = spdyConnection.newStream(httpEngine.getRequest().getHeaders().toNameValueBlock(),
|
||||
stream = spdyConnection.newStream(writeNameValueBlock(httpEngine.getRequest().getHeaders()),
|
||||
hasRequestBody, hasResponseBody);
|
||||
stream.setReadTimeout(httpEngine.client.getReadTimeout());
|
||||
}
|
||||
@@ -88,10 +92,49 @@ public final class SpdyTransport implements Transport {
|
||||
.handshake(httpEngine.connection.getHandshake())
|
||||
.build();
|
||||
httpEngine.connection.setHttpMinorVersion(response.httpMinorVersion());
|
||||
httpEngine.receiveHeaders(response.rawHeaders());
|
||||
httpEngine.receiveHeaders(response.headers());
|
||||
return response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of alternating names and values containing a SPDY request.
|
||||
* Names are all lower case. No names are repeated. If any name has multiple
|
||||
* values, they are concatenated using "\0" as a delimiter.
|
||||
*/
|
||||
public static List<String> writeNameValueBlock(Headers headers) {
|
||||
Set<String> names = new HashSet<String>();
|
||||
List<String> result = new ArrayList<String>();
|
||||
for (int i = 0; i < headers.length(); i++) {
|
||||
String name = headers.getFieldName(i).toLowerCase(Locale.US);
|
||||
String value = headers.getValue(i);
|
||||
|
||||
// Drop headers that are forbidden when layering HTTP over SPDY.
|
||||
if (name.equals("connection")
|
||||
|| name.equals("host")
|
||||
|| name.equals("keep-alive")
|
||||
|| name.equals("proxy-connection")
|
||||
|| name.equals("transfer-encoding")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// If we haven't seen this name before, add the pair to the end of the list...
|
||||
if (names.add(name)) {
|
||||
result.add(name);
|
||||
result.add(value);
|
||||
continue;
|
||||
}
|
||||
|
||||
// ...otherwise concatenate the existing values and this value.
|
||||
for (int j = 0; j < result.size(); j += 2) {
|
||||
if (name.equals(result.get(j))) {
|
||||
result.set(j + 1, result.get(j + 1) + "\0" + value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/** Returns headers for a name value block containing a SPDY response. */
|
||||
public static Response.Builder readNameValueBlock(Request request, List<String> nameValueBlock)
|
||||
throws IOException {
|
||||
@@ -101,7 +144,7 @@ public final class SpdyTransport implements Transport {
|
||||
String status = null;
|
||||
String version = null;
|
||||
|
||||
RawHeaders.Builder headersBuilder = new RawHeaders.Builder();
|
||||
Headers.Builder headersBuilder = new Headers.Builder();
|
||||
headersBuilder.set(Response.SELECTED_TRANSPORT, "spdy/3");
|
||||
for (int i = 0; i < nameValueBlock.size(); i += 2) {
|
||||
String name = nameValueBlock.get(i);
|
||||
@@ -127,7 +170,7 @@ public final class SpdyTransport implements Transport {
|
||||
|
||||
return new Response.Builder(request)
|
||||
.statusLine(new StatusLine(version + " " + status))
|
||||
.rawHeaders(headersBuilder.build());
|
||||
.headers(headersBuilder.build());
|
||||
}
|
||||
|
||||
@Override public InputStream getTransferStream(CacheRequest cacheRequest) throws IOException {
|
||||
|
||||
@@ -25,7 +25,7 @@ import org.junit.Test;
|
||||
import static junit.framework.Assert.assertNull;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
public final class RawHeadersTest {
|
||||
public final class HeadersTest {
|
||||
@Test public void parseNameValueBlock() throws IOException {
|
||||
List<String> nameValueBlock = Arrays.asList(
|
||||
"cache-control", "no-cache, no-store",
|
||||
@@ -34,31 +34,31 @@ public final class RawHeadersTest {
|
||||
":version", "HTTP/1.1");
|
||||
Request request = new Request.Builder("http://square.com/").build();
|
||||
Response response = SpdyTransport.readNameValueBlock(request, nameValueBlock).build();
|
||||
RawHeaders rawHeaders = response.rawHeaders();
|
||||
assertEquals(4, rawHeaders.length());
|
||||
Headers headers = response.headers();
|
||||
assertEquals(4, headers.length());
|
||||
assertEquals("HTTP/1.1 200 OK", response.statusLine());
|
||||
assertEquals("no-cache, no-store", rawHeaders.get("cache-control"));
|
||||
assertEquals("Cookie2", rawHeaders.get("set-cookie"));
|
||||
assertEquals("spdy/3", rawHeaders.get(Response.SELECTED_TRANSPORT));
|
||||
assertEquals(Response.SELECTED_TRANSPORT, rawHeaders.getFieldName(0));
|
||||
assertEquals("spdy/3", rawHeaders.getValue(0));
|
||||
assertEquals("cache-control", rawHeaders.getFieldName(1));
|
||||
assertEquals("no-cache, no-store", rawHeaders.getValue(1));
|
||||
assertEquals("set-cookie", rawHeaders.getFieldName(2));
|
||||
assertEquals("Cookie1", rawHeaders.getValue(2));
|
||||
assertEquals("set-cookie", rawHeaders.getFieldName(3));
|
||||
assertEquals("Cookie2", rawHeaders.getValue(3));
|
||||
assertNull(rawHeaders.get(":status"));
|
||||
assertNull(rawHeaders.get(":version"));
|
||||
assertEquals("no-cache, no-store", headers.get("cache-control"));
|
||||
assertEquals("Cookie2", headers.get("set-cookie"));
|
||||
assertEquals("spdy/3", headers.get(Response.SELECTED_TRANSPORT));
|
||||
assertEquals(Response.SELECTED_TRANSPORT, headers.getFieldName(0));
|
||||
assertEquals("spdy/3", headers.getValue(0));
|
||||
assertEquals("cache-control", headers.getFieldName(1));
|
||||
assertEquals("no-cache, no-store", headers.getValue(1));
|
||||
assertEquals("set-cookie", headers.getFieldName(2));
|
||||
assertEquals("Cookie1", headers.getValue(2));
|
||||
assertEquals("set-cookie", headers.getFieldName(3));
|
||||
assertEquals("Cookie2", headers.getValue(3));
|
||||
assertNull(headers.get(":status"));
|
||||
assertNull(headers.get(":version"));
|
||||
}
|
||||
|
||||
@Test public void toNameValueBlock() {
|
||||
RawHeaders.Builder builder = new RawHeaders.Builder();
|
||||
Headers.Builder builder = new Headers.Builder();
|
||||
builder.add("cache-control", "no-cache, no-store");
|
||||
builder.add("set-cookie", "Cookie1");
|
||||
builder.add("set-cookie", "Cookie2");
|
||||
builder.add(":status", "200 OK");
|
||||
List<String> nameValueBlock = builder.build().toNameValueBlock();
|
||||
List<String> nameValueBlock = SpdyTransport.writeNameValueBlock(builder.build());
|
||||
List<String> expected = Arrays.asList(
|
||||
"cache-control", "no-cache, no-store",
|
||||
"set-cookie", "Cookie1\u0000Cookie2",
|
||||
@@ -67,9 +67,9 @@ public final class RawHeadersTest {
|
||||
}
|
||||
|
||||
@Test public void toNameValueBlockDropsForbiddenHeaders() {
|
||||
RawHeaders.Builder builder = new RawHeaders.Builder();
|
||||
Headers.Builder builder = new Headers.Builder();
|
||||
builder.add("Connection", "close");
|
||||
builder.add("Transfer-Encoding", "chunked");
|
||||
assertEquals(Arrays.<String>asList(), builder.build().toNameValueBlock());
|
||||
assertEquals(Arrays.<String>asList(), SpdyTransport.writeNameValueBlock(builder.build()));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user