Skip to content

Commit ca4ab38

Browse files
committed
Merge pull request #584 from ghoonch4
* gh-584: Polish "Provide a preprocessor for modifying request and response headers" Provide a preprocessor for modifying request and response headers Closes gh-584
2 parents 683686e + 36418f4 commit ca4ab38

File tree

6 files changed

+415
-178
lines changed

6 files changed

+415
-178
lines changed

docs/src/docs/asciidoc/customizing-requests-and-responses.adoc

+3-5
Original file line numberDiff line numberDiff line change
@@ -108,12 +108,10 @@ You can also specify a different replacement if you wish.
108108
109109
110110
111-
[[customizing-requests-and-responses-preprocessors-remove-headers]]
112-
==== Removing Headers
111+
[[customizing-requests-and-responses-preprocessors-modify-headers]]
112+
==== Modifying Headers
113113
114-
`removeHeaders` on `Preprocessors` removes any headers from the request or response where the name is equal to any of the given header names.
115-
116-
`removeMatchingHeaders` on `Preprocessors` removes any headers from the request or response where the name matches any of the given regular expression patterns.
114+
You can use `modifyHeaders` on `Preprocessors` to add, set, and remove request or response headers.
117115
118116
119117

spring-restdocs-core/src/main/java/org/springframework/restdocs/operation/preprocess/HeaderRemovingOperationPreprocessor.java

-67
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,218 @@
1+
/*
2+
* Copyright 2014-2022 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.restdocs.operation.preprocess;
18+
19+
import java.util.ArrayList;
20+
import java.util.Arrays;
21+
import java.util.List;
22+
import java.util.regex.Matcher;
23+
import java.util.regex.Pattern;
24+
25+
import org.springframework.http.HttpHeaders;
26+
import org.springframework.restdocs.operation.OperationRequest;
27+
import org.springframework.restdocs.operation.OperationRequestFactory;
28+
import org.springframework.restdocs.operation.OperationResponse;
29+
import org.springframework.restdocs.operation.OperationResponseFactory;
30+
import org.springframework.util.Assert;
31+
32+
/**
33+
* An {@link OperationPreprocessor} that modifies a request or response by adding,
34+
* setting, or removing headers.
35+
*
36+
* @author Jihoon Cha
37+
* @author Andy Wilkinson
38+
* @since 3.0.0
39+
*/
40+
public class HeadersModifyingOperationPreprocessor implements OperationPreprocessor {
41+
42+
private final OperationRequestFactory requestFactory = new OperationRequestFactory();
43+
44+
private final OperationResponseFactory responseFactory = new OperationResponseFactory();
45+
46+
private final List<Modification> modifications = new ArrayList<>();
47+
48+
@Override
49+
public OperationRequest preprocess(OperationRequest request) {
50+
return this.requestFactory.createFrom(request, preprocess(request.getHeaders()));
51+
}
52+
53+
@Override
54+
public OperationResponse preprocess(OperationResponse response) {
55+
return this.responseFactory.createFrom(response, preprocess(response.getHeaders()));
56+
}
57+
58+
private HttpHeaders preprocess(HttpHeaders headers) {
59+
HttpHeaders modifiedHeaders = new HttpHeaders();
60+
modifiedHeaders.putAll(headers);
61+
for (Modification modification : this.modifications) {
62+
modification.applyTo(modifiedHeaders);
63+
}
64+
return modifiedHeaders;
65+
}
66+
67+
/**
68+
* Adds a header with the given {@code name} and {@code value}.
69+
* @param name the name
70+
* @param value the value
71+
* @return {@code this}
72+
*/
73+
public HeadersModifyingOperationPreprocessor add(String name, String value) {
74+
this.modifications.add(new AddHeaderModification(name, value));
75+
return this;
76+
}
77+
78+
/**
79+
* Sets the header with the given {@code name} to have the given {@code values}.
80+
* @param name the name
81+
* @param values the values
82+
* @return {@code this}
83+
*/
84+
public HeadersModifyingOperationPreprocessor set(String name, String... values) {
85+
Assert.notEmpty(values, "At least one value must be provided");
86+
this.modifications.add(new SetHeaderModification(name, Arrays.asList(values)));
87+
return this;
88+
}
89+
90+
/**
91+
* Removes the header with the given {@code name}.
92+
* @param name the name of the parameter
93+
* @return {@code this}
94+
*/
95+
public HeadersModifyingOperationPreprocessor remove(String name) {
96+
this.modifications.add(new RemoveHeaderModification(name));
97+
return this;
98+
}
99+
100+
/**
101+
* Removes the given {@code value} from the header with the given {@code name}.
102+
* @param name the name
103+
* @param value the value
104+
* @return {@code this}
105+
*/
106+
public HeadersModifyingOperationPreprocessor remove(String name, String value) {
107+
this.modifications.add(new RemoveValueHeaderModification(name, value));
108+
return this;
109+
}
110+
111+
/**
112+
* Remove headers that match the given {@code namePattern} regular expression.
113+
* @param namePattern the name pattern
114+
* @return {@code this}
115+
* @see Matcher#matches()
116+
*/
117+
public HeadersModifyingOperationPreprocessor removeMatching(String namePattern) {
118+
this.modifications.add(new RemoveHeadersByNamePatternModification(Pattern.compile(namePattern)));
119+
return this;
120+
}
121+
122+
private interface Modification {
123+
124+
void applyTo(HttpHeaders headers);
125+
126+
}
127+
128+
private static final class AddHeaderModification implements Modification {
129+
130+
private final String name;
131+
132+
private final String value;
133+
134+
private AddHeaderModification(String name, String value) {
135+
this.name = name;
136+
this.value = value;
137+
}
138+
139+
@Override
140+
public void applyTo(HttpHeaders headers) {
141+
headers.add(this.name, this.value);
142+
}
143+
144+
}
145+
146+
private static final class SetHeaderModification implements Modification {
147+
148+
private final String name;
149+
150+
private final List<String> values;
151+
152+
private SetHeaderModification(String name, List<String> values) {
153+
this.name = name;
154+
this.values = values;
155+
}
156+
157+
@Override
158+
public void applyTo(HttpHeaders headers) {
159+
headers.put(this.name, this.values);
160+
}
161+
162+
}
163+
164+
private static final class RemoveHeaderModification implements Modification {
165+
166+
private final String name;
167+
168+
private RemoveHeaderModification(String name) {
169+
this.name = name;
170+
}
171+
172+
@Override
173+
public void applyTo(HttpHeaders headers) {
174+
headers.remove(this.name);
175+
}
176+
177+
}
178+
179+
private static final class RemoveValueHeaderModification implements Modification {
180+
181+
private final String name;
182+
183+
private final String value;
184+
185+
private RemoveValueHeaderModification(String name, String value) {
186+
this.name = name;
187+
this.value = value;
188+
}
189+
190+
@Override
191+
public void applyTo(HttpHeaders headers) {
192+
List<String> values = headers.get(this.name);
193+
if (values != null) {
194+
values.remove(this.value);
195+
if (values.isEmpty()) {
196+
headers.remove(this.name);
197+
}
198+
}
199+
}
200+
201+
}
202+
203+
private static final class RemoveHeadersByNamePatternModification implements Modification {
204+
205+
private final Pattern namePattern;
206+
207+
private RemoveHeadersByNamePatternModification(Pattern namePattern) {
208+
this.namePattern = namePattern;
209+
}
210+
211+
@Override
212+
public void applyTo(HttpHeaders headers) {
213+
headers.keySet().removeIf((name) -> this.namePattern.matcher(name).matches());
214+
}
215+
216+
}
217+
218+
}

