Skip to content

Commit 3751939

Browse files
committed
Include customized Host header in curl and HTTPie request snippets
Previously, the curl and HTTPie request snippets always excluded the Host header, relying on the Host header that’s auto-generated by curl and HTTPie instead. This worked well for the most part, but meant that incorrect snippets were generated when the request was being sent with a custom host header that did not match the header that would be auto-generated. This commit updates CliOperationRequest to only filter out the Host header if it’s the same as the header that would be auto-generated by curl or HTTPie. Closes gh-258
1 parent a4298b2 commit 3751939

File tree

3 files changed

+66
-11
lines changed

3 files changed

+66
-11
lines changed

spring-restdocs-core/src/main/java/org/springframework/restdocs/cli/CliOperationRequest.java

Lines changed: 38 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@
1717
package org.springframework.restdocs.cli;
1818

1919
import java.net.URI;
20+
import java.util.Arrays;
2021
import java.util.Collection;
21-
import java.util.Collections;
2222
import java.util.HashSet;
2323
import java.util.List;
2424
import java.util.Map;
@@ -41,20 +41,15 @@
4141
*/
4242
final class CliOperationRequest implements OperationRequest {
4343

44-
private static final Set<HeaderFilter> HEADER_FILTERS;
45-
46-
static {
47-
Set<HeaderFilter> headerFilters = new HashSet<>();
48-
headerFilters.add(new NamedHeaderFilter(HttpHeaders.HOST));
49-
headerFilters.add(new NamedHeaderFilter(HttpHeaders.CONTENT_LENGTH));
50-
headerFilters.add(new BasicAuthHeaderFilter());
51-
HEADER_FILTERS = Collections.unmodifiableSet(headerFilters);
52-
}
44+
private final Set<HeaderFilter> headerFilters;
5345

5446
private final OperationRequest delegate;
5547

5648
CliOperationRequest(OperationRequest delegate) {
5749
this.delegate = delegate;
50+
this.headerFilters = new HashSet<>(Arrays.asList(
51+
new NamedHeaderFilter(HttpHeaders.CONTENT_LENGTH),
52+
new BasicAuthHeaderFilter(), new HostHeaderFilter(delegate.getUri())));
5853
}
5954

6055
Parameters getUniqueParameters() {
@@ -121,11 +116,20 @@ public HttpHeaders getHeaders() {
121116
}
122117

123118
private boolean allowedHeader(Map.Entry<String, List<String>> header) {
124-
for (HeaderFilter headerFilter : HEADER_FILTERS) {
119+
for (HeaderFilter headerFilter : this.headerFilters) {
125120
if (!headerFilter.allow(header.getKey(), header.getValue())) {
126121
return false;
127122
}
128123
}
124+
if (HttpHeaders.HOST.equalsIgnoreCase(header.getKey())) {
125+
if (!header.getValue().isEmpty()) {
126+
String value = header.getValue().get(0);
127+
if (value.equals(this.delegate.getUri().getHost() + ":"
128+
+ this.delegate.getUri().getPort())) {
129+
return false;
130+
}
131+
}
132+
}
129133
return true;
130134
}
131135

@@ -187,4 +191,27 @@ public boolean allow(String name, List<String> value) {
187191

188192
}
189193

194+
private static final class HostHeaderFilter implements HeaderFilter {
195+
196+
private final URI uri;
197+
198+
private HostHeaderFilter(URI uri) {
199+
this.uri = uri;
200+
}
201+
202+
@Override
203+
public boolean allow(String name, List<String> value) {
204+
if (value.isEmpty() || this.getImplicitHostHeader().equals(value.get(0))) {
205+
return false;
206+
}
207+
return true;
208+
}
209+
210+
private String getImplicitHostHeader() {
211+
return this.uri.getHost()
212+
+ ((this.uri.getPort() == -1) ? "" : ":" + this.uri.getPort());
213+
}
214+
215+
}
216+
190217
}

spring-restdocs-core/src/test/java/org/springframework/restdocs/cli/CurlRequestSnippetTests.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -330,4 +330,18 @@ public void customAttributes() throws IOException {
330330
.request("http://localhost/foo").build());
331331
}
332332

333+
@Test
334+
public void customHostHeaderIsIncluded() throws IOException {
335+
this.snippet.expectCurlRequest("custom-host-header")
336+
.withContents(codeBlock("bash").content(
337+
"$ curl 'http://localhost/foo' -i" + " -H 'Host: api.example.com'"
338+
+ " -H 'Content-Type: application/json' -H 'a: alpha'"));
339+
new CurlRequestSnippet().document(
340+
operationBuilder("custom-host-header").request("http://localhost/foo")
341+
.header(HttpHeaders.HOST, "api.example.com")
342+
.header(HttpHeaders.CONTENT_TYPE,
343+
MediaType.APPLICATION_JSON_VALUE)
344+
.header("a", "alpha").build());
345+
}
346+
333347
}

spring-restdocs-core/src/test/java/org/springframework/restdocs/cli/HttpieRequestSnippetTests.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -332,4 +332,18 @@ public void customAttributes() throws IOException {
332332
.request("http://localhost/foo").build());
333333
}
334334

335+
@Test
336+
public void customHostHeaderIsIncluded() throws IOException {
337+
this.snippet.expectHttpieRequest("custom-host-header")
338+
.withContents(codeBlock("bash").content(
339+
"$ http GET 'http://localhost/foo' 'Host:api.example.com'"
340+
+ " 'Content-Type:application/json' 'a:alpha'"));
341+
new HttpieRequestSnippet().document(
342+
operationBuilder("custom-host-header").request("http://localhost/foo")
343+
.header(HttpHeaders.HOST, "api.example.com")
344+
.header(HttpHeaders.CONTENT_TYPE,
345+
MediaType.APPLICATION_JSON_VALUE)
346+
.header("a", "alpha").build());
347+
}
348+
335349
}

0 commit comments

Comments
 (0)