Add support for documenting request and response cookies
See gh-592
This commit is contained in:
committed by
Andy Wilkinson
parent
15980d7486
commit
f72a9f1067
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
@@ -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();
|
||||
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
|===
|
||||
|Name|Description
|
||||
|
||||
{{#cookies}}
|
||||
|{{#tableCellContent}}`+{{name}}+`{{/tableCellContent}}
|
||||
|{{#tableCellContent}}{{description}}{{/tableCellContent}}
|
||||
|
||||
{{/cookies}}
|
||||
|===
|
||||
@@ -0,0 +1,9 @@
|
||||
|===
|
||||
|Name|Description
|
||||
|
||||
{{#cookies}}
|
||||
|{{#tableCellContent}}`+{{name}}+`{{/tableCellContent}}
|
||||
|{{#tableCellContent}}{{description}}{{/tableCellContent}}
|
||||
|
||||
{{/cookies}}
|
||||
|===
|
||||
@@ -0,0 +1,5 @@
|
||||
Name | Description
|
||||
---- | -----------
|
||||
{{#cookies}}
|
||||
`{{name}}` | {{description}}
|
||||
{{/cookies}}
|
||||
@@ -0,0 +1,5 @@
|
||||
Name | Description
|
||||
---- | -----------
|
||||
{{#cookies}}
|
||||
`{{name}}` | {{description}}
|
||||
{{/cookies}}
|
||||
Reference in New Issue
Block a user