SyncApiTest.java revision 3c938a3f6b61ce5e2dba0d039b03fe73b89fd26c
1/* 2 * Copyright (C) 2014 Square, Inc. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16package com.squareup.okhttp; 17 18import com.squareup.okhttp.internal.RecordingHostnameVerifier; 19import com.squareup.okhttp.internal.SslContextBuilder; 20import com.squareup.okhttp.mockwebserver.MockResponse; 21import com.squareup.okhttp.mockwebserver.MockWebServer; 22import com.squareup.okhttp.mockwebserver.RecordedRequest; 23import com.squareup.okhttp.mockwebserver.SocketPolicy; 24import java.io.File; 25import java.io.IOException; 26import java.net.HttpURLConnection; 27import java.util.UUID; 28import javax.net.ssl.SSLContext; 29import org.junit.After; 30import org.junit.Before; 31import org.junit.Test; 32 33import static org.junit.Assert.assertEquals; 34import static org.junit.Assert.assertNull; 35import static org.junit.Assert.assertTrue; 36import static org.junit.Assert.fail; 37 38public final class SyncApiTest { 39 private MockWebServer server = new MockWebServer(); 40 private OkHttpClient client = new OkHttpClient(); 41 42 private static final SSLContext sslContext = SslContextBuilder.localhost(); 43 private HttpResponseCache cache; 44 45 @Before public void setUp() throws Exception { 46 String tmp = System.getProperty("java.io.tmpdir"); 47 File cacheDir = new File(tmp, "HttpCache-" + UUID.randomUUID()); 48 cache = new HttpResponseCache(cacheDir, Integer.MAX_VALUE); 49 } 50 51 @After public void tearDown() throws Exception { 52 server.shutdown(); 53 cache.delete(); 54 } 55 56 @Test public void get() throws Exception { 57 server.enqueue(new MockResponse() 58 .setBody("abc") 59 .addHeader("Content-Type: text/plain")); 60 server.play(); 61 62 Request request = new Request.Builder() 63 .url(server.getUrl("/")) 64 .header("User-Agent", "SyncApiTest") 65 .build(); 66 67 onSuccess(request) 68 .assertCode(200) 69 .assertContainsHeaders("Content-Type: text/plain") 70 .assertBody("abc"); 71 72 assertTrue(server.takeRequest().getHeaders().contains("User-Agent: SyncApiTest")); 73 } 74 75 @Test public void connectionPooling() throws Exception { 76 server.enqueue(new MockResponse().setBody("abc")); 77 server.enqueue(new MockResponse().setBody("def")); 78 server.enqueue(new MockResponse().setBody("ghi")); 79 server.play(); 80 81 onSuccess(new Request.Builder().url(server.getUrl("/a")).build()) 82 .assertBody("abc"); 83 84 onSuccess(new Request.Builder().url(server.getUrl("/b")).build()) 85 .assertBody("def"); 86 87 onSuccess(new Request.Builder().url(server.getUrl("/c")).build()) 88 .assertBody("ghi"); 89 90 assertEquals(0, server.takeRequest().getSequenceNumber()); 91 assertEquals(1, server.takeRequest().getSequenceNumber()); 92 assertEquals(2, server.takeRequest().getSequenceNumber()); 93 } 94 95 @Test public void tls() throws Exception { 96 server.useHttps(sslContext.getSocketFactory(), false); 97 server.enqueue(new MockResponse() 98 .setBody("abc") 99 .addHeader("Content-Type: text/plain")); 100 server.play(); 101 102 client.setSslSocketFactory(sslContext.getSocketFactory()); 103 client.setHostnameVerifier(new RecordingHostnameVerifier()); 104 105 onSuccess(new Request.Builder().url(server.getUrl("/")).build()) 106 .assertHandshake(); 107 } 108 109 @Test public void recoverFromTlsHandshakeFailure() throws Exception { 110 server.useHttps(sslContext.getSocketFactory(), false); 111 server.enqueue(new MockResponse().setSocketPolicy(SocketPolicy.FAIL_HANDSHAKE)); 112 server.enqueue(new MockResponse().setBody("abc")); 113 server.play(); 114 115 client.setSslSocketFactory(sslContext.getSocketFactory()); 116 client.setHostnameVerifier(new RecordingHostnameVerifier()); 117 118 onSuccess(new Request.Builder().url(server.getUrl("/")).build()) 119 .assertBody("abc"); 120 } 121 122 @Test public void post() throws Exception { 123 server.enqueue(new MockResponse().setBody("abc")); 124 server.play(); 125 126 Request request = new Request.Builder() 127 .url(server.getUrl("/")) 128 .post(Request.Body.create(MediaType.parse("text/plain"), "def")) 129 .build(); 130 131 onSuccess(request) 132 .assertCode(200) 133 .assertBody("abc"); 134 135 RecordedRequest recordedRequest = server.takeRequest(); 136 assertEquals("def", recordedRequest.getUtf8Body()); 137 assertEquals("3", recordedRequest.getHeader("Content-Length")); 138 assertEquals("text/plain; charset=utf-8", recordedRequest.getHeader("Content-Type")); 139 } 140 141 @Test public void cache() throws Exception { 142 server.enqueue(new MockResponse().setBody("A").addHeader("ETag: v1")); 143 server.enqueue(new MockResponse().setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED)); 144 server.play(); 145 146 client.setOkResponseCache(cache); 147 148 onSuccess(new Request.Builder().url(server.getUrl("/")).build()) 149 .assertCode(200).assertBody("A"); 150 assertNull(server.takeRequest().getHeader("If-None-Match")); 151 152 onSuccess(new Request.Builder().url(server.getUrl("/")).build()) 153 .assertCode(200).assertBody("A"); 154 assertEquals("v1", server.takeRequest().getHeader("If-None-Match")); 155 } 156 157 @Test public void redirect() throws Exception { 158 server.enqueue(new MockResponse() 159 .setResponseCode(301) 160 .addHeader("Location: /b") 161 .addHeader("Test", "Redirect from /a to /b") 162 .setBody("/a has moved!")); 163 server.enqueue(new MockResponse() 164 .setResponseCode(302) 165 .addHeader("Location: /c") 166 .addHeader("Test", "Redirect from /b to /c") 167 .setBody("/b has moved!")); 168 server.enqueue(new MockResponse().setBody("C")); 169 server.play(); 170 171 onSuccess(new Request.Builder().url(server.getUrl("/a")).build()) 172 .assertCode(200) 173 .assertBody("C") 174 .redirectedBy() 175 .assertCode(302) 176 .assertContainsHeaders("Test: Redirect from /b to /c") 177 .redirectedBy() 178 .assertCode(301) 179 .assertContainsHeaders("Test: Redirect from /a to /b"); 180 181 assertEquals(0, server.takeRequest().getSequenceNumber()); // New connection. 182 assertEquals(1, server.takeRequest().getSequenceNumber()); // Connection reused. 183 assertEquals(2, server.takeRequest().getSequenceNumber()); // Connection reused again! 184 } 185 186 @Test public void redirectWithRedirectsDisabled() throws Exception { 187 client.setFollowProtocolRedirects(false); 188 server.enqueue(new MockResponse() 189 .setResponseCode(301) 190 .addHeader("Location: /b") 191 .addHeader("Test", "Redirect from /a to /b") 192 .setBody("/a has moved!")); 193 server.play(); 194 195 onSuccess(new Request.Builder().url(server.getUrl("/a")).build()) 196 .assertCode(301) 197 .assertBody("/a has moved!") 198 .assertContainsHeaders("Location: /b"); 199 } 200 201 @Test public void follow20Redirects() throws Exception { 202 for (int i = 0; i < 20; i++) { 203 server.enqueue(new MockResponse() 204 .setResponseCode(301) 205 .addHeader("Location: /" + (i + 1)) 206 .setBody("Redirecting to /" + (i + 1))); 207 } 208 server.enqueue(new MockResponse().setBody("Success!")); 209 server.play(); 210 211 onSuccess(new Request.Builder().url(server.getUrl("/0")).build()) 212 .assertCode(200) 213 .assertBody("Success!"); 214 } 215 216 @Test public void doesNotFollow21Redirects() throws Exception { 217 for (int i = 0; i < 21; i++) { 218 server.enqueue(new MockResponse() 219 .setResponseCode(301) 220 .addHeader("Location: /" + (i + 1)) 221 .setBody("Redirecting to /" + (i + 1))); 222 } 223 server.play(); 224 225 try { 226 client.execute(new Request.Builder().url(server.getUrl("/0")).build()); 227 fail(); 228 } catch (IOException e) { 229 assertEquals("Too many redirects: 21", e.getMessage()); 230 } 231 } 232 233 @Test public void postBodyRetransmittedOnRedirect() throws Exception { 234 server.enqueue(new MockResponse() 235 .setResponseCode(302) 236 .addHeader("Location: /b") 237 .setBody("Moved to /b !")); 238 server.enqueue(new MockResponse() 239 .setBody("This is b.")); 240 server.play(); 241 242 Request request = new Request.Builder() 243 .url(server.getUrl("/")) 244 .post(Request.Body.create(MediaType.parse("text/plain"), "body!")) 245 .build(); 246 247 onSuccess(request) 248 .assertCode(200) 249 .assertBody("This is b."); 250 251 RecordedRequest request1 = server.takeRequest(); 252 assertEquals("body!", request1.getUtf8Body()); 253 assertEquals("5", request1.getHeader("Content-Length")); 254 assertEquals("text/plain; charset=utf-8", request1.getHeader("Content-Type")); 255 assertEquals(0, request1.getSequenceNumber()); 256 257 RecordedRequest request2 = server.takeRequest(); 258 assertEquals("body!", request2.getUtf8Body()); 259 assertEquals("5", request2.getHeader("Content-Length")); 260 assertEquals("text/plain; charset=utf-8", request2.getHeader("Content-Type")); 261 assertEquals(1, request2.getSequenceNumber()); 262 } 263 264 private RecordedResponse onSuccess(Request request) throws IOException { 265 Response response = client.execute(request); 266 return new RecordedResponse(request, response, response.body().string(), null); 267 } 268} 269