Add support for headers in REST tests
This adds support for arbitrary headers sent with each REST request, it will allow us to test things like different xcontent-encoding (see 50_with_headers.yaml for what this looks like). Headers are specified at the same level as `catch`, so a request would look like: ```yaml - do: headers: Content-Type: application/yaml get: index: test_1 type: _all id: 1 ```
This commit is contained in:
parent
18a8c20cba
commit
a25b407aeb
|
@ -0,0 +1,30 @@
|
||||||
|
---
|
||||||
|
"REST test with headers":
|
||||||
|
- skip:
|
||||||
|
features: headers
|
||||||
|
|
||||||
|
- do:
|
||||||
|
index:
|
||||||
|
index: test_1
|
||||||
|
type: test
|
||||||
|
id: 1
|
||||||
|
body: { "body": "foo" }
|
||||||
|
|
||||||
|
- do:
|
||||||
|
headers:
|
||||||
|
Content-Type: application/yaml
|
||||||
|
get:
|
||||||
|
index: test_1
|
||||||
|
type: _all
|
||||||
|
id: 1
|
||||||
|
|
||||||
|
- match:
|
||||||
|
$body: |
|
||||||
|
/^---\n
|
||||||
|
_index:\s+\"test_1"\n
|
||||||
|
_type:\s+"test"\n
|
||||||
|
_id:\s+"1"\n
|
||||||
|
_version:\s+1\n
|
||||||
|
found:\s+true\n
|
||||||
|
_source:\n
|
||||||
|
\s+body:\s+"foo"\n$/
|
|
@ -62,7 +62,8 @@ public class RestTestExecutionContext implements Closeable {
|
||||||
* Saves the obtained response in the execution context.
|
* Saves the obtained response in the execution context.
|
||||||
* @throws RestException if the returned status code is non ok
|
* @throws RestException if the returned status code is non ok
|
||||||
*/
|
*/
|
||||||
public RestResponse callApi(String apiName, Map<String, String> params, List<Map<String, Object>> bodies) throws IOException, RestException {
|
public RestResponse callApi(String apiName, Map<String, String> params, List<Map<String, Object>> bodies,
|
||||||
|
Map<String, String> headers) throws IOException, RestException {
|
||||||
//makes a copy of the parameters before modifying them for this specific request
|
//makes a copy of the parameters before modifying them for this specific request
|
||||||
HashMap<String, String> requestParams = new HashMap<>(params);
|
HashMap<String, String> requestParams = new HashMap<>(params);
|
||||||
for (Map.Entry<String, String> entry : requestParams.entrySet()) {
|
for (Map.Entry<String, String> entry : requestParams.entrySet()) {
|
||||||
|
@ -74,7 +75,7 @@ public class RestTestExecutionContext implements Closeable {
|
||||||
String body = actualBody(bodies);
|
String body = actualBody(bodies);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
response = callApiInternal(apiName, requestParams, body);
|
response = callApiInternal(apiName, requestParams, body, headers);
|
||||||
//we always stash the last response body
|
//we always stash the last response body
|
||||||
stash.stashValue("body", response.getBody());
|
stash.stashValue("body", response.getBody());
|
||||||
return response;
|
return response;
|
||||||
|
@ -104,8 +105,8 @@ public class RestTestExecutionContext implements Closeable {
|
||||||
return XContentFactory.jsonBuilder().map(body).string();
|
return XContentFactory.jsonBuilder().map(body).string();
|
||||||
}
|
}
|
||||||
|
|
||||||
private RestResponse callApiInternal(String apiName, Map<String, String> params, String body) throws IOException, RestException {
|
private RestResponse callApiInternal(String apiName, Map<String, String> params, String body, Map<String, String> headers) throws IOException, RestException {
|
||||||
return restClient.callApi(apiName, params, body);
|
return restClient.callApi(apiName, params, body, headers);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -132,7 +132,7 @@ public class RestClient implements Closeable {
|
||||||
* @throws RestException if the obtained status code is non ok, unless the specific error code needs to be ignored
|
* @throws RestException if the obtained status code is non ok, unless the specific error code needs to be ignored
|
||||||
* according to the ignore parameter received as input (which won't get sent to elasticsearch)
|
* according to the ignore parameter received as input (which won't get sent to elasticsearch)
|
||||||
*/
|
*/
|
||||||
public RestResponse callApi(String apiName, Map<String, String> params, String body) throws IOException, RestException {
|
public RestResponse callApi(String apiName, Map<String, String> params, String body, Map<String, String> headers) throws IOException, RestException {
|
||||||
|
|
||||||
List<Integer> ignores = new ArrayList<>();
|
List<Integer> ignores = new ArrayList<>();
|
||||||
Map<String, String> requestParams = null;
|
Map<String, String> requestParams = null;
|
||||||
|
@ -151,6 +151,9 @@ public class RestClient implements Closeable {
|
||||||
}
|
}
|
||||||
|
|
||||||
HttpRequestBuilder httpRequestBuilder = callApiBuilder(apiName, requestParams, body);
|
HttpRequestBuilder httpRequestBuilder = callApiBuilder(apiName, requestParams, body);
|
||||||
|
for (Map.Entry<String, String> header : headers.entrySet()) {
|
||||||
|
httpRequestBuilder.addHeader(header.getKey(), header.getValue());
|
||||||
|
}
|
||||||
logger.debug("calling api [{}]", apiName);
|
logger.debug("calling api [{}]", apiName);
|
||||||
HttpResponse httpResponse = httpRequestBuilder.execute();
|
HttpResponse httpResponse = httpRequestBuilder.execute();
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,8 @@ import org.elasticsearch.test.rest.section.ApiCallSection;
|
||||||
import org.elasticsearch.test.rest.section.DoSection;
|
import org.elasticsearch.test.rest.section.DoSection;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parser for do sections
|
* Parser for do sections
|
||||||
|
@ -40,6 +42,8 @@ public class DoSectionParser implements RestTestFragmentParser<DoSection> {
|
||||||
XContentParser.Token token;
|
XContentParser.Token token;
|
||||||
|
|
||||||
DoSection doSection = new DoSection();
|
DoSection doSection = new DoSection();
|
||||||
|
ApiCallSection apiCallSection = null;
|
||||||
|
Map<String, String> headers = new HashMap<>();
|
||||||
|
|
||||||
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
|
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
|
||||||
if (token == XContentParser.Token.FIELD_NAME) {
|
if (token == XContentParser.Token.FIELD_NAME) {
|
||||||
|
@ -49,8 +53,17 @@ public class DoSectionParser implements RestTestFragmentParser<DoSection> {
|
||||||
doSection.setCatch(parser.text());
|
doSection.setCatch(parser.text());
|
||||||
}
|
}
|
||||||
} else if (token == XContentParser.Token.START_OBJECT) {
|
} else if (token == XContentParser.Token.START_OBJECT) {
|
||||||
if (currentFieldName != null) {
|
if ("headers".equals(currentFieldName)) {
|
||||||
ApiCallSection apiCallSection = new ApiCallSection(currentFieldName);
|
String headerName = null;
|
||||||
|
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
|
||||||
|
if (token == XContentParser.Token.FIELD_NAME) {
|
||||||
|
headerName = parser.currentName();
|
||||||
|
} else if (token.isValue()) {
|
||||||
|
headers.put(headerName, parser.text());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (currentFieldName != null) { // must be part of API call then
|
||||||
|
apiCallSection = new ApiCallSection(currentFieldName);
|
||||||
String paramName = null;
|
String paramName = null;
|
||||||
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
|
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
|
||||||
if (token == XContentParser.Token.FIELD_NAME) {
|
if (token == XContentParser.Token.FIELD_NAME) {
|
||||||
|
@ -73,17 +86,20 @@ public class DoSectionParser implements RestTestFragmentParser<DoSection> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
doSection.setApiCallSection(apiCallSection);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
try {
|
||||||
parser.nextToken();
|
if (apiCallSection == null) {
|
||||||
|
throw new RestTestParseException("client call section is mandatory within a do section");
|
||||||
if (doSection.getApiCallSection() == null) {
|
}
|
||||||
throw new RestTestParseException("client call section is mandatory within a do section");
|
if (headers.isEmpty() == false) {
|
||||||
|
apiCallSection.addHeaders(headers);
|
||||||
|
}
|
||||||
|
doSection.setApiCallSection(apiCallSection);
|
||||||
|
} finally {
|
||||||
|
parser.nextToken();
|
||||||
}
|
}
|
||||||
|
|
||||||
return doSection;
|
return doSection;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,6 +33,7 @@ public class ApiCallSection {
|
||||||
|
|
||||||
private final String api;
|
private final String api;
|
||||||
private final Map<String, String> params = new HashMap<>();
|
private final Map<String, String> params = new HashMap<>();
|
||||||
|
private final Map<String, String> headers = new HashMap<>();
|
||||||
private final List<Map<String, Object>> bodies = new ArrayList<>();
|
private final List<Map<String, Object>> bodies = new ArrayList<>();
|
||||||
|
|
||||||
public ApiCallSection(String api) {
|
public ApiCallSection(String api) {
|
||||||
|
@ -56,6 +57,18 @@ public class ApiCallSection {
|
||||||
this.params.put(key, value);
|
this.params.put(key, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void addHeaders(Map<String, String> otherHeaders) {
|
||||||
|
this.headers.putAll(otherHeaders);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addHeader(String key, String value) {
|
||||||
|
this.headers.put(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, String> getHeaders() {
|
||||||
|
return unmodifiableMap(headers);
|
||||||
|
}
|
||||||
|
|
||||||
public List<Map<String, Object>> getBodies() {
|
public List<Map<String, Object>> getBodies() {
|
||||||
return Collections.unmodifiableList(bodies);
|
return Collections.unmodifiableList(bodies);
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,6 +45,9 @@ import static org.junit.Assert.fail;
|
||||||
*
|
*
|
||||||
* - do:
|
* - do:
|
||||||
* catch: missing
|
* catch: missing
|
||||||
|
* headers:
|
||||||
|
* Authorization: Basic user:pass
|
||||||
|
* Content-Type: application/json
|
||||||
* update:
|
* update:
|
||||||
* index: test_1
|
* index: test_1
|
||||||
* type: test
|
* type: test
|
||||||
|
@ -86,7 +89,8 @@ public class DoSection implements ExecutableSection {
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
RestResponse restResponse = executionContext.callApi(apiCallSection.getApi(), apiCallSection.getParams(), apiCallSection.getBodies());
|
RestResponse restResponse = executionContext.callApi(apiCallSection.getApi(), apiCallSection.getParams(),
|
||||||
|
apiCallSection.getBodies(), apiCallSection.getHeaders());
|
||||||
if (Strings.hasLength(catchParam)) {
|
if (Strings.hasLength(catchParam)) {
|
||||||
String catchStatusCode;
|
String catchStatusCode;
|
||||||
if (catches.containsKey(catchParam)) {
|
if (catches.containsKey(catchParam)) {
|
||||||
|
|
|
@ -34,7 +34,7 @@ import java.util.List;
|
||||||
*/
|
*/
|
||||||
public final class Features {
|
public final class Features {
|
||||||
|
|
||||||
private static final List<String> SUPPORTED = Arrays.asList("stash_in_path", "groovy_scripting");
|
private static final List<String> SUPPORTED = Arrays.asList("stash_in_path", "groovy_scripting", "headers");
|
||||||
|
|
||||||
private Features() {
|
private Features() {
|
||||||
|
|
||||||
|
|
|
@ -341,6 +341,29 @@ public class DoSectionParserTests extends AbstractParserTestCase {
|
||||||
assertThat(doSection.getApiCallSection().hasBody(), equalTo(false));
|
assertThat(doSection.getApiCallSection().hasBody(), equalTo(false));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testParseDoSectionWithHeaders() throws Exception {
|
||||||
|
parser = YamlXContent.yamlXContent.createParser(
|
||||||
|
"headers:\n" +
|
||||||
|
" Authorization: \"thing one\"\n" +
|
||||||
|
" Content-Type: \"application/json\"\n" +
|
||||||
|
"indices.get_warmer:\n" +
|
||||||
|
" index: test_index\n" +
|
||||||
|
" name: test_warmer"
|
||||||
|
);
|
||||||
|
|
||||||
|
DoSectionParser doSectionParser = new DoSectionParser();
|
||||||
|
DoSection doSection = doSectionParser.parse(new RestTestSuiteParseContext("api", "suite", parser));
|
||||||
|
|
||||||
|
assertThat(doSection.getApiCallSection(), notNullValue());
|
||||||
|
assertThat(doSection.getApiCallSection().getApi(), equalTo("indices.get_warmer"));
|
||||||
|
assertThat(doSection.getApiCallSection().getParams().size(), equalTo(2));
|
||||||
|
assertThat(doSection.getApiCallSection().hasBody(), equalTo(false));
|
||||||
|
assertThat(doSection.getApiCallSection().getHeaders(), notNullValue());
|
||||||
|
assertThat(doSection.getApiCallSection().getHeaders().size(), equalTo(2));
|
||||||
|
assertThat(doSection.getApiCallSection().getHeaders().get("Authorization"), equalTo("thing one"));
|
||||||
|
assertThat(doSection.getApiCallSection().getHeaders().get("Content-Type"), equalTo("application/json"));
|
||||||
|
}
|
||||||
|
|
||||||
public void testParseDoSectionWithoutClientCallSection() throws Exception {
|
public void testParseDoSectionWithoutClientCallSection() throws Exception {
|
||||||
parser = YamlXContent.yamlXContent.createParser(
|
parser = YamlXContent.yamlXContent.createParser(
|
||||||
"catch: missing\n"
|
"catch: missing\n"
|
||||||
|
|
Loading…
Reference in New Issue