| /* |
| * Copyright (C) 2014 Square, Inc. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package com.squareup.okhttp; |
| |
| import java.io.IOException; |
| import okio.Buffer; |
| import okio.BufferedSink; |
| import org.junit.Test; |
| |
| import static com.squareup.okhttp.internal.Util.UTF_8; |
| import static org.junit.Assert.assertEquals; |
| import static org.junit.Assert.fail; |
| |
| public final class MultipartBuilderTest { |
| @Test(expected = IllegalStateException.class) |
| public void onePartRequired() throws Exception { |
| new MultipartBuilder().build(); |
| } |
| |
| @Test public void singlePart() throws Exception { |
| String expected = "" |
| + "--123\r\n" |
| + "Content-Length: 13\r\n" |
| + "\r\n" |
| + "Hello, World!\r\n" |
| + "--123--\r\n"; |
| |
| RequestBody requestBody = new MultipartBuilder("123") |
| .addPart(RequestBody.create(null, "Hello, World!")) |
| .build(); |
| |
| assertEquals("multipart/mixed; boundary=123", requestBody.contentType().toString()); |
| |
| Buffer buffer = new Buffer(); |
| requestBody.writeTo(buffer); |
| assertEquals(53, requestBody.contentLength()); |
| assertEquals(buffer.size(), requestBody.contentLength()); |
| assertEquals(expected, buffer.readUtf8()); |
| } |
| |
| @Test public void threeParts() throws Exception { |
| String expected = "" |
| + "--123\r\n" |
| + "Content-Length: 5\r\n" |
| + "\r\n" |
| + "Quick\r\n" |
| + "--123\r\n" |
| + "Content-Length: 5\r\n" |
| + "\r\n" |
| + "Brown\r\n" |
| + "--123\r\n" |
| + "Content-Length: 3\r\n" |
| + "\r\n" |
| + "Fox\r\n" |
| + "--123--\r\n"; |
| |
| RequestBody requestBody = new MultipartBuilder("123") |
| .addPart(RequestBody.create(null, "Quick")) |
| .addPart(RequestBody.create(null, "Brown")) |
| .addPart(RequestBody.create(null, "Fox")) |
| .build(); |
| |
| assertEquals("multipart/mixed; boundary=123", requestBody.contentType().toString()); |
| |
| Buffer buffer = new Buffer(); |
| requestBody.writeTo(buffer); |
| assertEquals(112, requestBody.contentLength()); |
| assertEquals(buffer.size(), requestBody.contentLength()); |
| assertEquals(expected, buffer.readUtf8()); |
| } |
| |
| @Test public void fieldAndTwoFiles() throws Exception { |
| String expected = "" |
| + "--AaB03x\r\n" |
| + "Content-Disposition: form-data; name=\"submit-name\"\r\n" |
| + "Content-Length: 5\r\n" |
| + "\r\n" |
| + "Larry\r\n" |
| + "--AaB03x\r\n" |
| + "Content-Disposition: form-data; name=\"files\"\r\n" |
| + "Content-Type: multipart/mixed; boundary=BbC04y\r\n" |
| + "Content-Length: 337\r\n" |
| + "\r\n" |
| + "--BbC04y\r\n" |
| + "Content-Disposition: file; filename=\"file1.txt\"\r\n" |
| + "Content-Type: text/plain; charset=utf-8\r\n" |
| + "Content-Length: 29\r\n" |
| + "\r\n" |
| + "... contents of file1.txt ...\r\n" |
| + "--BbC04y\r\n" |
| + "Content-Disposition: file; filename=\"file2.gif\"\r\n" |
| + "Content-Transfer-Encoding: binary\r\n" |
| + "Content-Type: image/gif\r\n" |
| + "Content-Length: 29\r\n" |
| + "\r\n" |
| + "... contents of file2.gif ...\r\n" |
| + "--BbC04y--\r\n" |
| + "\r\n" |
| + "--AaB03x--\r\n"; |
| |
| RequestBody requestBody = new MultipartBuilder("AaB03x") |
| .type(MultipartBuilder.FORM) |
| .addFormDataPart("submit-name", "Larry") |
| .addFormDataPart("files", null, |
| new MultipartBuilder("BbC04y") |
| .addPart( |
| Headers.of("Content-Disposition", "file; filename=\"file1.txt\""), |
| RequestBody.create( |
| MediaType.parse("text/plain"), "... contents of file1.txt ...")) |
| .addPart( |
| Headers.of( |
| "Content-Disposition", "file; filename=\"file2.gif\"", |
| "Content-Transfer-Encoding", "binary"), |
| RequestBody.create( |
| MediaType.parse("image/gif"), |
| "... contents of file2.gif ...".getBytes(UTF_8))) |
| .build()) |
| .build(); |
| |
| assertEquals("multipart/form-data; boundary=AaB03x", requestBody.contentType().toString()); |
| |
| Buffer buffer = new Buffer(); |
| requestBody.writeTo(buffer); |
| assertEquals(568, requestBody.contentLength()); |
| assertEquals(buffer.size(), requestBody.contentLength()); |
| assertEquals(expected, buffer.readUtf8()); |
| } |
| |
| @Test public void stringEscapingIsWeird() throws Exception { |
| String expected = "" |
| + "--AaB03x\r\n" |
| + "Content-Disposition: form-data; name=\"field with spaces\"; filename=\"filename with spaces.txt\"\r\n" |
| + "Content-Type: text/plain; charset=utf-8\r\n" |
| + "Content-Length: 4\r\n" |
| + "\r\n" |
| + "okay\r\n" |
| + "--AaB03x\r\n" |
| + "Content-Disposition: form-data; name=\"field with %22\"\r\n" |
| + "Content-Length: 1\r\n" |
| + "\r\n" |
| + "\"\r\n" |
| + "--AaB03x\r\n" |
| + "Content-Disposition: form-data; name=\"field with %22\"\r\n" |
| + "Content-Length: 3\r\n" |
| + "\r\n" |
| + "%22\r\n" |
| + "--AaB03x\r\n" |
| + "Content-Disposition: form-data; name=\"field with \u0391\"\r\n" |
| + "Content-Length: 5\r\n" |
| + "\r\n" |
| + "Alpha\r\n" |
| + "--AaB03x--\r\n"; |
| |
| RequestBody requestBody = new MultipartBuilder("AaB03x") |
| .type(MultipartBuilder.FORM) |
| .addFormDataPart("field with spaces", "filename with spaces.txt", |
| RequestBody.create(MediaType.parse("text/plain; charset=utf-8"), "okay")) |
| .addFormDataPart("field with \"", "\"") |
| .addFormDataPart("field with %22", "%22") |
| .addFormDataPart("field with \u0391", "Alpha") |
| .build(); |
| |
| Buffer buffer = new Buffer(); |
| requestBody.writeTo(buffer); |
| assertEquals(expected, buffer.readUtf8()); |
| } |
| |
| @Test public void streamingPartHasNoLength() throws Exception { |
| class StreamingBody extends RequestBody { |
| private final String body; |
| |
| StreamingBody(String body) { |
| this.body = body; |
| } |
| |
| @Override public MediaType contentType() { |
| return null; |
| } |
| |
| @Override public void writeTo(BufferedSink sink) throws IOException { |
| sink.writeUtf8(body); |
| } |
| } |
| |
| String expected = "" |
| + "--123\r\n" |
| + "Content-Length: 5\r\n" |
| + "\r\n" |
| + "Quick\r\n" |
| + "--123\r\n" |
| + "\r\n" |
| + "Brown\r\n" |
| + "--123\r\n" |
| + "Content-Length: 3\r\n" |
| + "\r\n" |
| + "Fox\r\n" |
| + "--123--\r\n"; |
| |
| RequestBody requestBody = new MultipartBuilder("123") |
| .addPart(RequestBody.create(null, "Quick")) |
| .addPart(new StreamingBody("Brown")) |
| .addPart(RequestBody.create(null, "Fox")) |
| .build(); |
| |
| assertEquals("multipart/mixed; boundary=123", requestBody.contentType().toString()); |
| |
| Buffer buffer = new Buffer(); |
| requestBody.writeTo(buffer); |
| assertEquals(expected, buffer.readUtf8()); |
| assertEquals(-1, requestBody.contentLength()); |
| } |
| |
| @Test public void contentTypeHeaderIsForbidden() throws Exception { |
| try { |
| new MultipartBuilder().addPart( |
| Headers.of("Content-Type", "text/plain"), |
| RequestBody.create(null, "Hello, World!")); |
| fail(); |
| } catch (IllegalArgumentException expected) { |
| } |
| } |
| |
| @Test public void contentLengthHeaderIsForbidden() throws Exception { |
| try { |
| new MultipartBuilder().addPart( |
| Headers.of("Content-Length", "13"), |
| RequestBody.create(null, "Hello, World!")); |
| fail(); |
| } catch (IllegalArgumentException expected) { |
| } |
| } |
| } |