Skip to content

Commit

Permalink
Merge pull request square#1270 from square/jw/mock-web-headers
Browse files Browse the repository at this point in the history
Update MockWebServer to use Headers.
  • Loading branch information
JakeWharton committed Jan 5, 2015
2 parents ddbf236 + 8e20129 commit 6763803
Show file tree
Hide file tree
Showing 10 changed files with 118 additions and 107 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@
*/
package com.squareup.okhttp.mockwebserver;

import com.squareup.okhttp.Headers;
import com.squareup.okhttp.internal.ws.WebSocketListener;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.TimeUnit;
import okio.Buffer;
Expand All @@ -27,7 +27,7 @@ public final class MockResponse implements Cloneable {
private static final String CHUNKED_BODY_HEADER = "Transfer-encoding: chunked";

private String status = "HTTP/1.1 200 OK";
private List<String> headers = new ArrayList<>();
private Headers.Builder headers = new Headers.Builder();

private Buffer body;

Expand All @@ -50,7 +50,7 @@ public MockResponse() {
@Override public MockResponse clone() {
try {
MockResponse result = (MockResponse) super.clone();
result.headers = new ArrayList<>(headers);
result.headers = headers.build().newBuilder();
result.promises = new ArrayList<>(promises);
return result;
} catch (CloneNotSupportedException e) {
Expand All @@ -74,15 +74,25 @@ public MockResponse setStatus(String status) {

/** Returns the HTTP headers, such as "Content-Length: 0". */
public List<String> getHeaders() {
return headers;
Headers headers = this.headers.build();
int size = headers.size();
List<String> headerList = new ArrayList<>(size);
for (int i = 0; i < size; i++) {
headerList.add(headers.name(i) + ": " + headers.value(i));
}
return headerList;
}

Headers getNewHeaders() {
return headers.build();
}

/**
* Removes all HTTP headers including any "Content-Length" and
* "Transfer-encoding" headers that were added by default.
*/
public MockResponse clearHeaders() {
headers.clear();
headers = new Headers.Builder();
return this;
}

Expand All @@ -100,7 +110,8 @@ public MockResponse addHeader(String header) {
* headers with the same name.
*/
public MockResponse addHeader(String name, Object value) {
return addHeader(name + ": " + String.valueOf(value));
headers.add(name, String.valueOf(value));
return this;
}

/**
Expand All @@ -112,15 +123,15 @@ public MockResponse setHeader(String name, Object value) {
return addHeader(name, value);
}

/** Replaces all headers with those specified in {@code headers}. */
public MockResponse setHeaders(Headers headers) {
this.headers = headers.newBuilder();
return this;
}

/** Removes all headers named {@code name}. */
public MockResponse removeHeader(String name) {
name += ":";
for (Iterator<String> i = headers.iterator(); i.hasNext(); ) {
String header = i.next();
if (name.regionMatches(true, 0, header, 0, name.length())) {
i.remove();
}
}
headers.removeAll(name);
return this;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -517,7 +517,7 @@ private RecordedRequest readRequest(Socket socket, BufferedSource source, Buffer
return null; // no request because the stream is exhausted
}

List<String> headers = new ArrayList<>();
Headers.Builder headers = new Headers.Builder();
long contentLength = -1;
boolean chunked = false;
boolean expectContinue = false;
Expand Down Expand Up @@ -581,7 +581,7 @@ private RecordedRequest readRequest(Socket socket, BufferedSource source, Buffer
throw new UnsupportedOperationException("Unexpected method: " + request);
}

return new RecordedRequest(request, headers, chunkSizes, requestBody.receivedByteCount,
return new RecordedRequest(request, headers.build(), chunkSizes, requestBody.receivedByteCount,
requestBody.buffer, sequenceNumber, socket);
}

Expand All @@ -604,28 +604,17 @@ private void handleWebSocketUpgrade(Socket socket, BufferedSource source, Buffer
};

// Adapt the request and response into our Request and Response domain model.
Request.Builder fancyRequestBuilder = new Request.Builder()
.get().url(request.getPath());
List<String> requestHeaders = request.getHeaders();
Headers.Builder fancyRequestHeaders = new Headers.Builder();
for (int i = 0, size = requestHeaders.size(); i < size; i++) {
fancyRequestHeaders.add(requestHeaders.get(i));
}
fancyRequestBuilder.headers(fancyRequestHeaders.build());
final Request fancyRequest = fancyRequestBuilder.build();

Response.Builder fancyResponseBuilder = new Response.Builder()
final Request fancyRequest = new Request.Builder()
.get().url(request.getPath())
.headers(request.getNewHeaders())
.build();
final Response fancyResponse = new Response.Builder()
.code(Integer.parseInt(response.getStatus().split(" ")[1]))
.message(response.getStatus().split(" ", 3)[2])
.headers(response.getNewHeaders())
.request(fancyRequest)
.protocol(Protocol.HTTP_1_1);
List<String> responseHeaders = response.getHeaders();
Headers.Builder fancyResponseHeaders = new Headers.Builder();
for (int i = 0, size = responseHeaders.size(); i < size; i++) {
fancyRequestHeaders.add(responseHeaders.get(i));
}
fancyRequestBuilder.headers(fancyResponseHeaders.build());
final Response fancyResponse = fancyResponseBuilder.build();
.protocol(Protocol.HTTP_1_1)
.build();

// The callback might act synchronously. Give it its own thread.
new Thread(new Runnable() {
Expand Down Expand Up @@ -803,7 +792,7 @@ private SpdySocketHandler(Socket socket, Protocol protocol) {

private RecordedRequest readRequest(SpdyStream stream) throws IOException {
List<Header> spdyHeaders = stream.getRequestHeaders();
List<String> httpHeaders = new ArrayList<>();
Headers.Builder httpHeaders = new Headers.Builder();
String method = "<:method omitted>";
String path = "<:path omitted>";
String version = protocol == Protocol.SPDY_3 ? "<:version omitted>" : "HTTP/1.1";
Expand All @@ -817,7 +806,7 @@ private RecordedRequest readRequest(SpdyStream stream) throws IOException {
} else if (name.equals(Header.VERSION)) {
version = value;
} else {
httpHeaders.add(name.utf8() + ": " + value);
httpHeaders.add(name.utf8(), value);
}
}

Expand All @@ -827,7 +816,7 @@ private RecordedRequest readRequest(SpdyStream stream) throws IOException {

String requestLine = method + ' ' + path + ' ' + version;
List<Integer> chunkSizes = Collections.emptyList(); // No chunked encoding for SPDY.
return new RecordedRequest(requestLine, httpHeaders, chunkSizes, body.size(), body,
return new RecordedRequest(requestLine, httpHeaders.build(), chunkSizes, body.size(), body,
sequenceNumber.getAndIncrement(), socket);
}

Expand All @@ -845,14 +834,9 @@ private void writeResponse(SpdyStream stream, MockResponse response) throws IOEx
if (protocol == Protocol.SPDY_3) {
spdyHeaders.add(new Header(Header.VERSION, statusParts[0]));
}
List<String> headers = response.getHeaders();
Headers headers = response.getNewHeaders();
for (int i = 0, size = headers.size(); i < size; i++) {
String header = headers.get(i);
String[] headerParts = header.split(":", 2);
if (headerParts.length != 2) {
throw new AssertionError("Unexpected header: " + header);
}
spdyHeaders.add(new Header(headerParts[0], headerParts[1]));
spdyHeaders.add(new Header(headers.name(i), headers.value(i)));
}

Buffer body = response.getBody();
Expand All @@ -877,13 +861,9 @@ private void pushPromises(SpdyStream stream, List<PushPromise> promises) throws
: Header.TARGET_AUTHORITY, getUrl(pushPromise.getPath()).getHost()));
pushedHeaders.add(new Header(Header.TARGET_METHOD, pushPromise.getMethod()));
pushedHeaders.add(new Header(Header.TARGET_PATH, pushPromise.getPath()));
for (int i = 0, size = pushPromise.getHeaders().size(); i < size; i++) {
String header = pushPromise.getHeaders().get(i);
String[] headerParts = header.split(":", 2);
if (headerParts.length != 2) {
throw new AssertionError("Unexpected header: " + header);
}
pushedHeaders.add(new Header(headerParts[0], headerParts[1].trim()));
Headers pushPromiseHeaders = pushPromise.getHeaders();
for (int i = 0, size = pushPromiseHeaders.size(); i < size; i++) {
pushedHeaders.add(new Header(pushPromiseHeaders.name(i), pushPromiseHeaders.value(i)));
}
String requestLine = pushPromise.getMethod() + ' ' + pushPromise.getPath() + " HTTP/1.1";
List<Integer> chunkSizes = Collections.emptyList(); // No chunked encoding for SPDY.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,16 @@
*/
package com.squareup.okhttp.mockwebserver;

import java.util.List;
import com.squareup.okhttp.Headers;

/** An HTTP request initiated by the server. */
public final class PushPromise {
private final String method;
private final String path;
private final List<String> headers;
private final Headers headers;
private final MockResponse response;

public PushPromise(String method, String path, List<String> headers, MockResponse response) {
public PushPromise(String method, String path, Headers headers, MockResponse response) {
this.method = method;
this.path = path;
this.headers = headers;
Expand All @@ -39,7 +39,7 @@ public String getPath() {
return path;
}

public List<String> getHeaders() {
public Headers getHeaders() {
return headers;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

import com.squareup.okhttp.TlsVersion;
import com.squareup.okhttp.internal.Internal;
import com.squareup.okhttp.Headers;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
Expand All @@ -29,14 +30,14 @@ public final class RecordedRequest {
private final String requestLine;
private final String method;
private final String path;
private final List<String> headers;
private final Headers headers;
private final List<Integer> chunkSizes;
private final long bodySize;
private final Buffer body;
private final int sequenceNumber;
private final TlsVersion tlsVersion;

public RecordedRequest(String requestLine, List<String> headers, List<Integer> chunkSizes,
public RecordedRequest(String requestLine, Headers headers, List<Integer> chunkSizes,
long bodySize, Buffer body, int sequenceNumber, Socket socket) {
this.requestLine = requestLine;
this.headers = headers;
Expand Down Expand Up @@ -73,6 +74,15 @@ public String getPath() {

/** Returns all headers. */
public List<String> getHeaders() {
int size = headers.size();
List<String> headerList = new ArrayList<>(size);
for (int i = 0; i < size; i++) {
headerList.add(headers.name(i) + ": " + headers.value(i));
}
return headerList;
}

Headers getNewHeaders() {
return headers;
}

Expand All @@ -81,27 +91,13 @@ public List<String> getHeaders() {
* exists.
*/
public String getHeader(String name) {
name += ":";
for (int i = 0, size = headers.size(); i < size; i++) {
String header = headers.get(i);
if (name.regionMatches(true, 0, header, 0, name.length())) {
return header.substring(name.length()).trim();
}
}
return null;
List<String> values = headers.values(name);
return values.isEmpty() ? null : values.get(0);
}

/** Returns the headers named {@code name}. */
public List<String> getHeaders(String name) {
List<String> result = new ArrayList<>();
name += ":";
for (int i = 0, size = headers.size(); i < size; i++) {
String header = headers.get(i);
if (name.regionMatches(true, 0, header, 0, name.length())) {
result.add(header.substring(name.length()).trim());
}
}
return result;
return headers.values(name);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
*/
package com.squareup.okhttp.mockwebserver;

import com.squareup.okhttp.Headers;
import com.squareup.okhttp.mockwebserver.rule.MockWebServerRule;
import java.io.BufferedReader;
import java.io.IOException;
Expand All @@ -41,14 +42,14 @@ public final class MockWebServerTest {
@Rule public final MockWebServerRule server = new MockWebServerRule();

@Test public void recordedRequestAccessors() {
List<String> headers = Arrays.asList(
"User-Agent: okhttp",
"Cookie: s=square",
"Cookie: a=android",
"X-Whitespace: left",
"X-Whitespace:right ",
"X-Whitespace: both "
);
Headers headers = new Headers.Builder()
.add("User-Agent", "okhttp")
.add("Cookie", "s=square")
.add("Cookie", "a=android")
.add("X-Whitespace", " left")
.add("X-Whitespace", "right ")
.add("X-Whitespace", " both ")
.build();
List<Integer> chunkSizes = Collections.emptyList();
Buffer body = new Buffer().writeUtf8("ABC");
String requestLine = "GET / HTTP/1.1";
Expand Down
13 changes: 9 additions & 4 deletions okhttp-tests/src/test/java/com/squareup/okhttp/CacheTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

package com.squareup.okhttp;

import com.squareup.okhttp.internal.Internal;
import com.squareup.okhttp.internal.SslContextBuilder;
import com.squareup.okhttp.internal.Util;
import com.squareup.okhttp.mockwebserver.MockResponse;
Expand Down Expand Up @@ -1867,9 +1868,11 @@ public void assertCookies(URL url, String... expectedCookies) throws Exception {
}

@Test public void emptyResponseHeaderNameFromCacheIsLenient() throws Exception {
Headers.Builder headers = new Headers.Builder()
.add("Cache-Control: max-age=120");
Internal.instance.addLenient(headers, ": A");
server.enqueue(new MockResponse()
.addHeader("Cache-Control: max-age=120")
.addHeader(": A")
.setHeaders(headers.build())
.setBody("body"));

Response response = get(server.getUrl("/"));
Expand Down Expand Up @@ -2215,8 +2218,10 @@ private MockResponse truncateViolently(MockResponse response, int numBytesToKeep
Buffer truncatedBody = new Buffer();
truncatedBody.write(response.getBody(), numBytesToKeep);
response.setBody(truncatedBody);
response.getHeaders().clear();
response.getHeaders().addAll(headers);
response.clearHeaders();
for (String header : headers) {
response.addHeader(header);
}
return response;
}

Expand Down
Loading

0 comments on commit 6763803

Please sign in to comment.