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
This commit is contained in:
Andy Wilkinson
2016-06-23 11:41:57 +01:00
parent a4298b29e7
commit 37519398c7
3 changed files with 66 additions and 11 deletions

View File

@@ -17,8 +17,8 @@
package org.springframework.restdocs.cli;
import java.net.URI;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
@@ -41,20 +41,15 @@ import org.springframework.util.Base64Utils;
*/
final class CliOperationRequest implements OperationRequest {
private static final Set<HeaderFilter> HEADER_FILTERS;
static {
Set<HeaderFilter> headerFilters = new HashSet<>();
headerFilters.add(new NamedHeaderFilter(HttpHeaders.HOST));
headerFilters.add(new NamedHeaderFilter(HttpHeaders.CONTENT_LENGTH));
headerFilters.add(new BasicAuthHeaderFilter());
HEADER_FILTERS = Collections.unmodifiableSet(headerFilters);
}
private final Set<HeaderFilter> headerFilters;
private final OperationRequest delegate;
CliOperationRequest(OperationRequest delegate) {
this.delegate = delegate;
this.headerFilters = new HashSet<>(Arrays.asList(
new NamedHeaderFilter(HttpHeaders.CONTENT_LENGTH),
new BasicAuthHeaderFilter(), new HostHeaderFilter(delegate.getUri())));
}
Parameters getUniqueParameters() {
@@ -121,11 +116,20 @@ final class CliOperationRequest implements OperationRequest {
}
private boolean allowedHeader(Map.Entry<String, List<String>> header) {
for (HeaderFilter headerFilter : HEADER_FILTERS) {
for (HeaderFilter headerFilter : this.headerFilters) {
if (!headerFilter.allow(header.getKey(), header.getValue())) {
return false;
}
}
if (HttpHeaders.HOST.equalsIgnoreCase(header.getKey())) {
if (!header.getValue().isEmpty()) {
String value = header.getValue().get(0);
if (value.equals(this.delegate.getUri().getHost() + ":"
+ this.delegate.getUri().getPort())) {
return false;
}
}
}
return true;
}
@@ -187,4 +191,27 @@ final class CliOperationRequest implements OperationRequest {
}
private static final class HostHeaderFilter implements HeaderFilter {
private final URI uri;
private HostHeaderFilter(URI uri) {
this.uri = uri;
}
@Override
public boolean allow(String name, List<String> value) {
if (value.isEmpty() || this.getImplicitHostHeader().equals(value.get(0))) {
return false;
}
return true;
}
private String getImplicitHostHeader() {
return this.uri.getHost()
+ ((this.uri.getPort() == -1) ? "" : ":" + this.uri.getPort());
}
}
}

View File

@@ -330,4 +330,18 @@ public class CurlRequestSnippetTests extends AbstractSnippetTests {
.request("http://localhost/foo").build());
}
@Test
public void customHostHeaderIsIncluded() throws IOException {
this.snippet.expectCurlRequest("custom-host-header")
.withContents(codeBlock("bash").content(
"$ curl 'http://localhost/foo' -i" + " -H 'Host: api.example.com'"
+ " -H 'Content-Type: application/json' -H 'a: alpha'"));
new CurlRequestSnippet().document(
operationBuilder("custom-host-header").request("http://localhost/foo")
.header(HttpHeaders.HOST, "api.example.com")
.header(HttpHeaders.CONTENT_TYPE,
MediaType.APPLICATION_JSON_VALUE)
.header("a", "alpha").build());
}
}

View File

@@ -332,4 +332,18 @@ public class HttpieRequestSnippetTests extends AbstractSnippetTests {
.request("http://localhost/foo").build());
}
@Test
public void customHostHeaderIsIncluded() throws IOException {
this.snippet.expectHttpieRequest("custom-host-header")
.withContents(codeBlock("bash").content(
"$ http GET 'http://localhost/foo' 'Host:api.example.com'"
+ " 'Content-Type:application/json' 'a:alpha'"));
new HttpieRequestSnippet().document(
operationBuilder("custom-host-header").request("http://localhost/foo")
.header(HttpHeaders.HOST, "api.example.com")
.header(HttpHeaders.CONTENT_TYPE,
MediaType.APPLICATION_JSON_VALUE)
.header("a", "alpha").build());
}
}