Add support for documenting request and response cookies

See gh-592
This commit is contained in:
clydebarrow
2019-03-07 14:26:31 +11:00
committed by Andy Wilkinson
parent 15980d7486
commit f72a9f1067
38 changed files with 1572 additions and 17 deletions

View File

@@ -0,0 +1,145 @@
/*
* 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.
* You may obtain a copy of the License at
*
* https://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 org.springframework.restdocs.cookies;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.springframework.restdocs.operation.Operation;
import org.springframework.restdocs.snippet.SnippetException;
import org.springframework.restdocs.snippet.TemplatedSnippet;
import org.springframework.util.Assert;
/**
* Abstract {@link TemplatedSnippet} subclass that provides a base for snippets that
* document a RESTful resource's request or response cookies.
*
* @author Andreas Evers
* @author Clyde Stubbs
* @since 2.1
*/
public abstract class AbstractCookiesSnippet extends TemplatedSnippet {
private List<CookieDescriptor> cookieDescriptors;
protected final boolean ignoreUndocumentedCookies;
private String type;
/**
* Creates a new {@code AbstractCookiesSnippet} that will produce a snippet named
* {@code <type>-cookies}. The cookies will be documented using the given
* {@code descriptors} and the given {@code attributes} will be included in the model
* during template rendering.
* @param type the type of the cookies
* @param descriptors the cookie descriptors
* @param attributes the additional attributes
* @param ignoreUndocumentedCookies whether undocumented cookies should be ignored
*/
protected AbstractCookiesSnippet(String type, List<CookieDescriptor> descriptors, Map<String, Object> attributes,
boolean ignoreUndocumentedCookies) {
super(type + "-cookies", attributes);
for (CookieDescriptor descriptor : descriptors) {
Assert.notNull(descriptor.getName(), "The name of the cookie must not be null");
if (!descriptor.isIgnored()) {
Assert.notNull(descriptor.getDescription(), "The description of the cookie must not be null");
}
}
this.cookieDescriptors = descriptors;
this.type = type;
this.ignoreUndocumentedCookies = ignoreUndocumentedCookies;
}
@Override
protected Map<String, Object> createModel(Operation operation) {
validateCookieDocumentation(operation);
Map<String, Object> model = new HashMap<>();
List<Map<String, Object>> cookies = new ArrayList<>();
model.put("cookies", cookies);
for (CookieDescriptor descriptor : this.cookieDescriptors) {
cookies.add(createModelForDescriptor(descriptor));
}
return model;
}
private void validateCookieDocumentation(Operation operation) {
List<CookieDescriptor> missingCookies = findMissingCookies(operation);
if (!missingCookies.isEmpty()) {
List<String> names = new ArrayList<>();
for (CookieDescriptor cookieDescriptor : missingCookies) {
names.add(cookieDescriptor.getName());
}
throw new SnippetException(
"Cookies with the following names were not found" + " in the " + this.type + ": " + names);
}
}
/**
* Finds the cookies that are missing from the operation. A cookie is missing if it is
* described by one of the {@code cookieDescriptors} but is not present in the
* operation.
* @param operation the operation
* @return descriptors for the cookies that are missing from the operation
*/
protected List<CookieDescriptor> findMissingCookies(Operation operation) {
List<CookieDescriptor> missingCookies = new ArrayList<>();
Set<String> actualCookies = extractActualCookies(operation);
for (CookieDescriptor cookieDescriptor : this.cookieDescriptors) {
if (!cookieDescriptor.isOptional() && !actualCookies.contains(cookieDescriptor.getName())) {
missingCookies.add(cookieDescriptor);
}
}
return missingCookies;
}
/**
* Extracts the names of the cookies from the request or response of the given
* {@code operation}.
* @param operation the operation
* @return the cookie names
*/
protected abstract Set<String> extractActualCookies(Operation operation);
/**
* Returns the list of {@link CookieDescriptor CookieDescriptors} that will be used to
* generate the documentation.
* @return the cookie descriptors
*/
protected final List<CookieDescriptor> getCookieDescriptors() {
return this.cookieDescriptors;
}
/**
* Returns a model for the given {@code descriptor}.
* @param descriptor the descriptor
* @return the model
*/
protected Map<String, Object> createModelForDescriptor(CookieDescriptor descriptor) {
Map<String, Object> model = new HashMap<>();
model.put("name", descriptor.getName());
model.put("description", descriptor.getDescription());
model.put("optional", descriptor.isOptional());
model.putAll(descriptor.getAttributes());
return model;
}
}

