diff --git a/spring-restdocs-core/src/main/java/org/springframework/restdocs/cli/CliOperationRequest.java b/spring-restdocs-core/src/main/java/org/springframework/restdocs/cli/CliOperationRequest.java index 2dde09ef..10ae0486 100644 --- a/spring-restdocs-core/src/main/java/org/springframework/restdocs/cli/CliOperationRequest.java +++ b/spring-restdocs-core/src/main/java/org/springframework/restdocs/cli/CliOperationRequest.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2016 the original author or authors. + * Copyright 2014-2017 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -25,6 +25,8 @@ import java.util.Map; import java.util.Map.Entry; import java.util.Set; +import javax.servlet.http.Cookie; + import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; import org.springframework.restdocs.operation.OperationRequest; @@ -125,6 +127,11 @@ final class CliOperationRequest implements OperationRequest { return this.delegate.getUri(); } + @Override + public Collection getCookies() { + return this.delegate.getCookies(); + } + private interface HeaderFilter { boolean allow(String name, List value); diff --git a/spring-restdocs-core/src/main/java/org/springframework/restdocs/cli/CurlRequestSnippet.java b/spring-restdocs-core/src/main/java/org/springframework/restdocs/cli/CurlRequestSnippet.java index 4f8d603c..886a4c07 100644 --- a/spring-restdocs-core/src/main/java/org/springframework/restdocs/cli/CurlRequestSnippet.java +++ b/spring-restdocs-core/src/main/java/org/springframework/restdocs/cli/CurlRequestSnippet.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2016 the original author or authors. + * Copyright 2014-2017 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,6 +23,8 @@ import java.util.List; import java.util.Map; import java.util.Map.Entry; +import javax.servlet.http.Cookie; + import org.springframework.http.HttpMethod; import org.springframework.restdocs.operation.Operation; import org.springframework.restdocs.operation.OperationRequest; @@ -30,6 +32,7 @@ import org.springframework.restdocs.operation.OperationRequestPart; import org.springframework.restdocs.operation.Parameters; import org.springframework.restdocs.snippet.Snippet; import org.springframework.restdocs.snippet.TemplatedSnippet; +import org.springframework.util.CollectionUtils; import org.springframework.util.StringUtils; /** @@ -92,12 +95,27 @@ public class CurlRequestSnippet extends TemplatedSnippet { writeUserOptionIfNecessary(request, printer); writeHttpMethodIfNecessary(request, printer); writeHeaders(request, printer); + writeCookies(request, printer); writePartsIfNecessary(request, printer); writeContent(request, printer); return command.toString(); } + private void writeCookies(CliOperationRequest request, PrintWriter printer) { + if (!CollectionUtils.isEmpty(request.getCookies())) { + StringBuilder cookiesBuilder = new StringBuilder(); + for (Cookie cookie : request.getCookies()) { + if (cookiesBuilder.length() > 0) { + cookiesBuilder.append(";"); + } + cookiesBuilder.append( + String.format("%s=%s", cookie.getName(), cookie.getValue())); + } + printer.print(String.format(" --cookie '%s'", cookiesBuilder.toString())); + } + } + private void writeIncludeHeadersInOutputOption(PrintWriter writer) { writer.print("-i"); } diff --git a/spring-restdocs-core/src/main/java/org/springframework/restdocs/cli/HttpieRequestSnippet.java b/spring-restdocs-core/src/main/java/org/springframework/restdocs/cli/HttpieRequestSnippet.java index 10b96fac..38a8970b 100644 --- a/spring-restdocs-core/src/main/java/org/springframework/restdocs/cli/HttpieRequestSnippet.java +++ b/spring-restdocs-core/src/main/java/org/springframework/restdocs/cli/HttpieRequestSnippet.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2016 the original author or authors. + * Copyright 2014-2017 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,6 +23,8 @@ import java.util.List; import java.util.Map; import java.util.Map.Entry; +import javax.servlet.http.Cookie; + import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; import org.springframework.http.MediaType; @@ -106,6 +108,7 @@ public class HttpieRequestSnippet extends TemplatedSnippet { PrintWriter printer = new PrintWriter(requestItems); writeFormDataIfNecessary(request, printer); writeHeaders(request, printer); + writeCookies(request, printer); writeParametersIfNecessary(request, printer); return requestItems.toString(); } @@ -162,6 +165,13 @@ public class HttpieRequestSnippet extends TemplatedSnippet { } } + private void writeCookies(OperationRequest request, PrintWriter writer) { + for (Cookie cookie : request.getCookies()) { + writer.print(String.format(" 'Cookie:%s=%s'", cookie.getName(), + cookie.getValue())); + } + } + private void writeParametersIfNecessary(CliOperationRequest request, PrintWriter writer) { if (StringUtils.hasText(request.getContentAsString())) { diff --git a/spring-restdocs-core/src/main/java/org/springframework/restdocs/http/HttpRequestSnippet.java b/spring-restdocs-core/src/main/java/org/springframework/restdocs/http/HttpRequestSnippet.java index 0110dd1b..8262571a 100644 --- a/spring-restdocs-core/src/main/java/org/springframework/restdocs/http/HttpRequestSnippet.java +++ b/spring-restdocs-core/src/main/java/org/springframework/restdocs/http/HttpRequestSnippet.java @@ -24,6 +24,8 @@ import java.util.List; import java.util.Map; import java.util.Map.Entry; +import javax.servlet.http.Cookie; + import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; import org.springframework.http.MediaType; @@ -35,6 +37,7 @@ import org.springframework.restdocs.snippet.Snippet; import org.springframework.restdocs.snippet.TemplatedSnippet; import org.springframework.util.StringUtils; + /** * A {@link Snippet} that documents an HTTP request. * @@ -112,6 +115,11 @@ public class HttpRequestSnippet extends TemplatedSnippet { } } + + for (Cookie cookie : request.getCookies()) { + headers.add(header(HttpHeaders.COOKIE, String.format("%s=%s", cookie.getName(), cookie.getValue()))); + } + if (requiresFormEncodingContentTypeHeader(request)) { headers.add(header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_FORM_URLENCODED_VALUE)); diff --git a/spring-restdocs-core/src/main/java/org/springframework/restdocs/operation/OperationRequest.java b/spring-restdocs-core/src/main/java/org/springframework/restdocs/operation/OperationRequest.java index 29153eec..93972dba 100644 --- a/spring-restdocs-core/src/main/java/org/springframework/restdocs/operation/OperationRequest.java +++ b/spring-restdocs-core/src/main/java/org/springframework/restdocs/operation/OperationRequest.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2015 the original author or authors. + * Copyright 2014-2017 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,6 +19,8 @@ package org.springframework.restdocs.operation; import java.net.URI; import java.util.Collection; +import javax.servlet.http.Cookie; + import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; @@ -86,4 +88,13 @@ public interface OperationRequest { */ URI getUri(); + /** + * Returns {@link Cookie Cookies} sent with the request. If no cookies were sent an + * empty collection is returned. + * + * @return the cookies, never {@code null} + * @since 1.2.0 + */ + Collection getCookies(); + } diff --git a/spring-restdocs-core/src/main/java/org/springframework/restdocs/operation/OperationRequestFactory.java b/spring-restdocs-core/src/main/java/org/springframework/restdocs/operation/OperationRequestFactory.java index 198011b4..3f75e289 100644 --- a/spring-restdocs-core/src/main/java/org/springframework/restdocs/operation/OperationRequestFactory.java +++ b/spring-restdocs-core/src/main/java/org/springframework/restdocs/operation/OperationRequestFactory.java @@ -18,6 +18,9 @@ package org.springframework.restdocs.operation; import java.net.URI; import java.util.Collection; +import java.util.Collections; + +import javax.servlet.http.Cookie; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; @@ -29,6 +32,28 @@ import org.springframework.http.HttpMethod; */ public class OperationRequestFactory { + /** + * Creates a new {@link OperationRequest}. The given {@code headers} will be augmented + * to ensure that they always include a {@code Content-Length} header if the request + * has any content and a {@code Host} header. + * + * @param uri the request's uri + * @param method the request method + * @param content the content of the request + * @param headers the request's headers + * @param parameters the request's parameters + * @param parts the request's parts + * @param cookies the request's cookies + * @return the {@code OperationRequest} + */ + public OperationRequest create(URI uri, HttpMethod method, byte[] content, + HttpHeaders headers, Parameters parameters, + Collection parts, + Collection cookies) { + return new StandardOperationRequest(uri, method, content, + augmentHeaders(headers, uri, content), parameters, parts, cookies); + } + /** * Creates a new {@link OperationRequest}. The given {@code headers} will be augmented * to ensure that they always include a {@code Content-Length} header if the request @@ -45,8 +70,7 @@ public class OperationRequestFactory { public OperationRequest create(URI uri, HttpMethod method, byte[] content, HttpHeaders headers, Parameters parameters, Collection parts) { - return new StandardOperationRequest(uri, method, content, - augmentHeaders(headers, uri, content), parameters, parts); + return create(uri, method, content, headers, parameters, parts, Collections.emptyList()); } /** @@ -62,7 +86,7 @@ public class OperationRequestFactory { public OperationRequest createFrom(OperationRequest original, byte[] newContent) { return new StandardOperationRequest(original.getUri(), original.getMethod(), newContent, getUpdatedHeaders(original.getHeaders(), newContent), - original.getParameters(), original.getParts()); + original.getParameters(), original.getParts(), original.getCookies()); } /** @@ -78,7 +102,7 @@ public class OperationRequestFactory { HttpHeaders newHeaders) { return new StandardOperationRequest(original.getUri(), original.getMethod(), original.getContent(), newHeaders, original.getParameters(), - original.getParts()); + original.getParts(), original.getCookies()); } /** @@ -94,7 +118,7 @@ public class OperationRequestFactory { Parameters newParameters) { return new StandardOperationRequest(original.getUri(), original.getMethod(), original.getContent(), original.getHeaders(), newParameters, - original.getParts()); + original.getParts(), original.getCookies()); } private HttpHeaders augmentHeaders(HttpHeaders originalHeaders, URI uri, diff --git a/spring-restdocs-core/src/main/java/org/springframework/restdocs/operation/StandardOperationRequest.java b/spring-restdocs-core/src/main/java/org/springframework/restdocs/operation/StandardOperationRequest.java index a09bd645..8495c6c9 100644 --- a/spring-restdocs-core/src/main/java/org/springframework/restdocs/operation/StandardOperationRequest.java +++ b/spring-restdocs-core/src/main/java/org/springframework/restdocs/operation/StandardOperationRequest.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2015 the original author or authors. + * Copyright 2014-2017 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,6 +20,8 @@ import java.net.URI; import java.util.Collection; import java.util.Collections; +import javax.servlet.http.Cookie; + import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; @@ -39,9 +41,12 @@ class StandardOperationRequest extends AbstractOperationMessage private URI uri; + private Collection cookies; + /** * Creates a new request with the given {@code uri} and {@code method}. The request - * will have the given {@code headers}, {@code parameters}, and {@code parts}. + * will have the given {@code headers}, {@code parameters}, {@code parts}, and + * {@code cookies}. * * @param uri the uri * @param method the method @@ -49,15 +54,17 @@ class StandardOperationRequest extends AbstractOperationMessage * @param headers the headers * @param parameters the parameters * @param parts the parts + * @param cookies the cookies */ StandardOperationRequest(URI uri, HttpMethod method, byte[] content, HttpHeaders headers, Parameters parameters, - Collection parts) { + Collection parts, Collection cookies) { super(content, headers); this.uri = uri; this.method = method; this.parameters = parameters; this.parts = parts; + this.cookies = cookies; } @Override @@ -80,4 +87,9 @@ class StandardOperationRequest extends AbstractOperationMessage return this.uri; } + @Override + public Collection getCookies() { + return this.cookies; + } + } diff --git a/spring-restdocs-core/src/test/java/org/springframework/restdocs/cli/CurlRequestSnippetTests.java b/spring-restdocs-core/src/test/java/org/springframework/restdocs/cli/CurlRequestSnippetTests.java index fc4cf64c..33d6aa88 100644 --- a/spring-restdocs-core/src/test/java/org/springframework/restdocs/cli/CurlRequestSnippetTests.java +++ b/spring-restdocs-core/src/test/java/org/springframework/restdocs/cli/CurlRequestSnippetTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2016 the original author or authors. + * Copyright 2014-2017 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -251,6 +251,16 @@ public class CurlRequestSnippetTests extends AbstractSnippetTests { .header("a", "alpha").build()); } + @Test + public void requestWithCookies() throws IOException { + this.snippets.expectCurlRequest() + .withContents(codeBlock("bash").content("$ curl 'http://localhost/foo' -i" + + " --cookie 'name1=value1;name2=value2'")); + new CurlRequestSnippet() + .document(this.operationBuilder.request("http://localhost/foo") + .cookie("name1", "value1").cookie("name2", "value2").build()); + } + @Test public void multipartPostWithNoSubmittedFileName() throws IOException { String expectedContent = "$ curl 'http://localhost/upload' -i -X POST -H " @@ -258,9 +268,10 @@ public class CurlRequestSnippetTests extends AbstractSnippetTests { + "'metadata={\"description\": \"foo\"}'"; this.snippets.expectCurlRequest() .withContents(codeBlock("bash").content(expectedContent)); - new CurlRequestSnippet().document(this.operationBuilder - .request("http://localhost/upload").method("POST") - .header(HttpHeaders.CONTENT_TYPE, MediaType.MULTIPART_FORM_DATA_VALUE) + new CurlRequestSnippet().document( + this.operationBuilder.request("http://localhost/upload").method("POST") + .header(HttpHeaders.CONTENT_TYPE, + MediaType.MULTIPART_FORM_DATA_VALUE) .part("metadata", "{\"description\": \"foo\"}".getBytes()).build()); } @@ -275,9 +286,9 @@ public class CurlRequestSnippetTests extends AbstractSnippetTests { this.operationBuilder.request("http://localhost/upload").method("POST") .header(HttpHeaders.CONTENT_TYPE, MediaType.MULTIPART_FORM_DATA_VALUE) - .part("image", new byte[0]) - .header(HttpHeaders.CONTENT_TYPE, MediaType.IMAGE_PNG_VALUE) - .submittedFileName("documents/images/example.png").build()); + .part("image", new byte[0]) + .header(HttpHeaders.CONTENT_TYPE, MediaType.IMAGE_PNG_VALUE) + .submittedFileName("documents/images/example.png").build()); } @Test @@ -291,8 +302,8 @@ public class CurlRequestSnippetTests extends AbstractSnippetTests { this.operationBuilder.request("http://localhost/upload").method("POST") .header(HttpHeaders.CONTENT_TYPE, MediaType.MULTIPART_FORM_DATA_VALUE) - .part("image", new byte[0]) - .submittedFileName("documents/images/example.png").build()); + .part("image", new byte[0]) + .submittedFileName("documents/images/example.png").build()); } @Test @@ -307,9 +318,9 @@ public class CurlRequestSnippetTests extends AbstractSnippetTests { this.operationBuilder.request("http://localhost/upload").method("POST") .header(HttpHeaders.CONTENT_TYPE, MediaType.MULTIPART_FORM_DATA_VALUE) - .part("image", new byte[0]) - .submittedFileName("documents/images/example.png").and() - .param("a", "apple", "avocado").param("b", "banana").build()); + .part("image", new byte[0]) + .submittedFileName("documents/images/example.png").and() + .param("a", "apple", "avocado").param("b", "banana").build()); } @Test @@ -321,7 +332,7 @@ public class CurlRequestSnippetTests extends AbstractSnippetTests { .header(HttpHeaders.AUTHORIZATION, "Basic " + Base64Utils .encodeToString("user:secret".getBytes())) - .build()); + .build()); } @Test diff --git a/spring-restdocs-core/src/test/java/org/springframework/restdocs/cli/HttpieRequestSnippetTests.java b/spring-restdocs-core/src/test/java/org/springframework/restdocs/cli/HttpieRequestSnippetTests.java index d5dc8a39..acb12cb9 100644 --- a/spring-restdocs-core/src/test/java/org/springframework/restdocs/cli/HttpieRequestSnippetTests.java +++ b/spring-restdocs-core/src/test/java/org/springframework/restdocs/cli/HttpieRequestSnippetTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2016 the original author or authors. + * Copyright 2014-2017 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -252,6 +252,16 @@ public class HttpieRequestSnippetTests extends AbstractSnippetTests { .header("a", "alpha").build()); } + @Test + public void requestWithCookies() throws IOException { + this.snippets.expectHttpieRequest().withContents( + codeBlock("bash").content("$ http GET 'http://localhost/foo'" + + " 'Cookie:name1=value1' 'Cookie:name2=value2'")); + new HttpieRequestSnippet() + .document(this.operationBuilder.request("http://localhost/foo") + .cookie("name1", "value1").cookie("name2", "value2").build()); + } + @Test public void multipartPostWithNoSubmittedFileName() throws IOException { String expectedContent = String @@ -259,9 +269,10 @@ public class HttpieRequestSnippetTests extends AbstractSnippetTests { + " 'metadata'@<(echo '{\"description\": \"foo\"}')"); this.snippets.expectHttpieRequest() .withContents(codeBlock("bash").content(expectedContent)); - new HttpieRequestSnippet().document(this.operationBuilder - .request("http://localhost/upload").method("POST") - .header(HttpHeaders.CONTENT_TYPE, MediaType.MULTIPART_FORM_DATA_VALUE) + new HttpieRequestSnippet().document( + this.operationBuilder.request("http://localhost/upload").method("POST") + .header(HttpHeaders.CONTENT_TYPE, + MediaType.MULTIPART_FORM_DATA_VALUE) .part("metadata", "{\"description\": \"foo\"}".getBytes()).build()); } @@ -277,9 +288,9 @@ public class HttpieRequestSnippetTests extends AbstractSnippetTests { this.operationBuilder.request("http://localhost/upload").method("POST") .header(HttpHeaders.CONTENT_TYPE, MediaType.MULTIPART_FORM_DATA_VALUE) - .part("image", new byte[0]) - .header(HttpHeaders.CONTENT_TYPE, MediaType.IMAGE_PNG_VALUE) - .submittedFileName("documents/images/example.png").build()); + .part("image", new byte[0]) + .header(HttpHeaders.CONTENT_TYPE, MediaType.IMAGE_PNG_VALUE) + .submittedFileName("documents/images/example.png").build()); } @Test @@ -293,8 +304,8 @@ public class HttpieRequestSnippetTests extends AbstractSnippetTests { this.operationBuilder.request("http://localhost/upload").method("POST") .header(HttpHeaders.CONTENT_TYPE, MediaType.MULTIPART_FORM_DATA_VALUE) - .part("image", new byte[0]) - .submittedFileName("documents/images/example.png").build()); + .part("image", new byte[0]) + .submittedFileName("documents/images/example.png").build()); } @Test @@ -309,9 +320,9 @@ public class HttpieRequestSnippetTests extends AbstractSnippetTests { this.operationBuilder.request("http://localhost/upload").method("POST") .header(HttpHeaders.CONTENT_TYPE, MediaType.MULTIPART_FORM_DATA_VALUE) - .part("image", new byte[0]) - .submittedFileName("documents/images/example.png").and() - .param("a", "apple", "avocado").param("b", "banana").build()); + .part("image", new byte[0]) + .submittedFileName("documents/images/example.png").and() + .param("a", "apple", "avocado").param("b", "banana").build()); } @Test @@ -323,7 +334,7 @@ public class HttpieRequestSnippetTests extends AbstractSnippetTests { .header(HttpHeaders.AUTHORIZATION, "Basic " + Base64Utils .encodeToString("user:secret".getBytes())) - .build()); + .build()); } @Test diff --git a/spring-restdocs-core/src/test/java/org/springframework/restdocs/headers/RequestHeadersSnippetTests.java b/spring-restdocs-core/src/test/java/org/springframework/restdocs/headers/RequestHeadersSnippetTests.java index ef87c2f7..1f28ea11 100644 --- a/spring-restdocs-core/src/test/java/org/springframework/restdocs/headers/RequestHeadersSnippetTests.java +++ b/spring-restdocs-core/src/test/java/org/springframework/restdocs/headers/RequestHeadersSnippetTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2016 the original author or authors. + * Copyright 2014-2017 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -72,13 +72,9 @@ public class RequestHeadersSnippetTests extends AbstractSnippetTests { .header("Accept", "*/*") .header("Accept-Encoding", "gzip, deflate") - .header("Accept-Language", - "en-US,en;q=0.5") - .header("Cache-Control", - "max-age=0") - .header("Connection", - "keep-alive") - .build()); + .header("Accept-Language", "en-US,en;q=0.5") + .header("Cache-Control", "max-age=0") + .header("Connection", "keep-alive").build()); } @Test @@ -147,7 +143,7 @@ public class RequestHeadersSnippetTests extends AbstractSnippetTests { .header("X-Test", "test") .header("Accept-Encoding", "gzip, deflate") - .header("Accept", "*/*").build()); + .header("Accept", "*/*").build()); } @Test diff --git a/spring-restdocs-core/src/test/java/org/springframework/restdocs/http/HttpRequestSnippetTests.java b/spring-restdocs-core/src/test/java/org/springframework/restdocs/http/HttpRequestSnippetTests.java index 88c27ee1..4312770e 100644 --- a/spring-restdocs-core/src/test/java/org/springframework/restdocs/http/HttpRequestSnippetTests.java +++ b/spring-restdocs-core/src/test/java/org/springframework/restdocs/http/HttpRequestSnippetTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2016 the original author or authors. + * Copyright 2014-2017 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -80,6 +80,19 @@ public class HttpRequestSnippetTests extends AbstractSnippetTests { .request("http://localhost:8080/foo").header("Alpha", "a").build()); } + @Test + public void getRequestWithCookies() throws IOException { + this.snippets.expectHttpRequest() + .withContents(httpRequest(RequestMethod.GET, "/foo") + .header(HttpHeaders.HOST, "localhost") + .header(HttpHeaders.COOKIE, "name1=value1") + .header(HttpHeaders.COOKIE, "name2=value2")); + + new HttpRequestSnippet() + .document(this.operationBuilder.request("http://localhost/foo") + .cookie("name1", "value1").cookie("name2", "value2").build()); + } + @Test public void getRequestWithQueryString() throws IOException { this.snippets.expectHttpRequest() @@ -127,8 +140,8 @@ public class HttpRequestSnippetTests extends AbstractSnippetTests { String content = "Hello, world"; this.snippets.expectHttpRequest() .withContents(httpRequest(RequestMethod.POST, "/foo") - .header(HttpHeaders.HOST, "localhost").content(content).header( - HttpHeaders.CONTENT_LENGTH, content.getBytes().length)); + .header(HttpHeaders.HOST, "localhost").content(content) + .header(HttpHeaders.CONTENT_LENGTH, content.getBytes().length)); new HttpRequestSnippet().document(this.operationBuilder .request("http://localhost/foo").method("POST").content(content).build()); @@ -139,8 +152,8 @@ public class HttpRequestSnippetTests extends AbstractSnippetTests { String content = "Hello, world"; this.snippets.expectHttpRequest() .withContents(httpRequest(RequestMethod.POST, "/foo?a=alpha") - .header(HttpHeaders.HOST, "localhost").content(content).header( - HttpHeaders.CONTENT_LENGTH, content.getBytes().length)); + .header(HttpHeaders.HOST, "localhost").content(content) + .header(HttpHeaders.CONTENT_LENGTH, content.getBytes().length)); new HttpRequestSnippet() .document(this.operationBuilder.request("http://localhost/foo") @@ -153,8 +166,8 @@ public class HttpRequestSnippetTests extends AbstractSnippetTests { String content = "Hello, world"; this.snippets.expectHttpRequest() .withContents(httpRequest(RequestMethod.POST, "/foo?b=bravo&a=alpha") - .header(HttpHeaders.HOST, "localhost").content(content).header( - HttpHeaders.CONTENT_LENGTH, content.getBytes().length)); + .header(HttpHeaders.HOST, "localhost").content(content) + .header(HttpHeaders.CONTENT_LENGTH, content.getBytes().length)); new HttpRequestSnippet() .document(this.operationBuilder.request("http://localhost/foo?b=bravo") @@ -167,8 +180,8 @@ public class HttpRequestSnippetTests extends AbstractSnippetTests { String content = "Hello, world"; this.snippets.expectHttpRequest() .withContents(httpRequest(RequestMethod.POST, "/foo?b=bravo&a=alpha") - .header(HttpHeaders.HOST, "localhost").content(content).header( - HttpHeaders.CONTENT_LENGTH, content.getBytes().length)); + .header(HttpHeaders.HOST, "localhost").content(content) + .header(HttpHeaders.CONTENT_LENGTH, content.getBytes().length)); new HttpRequestSnippet().document(this.operationBuilder .request("http://localhost/foo?b=bravo").method("POST") @@ -181,8 +194,8 @@ public class HttpRequestSnippetTests extends AbstractSnippetTests { String content = "Hello, world"; this.snippets.expectHttpRequest() .withContents(httpRequest(RequestMethod.POST, "/foo?b=bravo&a=alpha") - .header(HttpHeaders.HOST, "localhost").content(content).header( - HttpHeaders.CONTENT_LENGTH, content.getBytes().length)); + .header(HttpHeaders.HOST, "localhost").content(content) + .header(HttpHeaders.CONTENT_LENGTH, content.getBytes().length)); new HttpRequestSnippet().document(this.operationBuilder .request("http://localhost/foo?b=bravo&a=alpha").method("POST") @@ -236,8 +249,8 @@ public class HttpRequestSnippetTests extends AbstractSnippetTests { String content = "Hello, world"; this.snippets.expectHttpRequest() .withContents(httpRequest(RequestMethod.PUT, "/foo") - .header(HttpHeaders.HOST, "localhost").content(content).header( - HttpHeaders.CONTENT_LENGTH, content.getBytes().length)); + .header(HttpHeaders.HOST, "localhost").content(content) + .header(HttpHeaders.CONTENT_LENGTH, content.getBytes().length)); new HttpRequestSnippet().document(this.operationBuilder .request("http://localhost/foo").method("PUT").content(content).build()); @@ -269,7 +282,7 @@ public class HttpRequestSnippetTests extends AbstractSnippetTests { this.operationBuilder.request("http://localhost/upload").method("POST") .header(HttpHeaders.CONTENT_TYPE, MediaType.MULTIPART_FORM_DATA_VALUE) - .part("image", "<< data >>".getBytes()).build()); + .part("image", "<< data >>".getBytes()).build()); } @Test @@ -295,8 +308,8 @@ public class HttpRequestSnippetTests extends AbstractSnippetTests { this.operationBuilder.request("http://localhost/upload").method("POST") .header(HttpHeaders.CONTENT_TYPE, MediaType.MULTIPART_FORM_DATA_VALUE) - .param("a", "apple", "avocado").param("b", "banana") - .part("image", "<< data >>".getBytes()).build()); + .param("a", "apple", "avocado").param("b", "banana") + .part("image", "<< data >>".getBytes()).build()); } @Test @@ -332,9 +345,8 @@ public class HttpRequestSnippetTests extends AbstractSnippetTests { this.operationBuilder.request("http://localhost/upload").method("POST") .header(HttpHeaders.CONTENT_TYPE, MediaType.MULTIPART_FORM_DATA_VALUE) - .part("image", "<< data >>".getBytes()) - .header(HttpHeaders.CONTENT_TYPE, MediaType.IMAGE_PNG_VALUE) - .build()); + .part("image", "<< data >>".getBytes()) + .header(HttpHeaders.CONTENT_TYPE, MediaType.IMAGE_PNG_VALUE).build()); } @Test diff --git a/spring-restdocs-core/src/test/java/org/springframework/restdocs/test/OperationBuilder.java b/spring-restdocs-core/src/test/java/org/springframework/restdocs/test/OperationBuilder.java index 698a80da..6d210b5f 100644 --- a/spring-restdocs-core/src/test/java/org/springframework/restdocs/test/OperationBuilder.java +++ b/spring-restdocs-core/src/test/java/org/springframework/restdocs/test/OperationBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2016 the original author or authors. + * Copyright 2014-2017 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,11 +19,14 @@ package org.springframework.restdocs.test; import java.io.File; import java.net.URI; import java.util.ArrayList; +import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; +import javax.servlet.http.Cookie; + import org.junit.runners.model.Statement; import org.springframework.http.HttpHeaders; @@ -153,6 +156,8 @@ public class OperationBuilder extends OperationTestRule { private List partBuilders = new ArrayList<>(); + private Collection cookies = new ArrayList<>(); + private OperationRequestBuilder(String uri) { this.requestUri = URI.create(uri); } @@ -163,7 +168,7 @@ public class OperationBuilder extends OperationTestRule { parts.add(builder.buildPart()); } return new OperationRequestFactory().create(this.requestUri, this.method, - this.content, this.headers, this.parameters, parts); + this.content, this.headers, this.parameters, parts, this.cookies); } public Operation build() { @@ -209,6 +214,11 @@ public class OperationBuilder extends OperationTestRule { return partBuilder; } + public OperationRequestBuilder cookie(String name, String value) { + this.cookies.add(new Cookie(name, value)); + return this; + } + /** * Basic builder API for creating an {@link OperationRequestPart}. */ diff --git a/spring-restdocs-mockmvc/src/main/java/org/springframework/restdocs/mockmvc/MockMvcRequestConverter.java b/spring-restdocs-mockmvc/src/main/java/org/springframework/restdocs/mockmvc/MockMvcRequestConverter.java index e933a0e0..2aeb6119 100644 --- a/spring-restdocs-mockmvc/src/main/java/org/springframework/restdocs/mockmvc/MockMvcRequestConverter.java +++ b/spring-restdocs-mockmvc/src/main/java/org/springframework/restdocs/mockmvc/MockMvcRequestConverter.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2016 the original author or authors. + * Copyright 2014-2017 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,10 +21,14 @@ import java.io.PrintWriter; import java.io.StringWriter; import java.net.URI; import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; import java.util.List; import java.util.Map.Entry; import javax.servlet.ServletException; +import javax.servlet.http.Cookie; import javax.servlet.http.Part; import org.springframework.http.HttpHeaders; @@ -67,6 +71,7 @@ class MockMvcRequestConverter implements RequestConverter parts = extractParts(mockRequest); + Collection cookies = extractCookies(mockRequest); String queryString = mockRequest.getQueryString(); if (!StringUtils.hasText(queryString) && "GET".equals(mockRequest.getMethod())) { @@ -78,13 +83,21 @@ class MockMvcRequestConverter implements RequestConverter extractCookies(MockHttpServletRequest mockRequest) { + if (mockRequest.getCookies() != null) { + return Arrays.asList(mockRequest.getCookies()); + } + + return Collections.emptyList(); + } + private List extractParts(MockHttpServletRequest servletRequest) throws IOException, ServletException { List parts = new ArrayList<>(); diff --git a/spring-restdocs-mockmvc/src/test/java/org/springframework/restdocs/mockmvc/MockMvcRequestConverterTests.java b/spring-restdocs-mockmvc/src/test/java/org/springframework/restdocs/mockmvc/MockMvcRequestConverterTests.java index 9304dd51..d2a18373 100644 --- a/spring-restdocs-mockmvc/src/test/java/org/springframework/restdocs/mockmvc/MockMvcRequestConverterTests.java +++ b/spring-restdocs-mockmvc/src/test/java/org/springframework/restdocs/mockmvc/MockMvcRequestConverterTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2016 the original author or authors. + * Copyright 2014-2017 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,7 +19,9 @@ package org.springframework.restdocs.mockmvc; import java.io.ByteArrayInputStream; import java.net.URI; import java.util.Arrays; +import java.util.Iterator; +import javax.servlet.http.Cookie; import javax.servlet.http.Part; import org.junit.Test; @@ -88,6 +90,26 @@ public class MockMvcRequestConverterTests { assertThat(request.getHeaders(), hasEntry("b", Arrays.asList("bravo"))); } + @Test + public void requestWithCookies() throws Exception { + OperationRequest request = createOperationRequest(MockMvcRequestBuilders + .get("/foo").cookie(new Cookie("cookieName1", "cookieVal1"), + new Cookie("cookieName2", "cookieVal2"))); + assertThat(request.getUri(), is(URI.create("http://localhost/foo"))); + assertThat(request.getMethod(), is(HttpMethod.GET)); + assertThat(request.getCookies().size(), is(equalTo(2))); + + Iterator cookieIterator = request.getCookies().iterator(); + + Cookie cookie1 = cookieIterator.next(); + assertThat(cookie1.getName(), is(equalTo("cookieName1"))); + assertThat(cookie1.getValue(), is(equalTo("cookieVal1"))); + + Cookie cookie2 = cookieIterator.next(); + assertThat(cookie2.getName(), is(equalTo("cookieName2"))); + assertThat(cookie2.getValue(), is(equalTo("cookieVal2"))); + } + @Test public void httpsRequest() throws Exception { MockHttpServletRequest mockRequest = MockMvcRequestBuilders.get("/foo") diff --git a/spring-restdocs-mockmvc/src/test/java/org/springframework/restdocs/mockmvc/MockMvcRestDocumentationIntegrationTests.java b/spring-restdocs-mockmvc/src/test/java/org/springframework/restdocs/mockmvc/MockMvcRestDocumentationIntegrationTests.java index cd47c51f..77b2136a 100644 --- a/spring-restdocs-mockmvc/src/test/java/org/springframework/restdocs/mockmvc/MockMvcRestDocumentationIntegrationTests.java +++ b/spring-restdocs-mockmvc/src/test/java/org/springframework/restdocs/mockmvc/MockMvcRestDocumentationIntegrationTests.java @@ -24,6 +24,8 @@ import java.util.HashMap; import java.util.Map; import java.util.regex.Pattern; +import javax.servlet.http.Cookie; + import org.junit.After; import org.junit.Before; import org.junit.Rule; @@ -159,6 +161,22 @@ public class MockMvcRestDocumentationIntegrationTests { + "-H 'Accept: application/json' -d 'content'")))); } + @Test + public void curlSnippetWithCookies() throws Exception { + MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(this.context) + .apply(documentationConfiguration(this.restDocumentation)).build(); + + mockMvc.perform(get("/").accept(MediaType.APPLICATION_JSON) + .cookie(new Cookie("cookieName", "cookieVal"))).andExpect(status().isOk()) + .andDo(document("curl-snippet-with-cookies")); + assertThat( + new File( + "build/generated-snippets/curl-snippet-with-cookies/curl-request.adoc"), + is(snippet(asciidoctor()).withContents(codeBlock(asciidoctor(), "bash") + .content("$ curl " + "'http://localhost:8080/' -i " + + "-H 'Accept: application/json' --cookie 'cookieName=cookieVal'")))); + } + @Test public void curlSnippetWithQueryStringOnPost() throws Exception { MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(this.context) @@ -207,6 +225,22 @@ public class MockMvcRestDocumentationIntegrationTests { + " 'Accept:application/json'")))); } + @Test + public void httpieSnippetWithCookies() throws Exception { + MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(this.context) + .apply(documentationConfiguration(this.restDocumentation)).build(); + + mockMvc.perform(get("/").accept(MediaType.APPLICATION_JSON) + .cookie(new Cookie("cookieName", "cookieVal"))).andExpect(status().isOk()) + .andDo(document("httpie-snippet-with-cookies")); + assertThat( + new File( + "build/generated-snippets/httpie-snippet-with-cookies/httpie-request.adoc"), + is(snippet(asciidoctor()).withContents(codeBlock(asciidoctor(), "bash") + .content("$ http GET 'http://localhost:8080/'" + + " 'Accept:application/json' 'Cookie:cookieName=cookieVal'")))); + } + @Test public void httpieSnippetWithQueryStringOnPost() throws Exception { MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(this.context) diff --git a/spring-restdocs-restassured/src/main/java/org/springframework/restdocs/restassured/RestAssuredRequestConverter.java b/spring-restdocs-restassured/src/main/java/org/springframework/restdocs/restassured/RestAssuredRequestConverter.java index 1673366a..6b64c6a3 100644 --- a/spring-restdocs-restassured/src/main/java/org/springframework/restdocs/restassured/RestAssuredRequestConverter.java +++ b/spring-restdocs-restassured/src/main/java/org/springframework/restdocs/restassured/RestAssuredRequestConverter.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2016 the original author or authors. + * Copyright 2014-2017 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -25,6 +25,7 @@ import java.util.Collection; import java.util.List; import java.util.Map.Entry; +import com.jayway.restassured.response.Cookie; import com.jayway.restassured.response.Header; import com.jayway.restassured.specification.FilterableRequestSpecification; import com.jayway.restassured.specification.MultiPartSpecification; @@ -55,7 +56,18 @@ class RestAssuredRequestConverter return new OperationRequestFactory().create(URI.create(requestSpec.getURI()), HttpMethod.valueOf(requestSpec.getMethod().name()), extractContent(requestSpec), extractHeaders(requestSpec), - extractParameters(requestSpec), extractParts(requestSpec)); + extractParameters(requestSpec), extractParts(requestSpec), + extractCookies(requestSpec)); + } + + private Collection extractCookies( + FilterableRequestSpecification requestSpec) { + Collection cookies = new ArrayList<>(); + for (Cookie cookie : requestSpec.getCookies()) { + cookies.add( + new javax.servlet.http.Cookie(cookie.getName(), cookie.getValue())); + } + return cookies; } private byte[] extractContent(FilterableRequestSpecification requestSpec) { diff --git a/spring-restdocs-restassured/src/test/java/org/springframework/restdocs/restassured/RestAssuredRequestConverterTests.java b/spring-restdocs-restassured/src/test/java/org/springframework/restdocs/restassured/RestAssuredRequestConverterTests.java index 562a8260..4617cb30 100644 --- a/spring-restdocs-restassured/src/test/java/org/springframework/restdocs/restassured/RestAssuredRequestConverterTests.java +++ b/spring-restdocs-restassured/src/test/java/org/springframework/restdocs/restassured/RestAssuredRequestConverterTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2016 the original author or authors. + * Copyright 2014-2017 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -25,6 +25,8 @@ import java.util.Arrays; import java.util.Collection; import java.util.Iterator; +import javax.servlet.http.Cookie; + import com.jayway.restassured.RestAssured; import com.jayway.restassured.specification.FilterableRequestSpecification; import com.jayway.restassured.specification.RequestSpecification; @@ -143,6 +145,26 @@ public class RestAssuredRequestConverterTests { is(equalTo(Arrays.asList("localhost:" + this.port)))); } + @Test + public void cookies() { + RequestSpecification requestSpec = RestAssured.given().port(this.port) + .cookie("cookie1", "cookieVal1").cookie("cookie2", "cookieVal2"); + requestSpec.get("/"); + OperationRequest request = this.factory + .convert((FilterableRequestSpecification) requestSpec); + assertThat(request.getCookies().size(), is(equalTo(2))); + + Iterator cookieIterator = request.getCookies().iterator(); + Cookie cookie1 = cookieIterator.next(); + + assertThat(cookie1.getName(), is(equalTo("cookie1"))); + assertThat(cookie1.getValue(), is(equalTo("cookieVal1"))); + + Cookie cookie2 = cookieIterator.next(); + assertThat(cookie2.getName(), is(equalTo("cookie2"))); + assertThat(cookie2.getValue(), is(equalTo("cookieVal2"))); + } + @Test public void multipart() { RequestSpecification requestSpec = RestAssured.given().port(this.port) diff --git a/spring-restdocs-restassured/src/test/java/org/springframework/restdocs/restassured/RestAssuredRestDocumentationIntegrationTests.java b/spring-restdocs-restassured/src/test/java/org/springframework/restdocs/restassured/RestAssuredRestDocumentationIntegrationTests.java index da43824b..07d62682 100644 --- a/spring-restdocs-restassured/src/test/java/org/springframework/restdocs/restassured/RestAssuredRestDocumentationIntegrationTests.java +++ b/spring-restdocs-restassured/src/test/java/org/springframework/restdocs/restassured/RestAssuredRestDocumentationIntegrationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2016 the original author or authors. + * Copyright 2014-2017 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -119,6 +119,23 @@ public class RestAssuredRestDocumentationIntegrationTests { + "-d 'content'")))); } + @Test + public void curlSnippetWithCookies() throws Exception { + String contentType = "text/plain; charset=UTF-8"; + given().port(this.port).filter(documentationConfiguration(this.restDocumentation)) + .filter(document("curl-snippet-with-cookies")).accept("application/json") + .contentType(contentType).cookie("cookieName", "cookieVal").get("/") + .then().statusCode(200); + assertThat( + new File( + "build/generated-snippets/curl-snippet-with-cookies/curl-request.adoc"), + is(snippet(asciidoctor()).withContents(codeBlock(asciidoctor(), "bash") + .content("$ curl 'http://localhost:" + this.port + "/' -i " + + "-H 'Accept: application/json' " + "-H 'Content-Type: " + + contentType + "' " + + "--cookie 'cookieName=cookieVal'")))); + } + @Test public void curlSnippetWithQueryStringOnPost() throws Exception { given().port(this.port).filter(documentationConfiguration(this.restDocumentation))