spring-restdocs-core/src/main/java/org/springframework/restdocs/operation/preprocess/Preprocessors.java

+27-2
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
*
3232
* @author Andy Wilkinson
3333
* @author Roland Huss
34+
* @author Jihoon Cha
3435
*/
3536
public final class Preprocessors {
3637

@@ -73,10 +74,17 @@ public static OperationPreprocessor prettyPrint() {
7374
* {@code headersToRemove}.
7475
* @param headerNames the header names
7576
* @return the preprocessor
77+
* @deprecated since 3.0.0 in favor of {@link #modifyHeaders()} and
78+
* {@link HeadersModifyingOperationPreprocessor#remove(String)}
7679
* @see String#equals(Object)
7780
*/
81+
@Deprecated
7882
public static OperationPreprocessor removeHeaders(String... headerNames) {
79-
return new HeaderRemovingOperationPreprocessor(new ExactMatchHeaderFilter(headerNames));
83+
HeadersModifyingOperationPreprocessor preprocessor = new HeadersModifyingOperationPreprocessor();
84+
for (String headerName : headerNames) {
85+
preprocessor.remove(headerName);
86+
}
87+
return preprocessor;
8088
}
8189

8290
/**
@@ -85,10 +93,17 @@ public static OperationPreprocessor removeHeaders(String... headerNames) {
8593
* {@code headerNamePatterns} regular expressions.
8694
* @param headerNamePatterns the header name patterns
8795
* @return the preprocessor
96+
* @deprecated since 3.0.0 in favor of {@link #modifyHeaders()} and
97+
* {@link HeadersModifyingOperationPreprocessor#removeMatching(String)}
8898
* @see java.util.regex.Matcher#matches()
8999
*/
100+
@Deprecated
90101
public static OperationPreprocessor removeMatchingHeaders(String... headerNamePatterns) {
91-
return new HeaderRemovingOperationPreprocessor(new PatternMatchHeaderFilter(headerNamePatterns));
102+
HeadersModifyingOperationPreprocessor preprocessor = new HeadersModifyingOperationPreprocessor();
103+
for (String headerNamePattern : headerNamePatterns) {
104+
preprocessor.removeMatching(headerNamePattern);
105+
}
106+
return preprocessor;
92107
}
93108

94109
/**
@@ -132,6 +147,16 @@ public static ParametersModifyingOperationPreprocessor modifyParameters() {
132147
return new ParametersModifyingOperationPreprocessor();
133148
}
134149

150+
/**
151+
* Returns a {@code HeadersModifyingOperationPreprocessor} that can then be configured
152+
* to modify the headers of the request.
153+
* @return the preprocessor
154+
* @since 3.0.0
155+
*/
156+
public static HeadersModifyingOperationPreprocessor modifyHeaders() {
157+
return new HeadersModifyingOperationPreprocessor();
158+
}
159+
135160
/**
136161
* Returns a {@code UriModifyingOperationPreprocessor} that will modify URIs in the
137162
* request or response by changing one or more of their host, scheme, and port.

0 commit comments

Comments
 (0)