View File

@@ -0,0 +1,69 @@
/*
* Copyright 2014-2015 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.
* You may obtain a copy of the License at
*
* https://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 org.springframework.restdocs.cookies;
import org.springframework.restdocs.snippet.IgnorableDescriptor;
/**
* A description of a cookie found in a request or response.
*
* @author Andreas Evers
* @author Clyde Stubbs
* @since 2.1
* @see CookieDocumentation#cookieWithName(String)
*/
public class CookieDescriptor extends IgnorableDescriptor<CookieDescriptor> {
private final String name;
private boolean optional;
/**
* Creates a new {@code CookieDescriptor} describing the cookie with the given
* {@code name}.
* @param name the name
*/
protected CookieDescriptor(String name) {
this.name = name;
}
/**
* Marks the cookie as optional.
* @return {@code this}
*/
public final CookieDescriptor optional() {
this.optional = true;
return this;
}
/**
* Returns the name for the cookie.
* @return the cookie name
*/
public final String getName() {
return this.name;
}
/**
* Returns {@code true} if the described cookie is optional, otherwise {@code false}.
* @return {@code true} if the described cookie is optional, otherwise {@code false}
*/
public final boolean isOptional() {
return this.optional;
}
}

View File

@@ -0,0 +1,232 @@
/*
* Copyright 2014-2016 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.
* You may obtain a copy of the License at
*
* https://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 org.springframework.restdocs.cookies;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import org.springframework.restdocs.snippet.Snippet;
/**
* Static factory methods for documenting a RESTful API's request and response cookies.
*
* @author Andreas Evers
* @author Andy Wilkinson
* @author Marcel Overdijk
* @author Clyde Stubbs
* @since 2.1
*/
public abstract class CookieDocumentation {
private CookieDocumentation() {
}
/**
* Creates a {@code CookieDescriptor} that describes a cookie with the given
* {@code name}.
* @param name the name of the cookie
* @return a {@code CookieDescriptor} ready for further configuration
*/
public static CookieDescriptor cookieWithName(String name) {
return new CookieDescriptor(name);
}
/**
* Returns a new {@link Snippet} that will document the cookies of the API operation's
* request. The cookies will be documented using the given {@code descriptors}.
* <p>
* If a cookie is documented, is not marked as optional, and is not present in the
* request, a failure will occur.
* @param descriptors the descriptions of the request's cookies
* @return the snippet that will document the request cookies
* @see #cookieWithName(String)
*/
public static RequestCookiesSnippet requestCookies(CookieDescriptor... descriptors) {
return requestCookies(Arrays.asList(descriptors));
}
/**
* Returns a new {@link Snippet} that will document the cookies of the API operation's
* request. The cookies will be documented using the given {@code descriptors}.
* <p>
* If a cookie is documented, is not marked as optional, and is not present in the
* request, a failure will occur.
* @param descriptors the descriptions of the request's cookies
* @return the snippet that will document the request cookies
* @see #cookieWithName(String)
*/
public static RequestCookiesSnippet requestCookies(List<CookieDescriptor> descriptors) {
return new RequestCookiesSnippet(descriptors);
}
/**
* Returns a new {@link Snippet} that will document the cookies of the API
* operations's request. The given {@code attributes} will be available during snippet
* generation and the cookies will be documented using the given {@code descriptors}.
* <p>
* If a cookie is documented, is not marked as optional, and is not present in the
* request, a failure will occur.
* @param attributes the attributes
* @param descriptors the descriptions of the request's cookies
* @return the snippet that will document the request cookies
* @see #cookieWithName(String)
*/
public static RequestCookiesSnippet requestCookies(Map<String, Object> attributes,
CookieDescriptor... descriptors) {
return requestCookies(attributes, Arrays.asList(descriptors));
}
/**
* Returns a new {@link Snippet} that will document the cookies of the API
* operations's request. The given {@code attributes} will be available during snippet
* generation and the cookies will be documented using the given {@code descriptors}.
* <p>
* If a cookie is documented, is not marked as optional, and is not present in the
* request, a failure will occur. Any cookies present in the request that are not
* documented will result in an error.
* @param attributes the attributes
* @param descriptors the descriptions of the request's cookies
* @return the snippet that will document the request cookies
* @see #cookieWithName(String)
*/
public static RequestCookiesSnippet requestCookies(Map<String, Object> attributes,
List<CookieDescriptor> descriptors) {
return new RequestCookiesSnippet(descriptors, attributes, false);
}
/**
* Returns a new {@link Snippet} that will document the cookies of the API
* operations's request. The given {@code attributes} will be available during snippet
* generation and the cookies will be documented using the given {@code descriptors}.
* <p>
* If a cookie is documented, is not marked as optional, and is not present in the
* request, a failure will occur. An undocumented cookie in the request will not
* generate an error.
* @param attributes the attributes
* @param descriptors the descriptions of the request's cookies
* @return the snippet that will document the request cookies
* @see #cookieWithName(String)
*/
public static RequestCookiesSnippet relaxedRequestCookies(Map<String, Object> attributes,
List<CookieDescriptor> descriptors) {
return new RequestCookiesSnippet(descriptors, attributes, true);
}
/**
* Returns a new {@link Snippet} that will document the cookies of the API operation's
* response. The cookies will be documented using the given {@code descriptors}.
* <p>
* If a cookie is documented, is not marked as optional or ignored, and is not present
* in the request, a failure will occur.
* @param descriptors the descriptions of the response's cookies
* @return the snippet that will document the response cookies
* @see #cookieWithName(String)
*/
public static ResponseCookiesSnippet responseCookies(CookieDescriptor... descriptors) {
return responseCookies(Arrays.asList(descriptors));
}
/**
* Returns a new {@link Snippet} that will document the cookies of the API operation's
* response. The cookies will be documented using the given {@code descriptors}.
* <p>
* If a cookie is documented, is not marked as optional or ignored, and is not present
* in the request, a failure will occur. If a cookie is present in the response but is
* undocumented a failure will occur.
* @param descriptors the descriptions of the response's cookies
* @return the snippet that will document the response cookies
* @see #cookieWithName(String)
*/
public static ResponseCookiesSnippet responseCookies(List<CookieDescriptor> descriptors) {
return new ResponseCookiesSnippet(descriptors);
}
/**
* Returns a new {@link Snippet} that will document the cookies of the API operation's
* response. The cookies will be documented using the given {@code descriptors}.
* <p>
* If a cookie is documented, is not marked as optional or ignored, and is not present
* in the request, a failure will occur. No failure will occur if a cookie is present
* but undocumented.
* @param descriptors the descriptions of the response's cookies
* @return the snippet that will document the response cookies
* @see #cookieWithName(String)
*/
public static ResponseCookiesSnippet relaxedResponseCookies(List<CookieDescriptor> descriptors) {
return new ResponseCookiesSnippet(descriptors, null, true);
}
/**
* Returns a new {@link Snippet} that will document the cookies of the API
* operations's response. The given {@code attributes} will be available during
* snippet generation and the cookies will be documented using the given
* {@code descriptors}.
* <p>
* If a cookie is documented, is not marked as optional, and is not present in the
* response, a failure will occur. If a cookie is present in the response but is
* undocumented a failure will occur.
* @param attributes the attributes
* @param descriptors the descriptions of the response's cookies
* @return the snippet that will document the response cookies
* @see #cookieWithName(String)
*/
public static ResponseCookiesSnippet responseCookies(Map<String, Object> attributes,
CookieDescriptor... descriptors) {
return responseCookies(attributes, Arrays.asList(descriptors));
}
/**
* Returns a new {@link Snippet} that will document the cookies of the API
* operations's response. The given {@code attributes} will be available during
* snippet generation and the cookies will be documented using the given
* {@code descriptors}.
* <p>
* If a cookie is documented, is not marked as optional, and is not present in the
* response, a failure will occur. If a cookie is present in the response but is
* undocumented a failure will occur.
* @param attributes the attributes
* @param descriptors the descriptions of the response's cookies
* @return the snippet that will document the response cookies
* @see #cookieWithName(String)
*/
public static ResponseCookiesSnippet responseCookies(Map<String, Object> attributes,
List<CookieDescriptor> descriptors) {
return new ResponseCookiesSnippet(descriptors, attributes, false);
}
/**
* Returns a new {@link Snippet} that will document the cookies of the API
* operations's response. The given {@code attributes} will be available during
* snippet generation and the cookies will be documented using the given
* {@code descriptors}.
* <p>
* If a cookie is documented, is not marked as optional, and is not present in the
* response, a failure will occur. No failure will occur if a cookie is present but
* undocumented.
* @param attributes the attributes
* @param descriptors the descriptions of the response's cookies
* @return the snippet that will document the response cookies
* @see #cookieWithName(String)
*/
public static ResponseCookiesSnippet relaxedResponseCookies(Map<String, Object> attributes,
List<CookieDescriptor> descriptors) {
return new ResponseCookiesSnippet(descriptors, attributes, true);
}
}

