MockResponse.java revision 4559b1d37edcb5d7f1da086cf2e3290388d74f46
1b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson/* 2b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson * Copyright (C) 2010 The Android Open Source Project 3b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson * 4b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson * Licensed under the Apache License, Version 2.0 (the "License"); 5b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson * you may not use this file except in compliance with the License. 6b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson * You may obtain a copy of the License at 7b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson * 8b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson * http://www.apache.org/licenses/LICENSE-2.0 9b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson * 10b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson * Unless required by applicable law or agreed to in writing, software 11b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson * distributed under the License is distributed on an "AS IS" BASIS, 12b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson * See the License for the specific language governing permissions and 14b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson * limitations under the License. 15b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson */ 16b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson 17b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilsonpackage tests.http; 18b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson 19b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilsonimport java.io.ByteArrayOutputStream; 20b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilsonimport java.io.IOException; 21b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilsonimport java.io.UnsupportedEncodingException; 22b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilsonimport java.util.ArrayList; 23b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilsonimport java.util.List; 24b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson 25b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilsonimport static tests.http.MockWebServer.ASCII; 26b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson 27b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson/** 28b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson * A scripted response to be replayed by the mock web server. 29b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson */ 30b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilsonpublic class MockResponse { 31b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson private static final String EMPTY_BODY_HEADER = "Content-Length: 0"; 32b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson private static final String CHUNKED_BODY_HEADER = "Transfer-encoding: chunked"; 33b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson private static final byte[] EMPTY_BODY = new byte[0]; 34b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson 35b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson private String status = "HTTP/1.1 200 OK"; 36b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson private List<String> headers = new ArrayList<String>(); 37b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson private byte[] body = EMPTY_BODY; 384559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom private boolean disconnectAtStart; 3951e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson private boolean disconnectAtEnd; 40b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson 41b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson public MockResponse() { 42b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson headers.add(EMPTY_BODY_HEADER); 43b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson } 44b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson 45b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson /** 46b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson * Returns the HTTP response line, such as "HTTP/1.1 200 OK". 47b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson */ 48b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson public String getStatus() { 49b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson return status; 50b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson } 51b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson 52b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson public MockResponse setResponseCode(int code) { 53b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson this.status = "HTTP/1.1 " + code + " OK"; 54b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson return this; 55b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson } 56b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson 57706d53593cd8841d378dbe298a8d1940db1e71dfJesse Wilson public MockResponse setStatus(String status) { 58706d53593cd8841d378dbe298a8d1940db1e71dfJesse Wilson this.status = status; 59706d53593cd8841d378dbe298a8d1940db1e71dfJesse Wilson return this; 60706d53593cd8841d378dbe298a8d1940db1e71dfJesse Wilson } 61706d53593cd8841d378dbe298a8d1940db1e71dfJesse Wilson 62b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson /** 63b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson * Returns the HTTP headers, such as "Content-Length: 0". 64b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson */ 65b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson public List<String> getHeaders() { 66b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson return headers; 67b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson } 68b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson 69c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson public MockResponse clearHeaders() { 70c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson headers.clear(); 71c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson return this; 72c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson } 73c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson 74b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson public MockResponse addHeader(String header) { 75b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson headers.add(header); 76b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson return this; 77b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson } 78b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson 79b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson /** 80b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson * Returns an input stream containing the raw HTTP payload. 81b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson */ 82b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson public byte[] getBody() { 83b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson return body; 84b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson } 85b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson 86b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson public MockResponse setBody(byte[] body) { 87b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson if (this.body == EMPTY_BODY) { 88b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson headers.remove(EMPTY_BODY_HEADER); 89b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson } 90b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson this.headers.add("Content-Length: " + body.length); 91b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson this.body = body; 92b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson return this; 93b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson } 94b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson 95b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson public MockResponse setBody(String body) { 96b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson try { 97b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson return setBody(body.getBytes(ASCII)); 98b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson } catch (UnsupportedEncodingException e) { 99b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson throw new AssertionError(); 100b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson } 101b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson } 102b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson 103b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson public MockResponse setChunkedBody(byte[] body, int maxChunkSize) throws IOException { 104b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson headers.remove(EMPTY_BODY_HEADER); 105b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson headers.add(CHUNKED_BODY_HEADER); 106b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson 107b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson ByteArrayOutputStream bytesOut = new ByteArrayOutputStream(); 108b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson int pos = 0; 109b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson while (pos < body.length) { 110b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson int chunkSize = Math.min(body.length - pos, maxChunkSize); 111b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson bytesOut.write(Integer.toHexString(chunkSize).getBytes(ASCII)); 112b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson bytesOut.write("\r\n".getBytes(ASCII)); 113b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson bytesOut.write(body, pos, chunkSize); 114b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson bytesOut.write("\r\n".getBytes(ASCII)); 115b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson pos += chunkSize; 116b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson } 117c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson bytesOut.write("0\r\n\r\n".getBytes(ASCII)); // last chunk + empty trailer + crlf 118b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson this.body = bytesOut.toByteArray(); 119b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson return this; 120b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson } 121b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson 122b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson public MockResponse setChunkedBody(String body, int maxChunkSize) throws IOException { 123b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson return setChunkedBody(body.getBytes(ASCII), maxChunkSize); 124b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson } 125b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson 1264559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom /** 1274559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom * Request immediate close of connection without even reading the 1284559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom * request. 1294559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom * <p> 1304559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom * Use to simulate the real life case of losing connection 1314559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom * because of bugger SSL server close connection when it seems 1324559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom * something like a compression method or TLS extension it doesn't 1334559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom * understand, instead of simply ignoring it like it should. 1344559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom */ 1354559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom public MockResponse setDisconnectAtStart(boolean disconnectAtStart) { 1364559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom this.disconnectAtStart = disconnectAtStart; 1374559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom return this; 1384559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom } 1394559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom 1404559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom public boolean getDisconnectAtStart() { 1414559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom return disconnectAtStart; 1424559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom } 1434559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom 1444559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom /** 1454559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom * Request close of connection after the response. This is the 1464559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom * default HTTP/1.0 behavior. 1474559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom */ 14851e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson public MockResponse setDisconnectAtEnd(boolean disconnectAtEnd) { 14951e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson this.disconnectAtEnd = disconnectAtEnd; 15051e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson return this; 15151e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson } 15251e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson 15351e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson public boolean getDisconnectAtEnd() { 15451e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson return disconnectAtEnd; 15551e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson } 15651e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson 157b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson @Override public String toString() { 158b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson return status; 159b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson } 160b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson} 161