1/* 2 * Copyright (C) 2013 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.Util; 19import java.io.File; 20import java.io.FileWriter; 21import java.io.IOException; 22import java.net.URI; 23import java.net.URL; 24import java.util.Arrays; 25import java.util.Collections; 26import okio.Buffer; 27import org.junit.Test; 28 29import static org.junit.Assert.assertEquals; 30import static org.junit.Assert.assertNull; 31import static org.junit.Assert.fail; 32 33public final class RequestTest { 34 @Test public void string() throws Exception { 35 MediaType contentType = MediaType.parse("text/plain; charset=utf-8"); 36 RequestBody body = RequestBody.create(contentType, "abc".getBytes(Util.UTF_8)); 37 assertEquals(contentType, body.contentType()); 38 assertEquals(3, body.contentLength()); 39 assertEquals("616263", bodyToHex(body)); 40 assertEquals("Retransmit body", "616263", bodyToHex(body)); 41 } 42 43 @Test public void stringWithDefaultCharsetAdded() throws Exception { 44 MediaType contentType = MediaType.parse("text/plain"); 45 RequestBody body = RequestBody.create(contentType, "\u0800"); 46 assertEquals(MediaType.parse("text/plain; charset=utf-8"), body.contentType()); 47 assertEquals(3, body.contentLength()); 48 assertEquals("e0a080", bodyToHex(body)); 49 } 50 51 @Test public void stringWithNonDefaultCharsetSpecified() throws Exception { 52 MediaType contentType = MediaType.parse("text/plain; charset=utf-16be"); 53 RequestBody body = RequestBody.create(contentType, "\u0800"); 54 assertEquals(contentType, body.contentType()); 55 assertEquals(2, body.contentLength()); 56 assertEquals("0800", bodyToHex(body)); 57 } 58 59 @Test public void byteArray() throws Exception { 60 MediaType contentType = MediaType.parse("text/plain"); 61 RequestBody body = RequestBody.create(contentType, "abc".getBytes(Util.UTF_8)); 62 assertEquals(contentType, body.contentType()); 63 assertEquals(3, body.contentLength()); 64 assertEquals("616263", bodyToHex(body)); 65 assertEquals("Retransmit body", "616263", bodyToHex(body)); 66 } 67 68 @Test public void byteArrayRange() throws Exception { 69 MediaType contentType = MediaType.parse("text/plain"); 70 RequestBody body = RequestBody.create(contentType, ".abcd".getBytes(Util.UTF_8), 1, 3); 71 assertEquals(contentType, body.contentType()); 72 assertEquals(3, body.contentLength()); 73 assertEquals("616263", bodyToHex(body)); 74 assertEquals("Retransmit body", "616263", bodyToHex(body)); 75 } 76 77 @Test public void file() throws Exception { 78 File file = File.createTempFile("RequestTest", "tmp"); 79 FileWriter writer = new FileWriter(file); 80 writer.write("abc"); 81 writer.close(); 82 83 MediaType contentType = MediaType.parse("text/plain"); 84 RequestBody body = RequestBody.create(contentType, file); 85 assertEquals(contentType, body.contentType()); 86 assertEquals(3, body.contentLength()); 87 assertEquals("616263", bodyToHex(body)); 88 assertEquals("Retransmit body", "616263", bodyToHex(body)); 89 } 90 91 /** Common verbs used for apis such as GitHub, AWS, and Google Cloud. */ 92 @Test public void crudVerbs() throws IOException { 93 MediaType contentType = MediaType.parse("application/json"); 94 RequestBody body = RequestBody.create(contentType, "{}"); 95 96 Request get = new Request.Builder().url("http://localhost/api").get().build(); 97 assertEquals("GET", get.method()); 98 assertNull(get.body()); 99 100 Request head = new Request.Builder().url("http://localhost/api").head().build(); 101 assertEquals("HEAD", head.method()); 102 assertNull(head.body()); 103 104 Request delete = new Request.Builder().url("http://localhost/api").delete().build(); 105 assertEquals("DELETE", delete.method()); 106 assertEquals(0L, delete.body().contentLength()); 107 108 Request post = new Request.Builder().url("http://localhost/api").post(body).build(); 109 assertEquals("POST", post.method()); 110 assertEquals(body, post.body()); 111 112 Request put = new Request.Builder().url("http://localhost/api").put(body).build(); 113 assertEquals("PUT", put.method()); 114 assertEquals(body, put.body()); 115 116 Request patch = new Request.Builder().url("http://localhost/api").patch(body).build(); 117 assertEquals("PATCH", patch.method()); 118 assertEquals(body, patch.body()); 119 } 120 121 @Test public void uninitializedURI() throws Exception { 122 Request request = new Request.Builder().url("http://localhost/api").build(); 123 assertEquals(new URI("http://localhost/api"), request.uri()); 124 assertEquals(new URL("http://localhost/api"), request.url()); 125 } 126 127 @Test public void newBuilderUrlResetsUrl() throws Exception { 128 Request requestWithoutCache = new Request.Builder().url("http://localhost/api").build(); 129 Request builtRequestWithoutCache = requestWithoutCache.newBuilder().url("http://localhost/api/foo").build(); 130 assertEquals(new URL("http://localhost/api/foo"), builtRequestWithoutCache.url()); 131 132 Request requestWithCache = new Request.Builder().url("http://localhost/api").build(); 133 // cache url object 134 requestWithCache.url(); 135 Request builtRequestWithCache = requestWithCache.newBuilder().url( 136 "http://localhost/api/foo").build(); 137 assertEquals(new URL("http://localhost/api/foo"), builtRequestWithCache.url()); 138 } 139 140 @Test public void cacheControl() throws Exception { 141 Request request = new Request.Builder() 142 .cacheControl(new CacheControl.Builder().noCache().build()) 143 .url("https://square.com") 144 .build(); 145 assertEquals(Arrays.asList("no-cache"), request.headers("Cache-Control")); 146 } 147 148 @Test public void emptyCacheControlClearsAllCacheControlHeaders() throws Exception { 149 Request request = new Request.Builder() 150 .header("Cache-Control", "foo") 151 .cacheControl(new CacheControl.Builder().build()) 152 .url("https://square.com") 153 .build(); 154 assertEquals(Collections.<String>emptyList(), request.headers("Cache-Control")); 155 } 156 157 @Test public void headerAcceptsPermittedCharacters() throws Exception { 158 Request.Builder builder = new Request.Builder(); 159 builder.header("AZab09 ~", "AZab09 ~"); 160 builder.addHeader("AZab09 ~", "AZab09 ~"); 161 } 162 163 @Test public void emptyNameForbidden() throws Exception { 164 Request.Builder builder = new Request.Builder(); 165 try { 166 builder.header("", "Value"); 167 fail(); 168 } catch (IllegalArgumentException expected) { 169 } 170 try { 171 builder.addHeader("", "Value"); 172 fail(); 173 } catch (IllegalArgumentException expected) { 174 } 175 } 176 177 @Test public void headerForbidsControlCharacters() throws Exception { 178 assertForbiddenHeader(null); 179 assertForbiddenHeader("\u0000"); 180 // Workaround for http://b/26422335 , http://b/26889631 181 // assertForbiddenHeader("\n"); 182 assertForbiddenHeader("a\nb"); 183 assertForbiddenHeader("\nb"); 184 // assertForbiddenHeader("\r"); 185 assertForbiddenHeader("a\rb"); 186 assertForbiddenHeader("\rb"); 187 // End of Android modification. 188 assertForbiddenHeader("\t"); 189 assertForbiddenHeader("\u001f"); 190 assertForbiddenHeader("\u007f"); 191 192 // ANDROID-BEGIN Workaround for http://b/28867041 193 // assertForbiddenHeader("\u0080"); 194 // assertForbiddenHeader("\ud83c\udf69"); 195 // ANDROID-END 196 } 197 198 private void assertForbiddenHeader(String s) { 199 Request.Builder builder = new Request.Builder(); 200 try { 201 builder.header(s, "Value"); 202 fail(); 203 } catch (IllegalArgumentException expected) { 204 } 205 try { 206 builder.addHeader(s, "Value"); 207 fail(); 208 } catch (IllegalArgumentException expected) { 209 } 210 try { 211 builder.header("Name", s); 212 fail(); 213 } catch (IllegalArgumentException expected) { 214 } 215 try { 216 builder.addHeader("Name", s); 217 fail(); 218 } catch (IllegalArgumentException expected) { 219 } 220 } 221 222 private String bodyToHex(RequestBody body) throws IOException { 223 Buffer buffer = new Buffer(); 224 body.writeTo(buffer); 225 return buffer.readByteString().hex(); 226 } 227} 228