View File

@@ -0,0 +1,109 @@
/*
* Copyright 2014-2016 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.
* You may obtain a copy of the License at
*
* https://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 org.springframework.restdocs.cookies;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.springframework.restdocs.operation.Operation;
import org.springframework.restdocs.operation.RequestCookie;
import org.springframework.restdocs.snippet.Snippet;
/**
* A {@link Snippet} that documents the cookies in a request.
*
* @author Andreas Evers
* @author Andy Wilkinson
* @author Clyde Stubbs
* @since 2.1
* @see CookieDocumentation#requestCookies(CookieDescriptor...)
* @see CookieDocumentation#requestCookies(Map, CookieDescriptor...)
*/
public class RequestCookiesSnippet extends AbstractCookiesSnippet {
/**
* Creates a new {@code RequestCookiesSnippet} that will document the cookies in the
* request using the given {@code descriptors}.
* @param descriptors the descriptors
*/
protected RequestCookiesSnippet(List<CookieDescriptor> descriptors) {
this(descriptors, null, false);
}
/**
* Creates a new {@code RequestCookiesSnippet} that will document the cookies in the
* request using the given {@code descriptors}. The given {@code attributes} will be
* included in the model during template rendering.
* @param descriptors the descriptors
* @param attributes the additional attributes
* @param ignoreUndocumentedCookies if set undocumented cookies will be ignored
*/
protected RequestCookiesSnippet(List<CookieDescriptor> descriptors, Map<String, Object> attributes,
boolean ignoreUndocumentedCookies) {
super("request", descriptors, attributes, ignoreUndocumentedCookies);
}
/**
* Creates a new {@code RequestCookiesSnippet} that will document the cookies in the
* request using the given {@code descriptors}. The given {@code attributes} will be
* included in the model during template rendering. Undocumented cookies will not be
* ignored.
* @param descriptors the descriptors
* @param attributes the additional attributes
*/
protected RequestCookiesSnippet(List<CookieDescriptor> descriptors, Map<String, Object> attributes) {
super("request", descriptors, attributes, false);
}
@Override
protected Set<String> extractActualCookies(Operation operation) {
HashSet<String> actualCookies = new HashSet<>();
for (RequestCookie cookie : operation.getRequest().getCookies()) {
actualCookies.add(cookie.getName());
}
return actualCookies;
}
/**
* Returns a new {@code RequestCookiesSnippet} configured with this snippet's
* attributes and its descriptors combined with the given
* {@code additionalDescriptors}.
* @param additionalDescriptors the additional descriptors
* @return the new snippet
*/
public final RequestCookiesSnippet and(CookieDescriptor... additionalDescriptors) {
return and(Arrays.asList(additionalDescriptors));
}
/**
* Returns a new {@code RequestCookiesSnippet} configured with this snippet's
* attributes and its descriptors combined with the given
* {@code additionalDescriptors}.
* @param additionalDescriptors the additional descriptors
* @return the new snippet
*/
public final RequestCookiesSnippet and(List<CookieDescriptor> additionalDescriptors) {
List<CookieDescriptor> combinedDescriptors = new ArrayList<>(this.getCookieDescriptors());
combinedDescriptors.addAll(additionalDescriptors);
return new RequestCookiesSnippet(combinedDescriptors, getAttributes(), false);
}
}

View File

@@ -0,0 +1,105 @@
/*
* Copyright 2014-2016 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.
* You may obtain a copy of the License at
*
* https://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 org.springframework.restdocs.cookies;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import org.springframework.restdocs.operation.Operation;
import org.springframework.restdocs.operation.ResponseCookie;
import org.springframework.restdocs.snippet.Snippet;
/**
* A {@link Snippet} that documents the cookies in a response.
*
* @author Andreas Evers
* @author Andy Wilkinson
* @author Clyde Stubbs
* @since 2.1
* @see CookieDocumentation#responseCookies(CookieDescriptor...)
* @see CookieDocumentation#responseCookies(Map, CookieDescriptor...)
*/
public class ResponseCookiesSnippet extends AbstractCookiesSnippet {
/**
* Creates a new {@code ResponseCookiesSnippet} that will document the cookies in the
* response using the given {@code descriptors}.
* @param descriptors the descriptors
*/
protected ResponseCookiesSnippet(List<CookieDescriptor> descriptors) {
this(descriptors, null, false);
}
/**
* Creates a new {@code ResponseCookiesSnippet} that will document the cookies in the
* response using the given {@code descriptors}. The given {@code attributes} will be
* included in the model during template rendering. Undocumented cookies will cause a
* failure.
* @param descriptors the descriptors
* @param attributes the additional attributes
*/
protected ResponseCookiesSnippet(List<CookieDescriptor> descriptors, Map<String, Object> attributes) {
super("response", descriptors, attributes, false);
}
/**
* Creates a new {@code ResponseCookiesSnippet} that will document the cookies in the
* response using the given {@code descriptors}. The given {@code attributes} will be
* included in the model during template rendering.
* @param descriptors the descriptors
* @param attributes the additional attributes
* @param ignoreUndocumentedCookies ignore any cookies that are undocumented
*/
protected ResponseCookiesSnippet(List<CookieDescriptor> descriptors, Map<String, Object> attributes,
boolean ignoreUndocumentedCookies) {
super("response", descriptors, attributes, ignoreUndocumentedCookies);
}
@Override
protected Set<String> extractActualCookies(Operation operation) {
return operation.getResponse().getCookies().stream().map(ResponseCookie::getName).collect(Collectors.toSet());
}
/**
* Returns a new {@code ResponseCookiesSnippet} configured with this snippet's
* attributes and its descriptors combined with the given
* {@code additionalDescriptors}.
* @param additionalDescriptors the additional descriptors
* @return the new snippet
*/
public final ResponseCookiesSnippet and(CookieDescriptor... additionalDescriptors) {
return and(Arrays.asList(additionalDescriptors));
}
/**
* Returns a new {@code ResponseCookiesSnippet} configured with this snippet's
* attributes and its descriptors combined with the given
* {@code additionalDescriptors}.
* @param additionalDescriptors the additional descriptors
* @return the new snippet
*/
public final ResponseCookiesSnippet and(List<CookieDescriptor> additionalDescriptors) {
List<CookieDescriptor> combinedDescriptors = new ArrayList<>(this.getCookieDescriptors());
combinedDescriptors.addAll(additionalDescriptors);
return new ResponseCookiesSnippet(combinedDescriptors, getAttributes(), this.ignoreUndocumentedCookies);
}
}

View File

@@ -0,0 +1,20 @@
/*
* Copyright 2014-2015 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.
* You may obtain a copy of the License at
*
* https://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.
*/
/**
* Documenting the cookies of a RESTful API's requests and responses.
*/
package org.springframework.restdocs.cookies;

View File

@@ -16,6 +16,8 @@
package org.springframework.restdocs.operation;
import java.util.Collection;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
@@ -23,6 +25,7 @@ import org.springframework.http.HttpStatus;
* The response that was received as part of performing an operation on a RESTful service.
*
* @author Andy Wilkinson
* @author Clyde Stubbs
* @see Operation
* @see Operation#getRequest()
*/
@@ -64,4 +67,12 @@ public interface OperationResponse {
*/
String getContentAsString();
/**
* Returns the {@link ResponseCookie cookies} returned with the response. If no
* cookies were returned an empty collection is returned.
* @return the cookies, never {@code null}
* @since 2.1
*/
Collection<ResponseCookie> getCookies();
}

View File

@@ -16,26 +16,47 @@
package org.springframework.restdocs.operation;
import java.util.Collection;
import java.util.Collections;
import org.springframework.http.HttpHeaders;
/**
* A factory for creating {@link OperationResponse OperationResponses}.
*
* @author Andy Wilkinson
* @author Clyde Stubbs
*/
public class OperationResponseFactory {
/**
* Creates a new {@link OperationResponse} without cookies. If the response has any
* content, the given {@code headers} will be augmented to ensure that they include a
* {@code Content-Length} header.
* @param status the status of the response
* @param headers the request's headers
* @param content the content of the request
* @return the {@code OperationResponse}
*/
public OperationResponse create(int status, HttpHeaders headers, byte[] content) {
return new StandardOperationResponse(status, augmentHeaders(headers, content), content,
Collections.emptyList());
}
/**
* Creates a new {@link OperationResponse}. If the response has any content, the given
* {@code headers} will be augmented to ensure that they include a
* {@code Content-Length} header.
* @param status the status of the response
* @param headers the response's headers
* @param content the content of the response
* @param headers the request's headers
* @param content the content of the request
* @param cookies the cookies
* @return the {@code OperationResponse}
* @since 3.0
*/
public OperationResponse create(int status, HttpHeaders headers, byte[] content) {
return new StandardOperationResponse(status, augmentHeaders(headers, content), content);
public OperationResponse create(int status, HttpHeaders headers, byte[] content,
Collection<ResponseCookie> cookies) {
return new StandardOperationResponse(status, augmentHeaders(headers, content), content, cookies);
}
/**
@@ -49,7 +70,7 @@ public class OperationResponseFactory {
*/
public OperationResponse createFrom(OperationResponse original, byte[] newContent) {
return new StandardOperationResponse(original.getStatusCode(),
getUpdatedHeaders(original.getHeaders(), newContent), newContent);
getUpdatedHeaders(original.getHeaders(), newContent), newContent, original.getCookies());
}
/**
@@ -60,7 +81,8 @@ public class OperationResponseFactory {
* @return the new response with the new headers
*/
public OperationResponse createFrom(OperationResponse original, HttpHeaders newHeaders) {
return new StandardOperationResponse(original.getStatusCode(), newHeaders, original.getContent());
return new StandardOperationResponse(original.getStatusCode(), newHeaders, original.getContent(),
original.getCookies());
}
private HttpHeaders augmentHeaders(HttpHeaders originalHeaders, byte[] content) {

View File

@@ -0,0 +1,57 @@
/*
* Copyright 2014-2018 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.
* You may obtain a copy of the License at
*
* https://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 org.springframework.restdocs.operation;
/**
* A representation of a Cookie returned in a response.
*
* @author Clyde Stubbs
* @since 2.1
*/
public final class ResponseCookie {
private final String name;
private final String value;
/**
* Creates a new {@code ResponseCookie} with the given {@code name} and {@code value}.
* @param name the name of the cookie
* @param value the value of the cookie
*/
public ResponseCookie(String name, String value) {
this.name = name;
this.value = value;
}
/**
* Returns the name of the cookie.
* @return the name
*/
public String getName() {
return this.name;
}
/**
* Returns the value of the cookie.
* @return the value
*/
public String getValue() {
return this.value;
}
}

View File

@@ -16,6 +16,8 @@
package org.springframework.restdocs.operation;
import java.util.Collection;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
@@ -23,21 +25,26 @@ import org.springframework.http.HttpStatus;
* Standard implementation of {@link OperationResponse}.
*
* @author Andy Wilkinson
* @author Clyde Stubbs
*/
class StandardOperationResponse extends AbstractOperationMessage implements OperationResponse {
private final int status;
private Collection<ResponseCookie> cookies;
/**
* Creates a new response with the given {@code status}, {@code headers}, and
* {@code content}.
* @param status the status of the response
* @param headers the headers of the response
* @param content the content of the response
* @param cookies any cookies included in the response
*/
StandardOperationResponse(int status, HttpHeaders headers, byte[] content) {
StandardOperationResponse(int status, HttpHeaders headers, byte[] content, Collection<ResponseCookie> cookies) {
super(content, headers);
this.status = status;
this.cookies = cookies;
}
@Override
@@ -50,4 +57,9 @@ class StandardOperationResponse extends AbstractOperationMessage implements Oper
return this.status;
}
@Override
public Collection<ResponseCookie> getCookies() {
return this.cookies;
}
}

View File

@@ -142,7 +142,7 @@ public class UriModifyingOperationPreprocessor implements OperationPreprocessor
@Override
public OperationResponse preprocess(OperationResponse response) {
return this.contentModifyingDelegate.preprocess(new OperationResponseFactory().create(response.getStatusCode(),
modify(response.getHeaders()), response.getContent()));
modify(response.getHeaders()), response.getContent(), response.getCookies()));
}
private HttpHeaders modify(HttpHeaders headers) {

View File

@@ -0,0 +1,9 @@
|===
|Name|Description
{{#cookies}}
|{{#tableCellContent}}`+{{name}}+`{{/tableCellContent}}
|{{#tableCellContent}}{{description}}{{/tableCellContent}}
{{/cookies}}
|===

View File

@@ -0,0 +1,9 @@
|===
|Name|Description
{{#cookies}}
|{{#tableCellContent}}`+{{name}}+`{{/tableCellContent}}
|{{#tableCellContent}}{{description}}{{/tableCellContent}}
{{/cookies}}
|===

View File

@@ -0,0 +1,5 @@
Name | Description
---- | -----------
{{#cookies}}
`{{name}}` | {{description}}
{{/cookies}}

View File

@@ -0,0 +1,5 @@
Name | Description
---- | -----------
{{#cookies}}
`{{name}}` | {{description}}
{{/cookies}}