Skip to content

Commit cd858ce

Browse files
committed
[search] HEAD support for the _search/exists api
Registers the `_search/exists` api to receive HEAD requests. If it gets one then it won't output the JSON response but will still do everything else. Adds magic to the rest tests to ignore `catch: missing` for HEAD requests. This behavior is checked instead with `- is_false: anystring`. This setup makes the rest tests for `search/_exists` work for HEAD requests. Also forces the request body over the source URL parameter for all HEAD requests. Closes elastic#11204
1 parent ed443a3 commit cd858ce

File tree

6 files changed

+37
-18
lines changed

6 files changed

+37
-18
lines changed

core/src/main/java/org/elasticsearch/rest/action/exists/RestExistsAction.java

+6-4
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636
import static org.elasticsearch.rest.RestStatus.OK;
3737

3838
/**
39-
* Action for /_search/exists endpoint
39+
* Action for /_search/exists endpoint.
4040
*/
4141
public class RestExistsAction extends BaseRestHandler {
4242

@@ -65,9 +65,11 @@ public void handleRequest(final RestRequest request, final RestChannel channel,
6565
@Override
6666
public RestResponse buildResponse(ExistsResponse response, XContentBuilder builder) throws Exception {
6767
RestStatus status = response.exists() ? OK : NOT_FOUND;
68-
builder.startObject();
69-
builder.field("exists", response.exists());
70-
builder.endObject();
68+
if (request.method() != RestRequest.Method.HEAD) {
69+
builder.startObject();
70+
builder.field("exists", response.exists());
71+
builder.endObject();
72+
}
7173
return new BytesRestResponse(status, builder);
7274
}
7375
});

core/src/main/java/org/elasticsearch/rest/action/search/RestSearchAction.java

+4
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444

4545
import static org.elasticsearch.common.unit.TimeValue.parseTimeValue;
4646
import static org.elasticsearch.rest.RestRequest.Method.GET;
47+
import static org.elasticsearch.rest.RestRequest.Method.HEAD;
4748
import static org.elasticsearch.rest.RestRequest.Method.POST;
4849
import static org.elasticsearch.search.suggest.SuggestBuilders.termSuggestion;
4950

@@ -71,10 +72,13 @@ public RestSearchAction(Settings settings, RestController controller, Client cli
7172
RestExistsAction restExistsAction = new RestExistsAction(settings, controller, client);
7273
controller.registerHandler(GET, "/_search/exists", restExistsAction);
7374
controller.registerHandler(POST, "/_search/exists", restExistsAction);
75+
controller.registerHandler(HEAD, "/_search/exists", restExistsAction);
7476
controller.registerHandler(GET, "/{index}/_search/exists", restExistsAction);
7577
controller.registerHandler(POST, "/{index}/_search/exists", restExistsAction);
78+
controller.registerHandler(HEAD, "/{index}/_search/exists", restExistsAction);
7679
controller.registerHandler(GET, "/{index}/{type}/_search/exists", restExistsAction);
7780
controller.registerHandler(POST, "/{index}/{type}/_search/exists", restExistsAction);
81+
controller.registerHandler(HEAD, "/{index}/{type}/_search/exists", restExistsAction);
7882
}
7983

8084
@Override

core/src/test/java/org/elasticsearch/test/rest/client/RestClient.java

+9-7
Original file line numberDiff line numberDiff line change
@@ -154,8 +154,6 @@ public RestResponse callApi(String apiName, Map<String, String> params, String b
154154
logger.debug("calling api [{}]", apiName);
155155
HttpResponse httpResponse = httpRequestBuilder.execute();
156156

157-
// http HEAD doesn't support response body
158-
// For the few api (exists class of api) that use it we need to accept 404 too
159157
if (!httpResponse.supportsBody()) {
160158
ignores.add(404);
161159
}
@@ -216,12 +214,16 @@ private HttpRequestBuilder callApiBuilder(String apiName, Map<String, String> pa
216214
if (!restApi.isBodySupported()) {
217215
throw new IllegalArgumentException("body is not supported by [" + restApi.getName() + "] api");
218216
}
219-
//test the GET with source param instead of GET/POST with body
220-
if (supportedMethods.contains("GET") && RandomizedTest.rarely()) {
221-
logger.debug("sending the request body as source param with GET method");
222-
httpRequestBuilder.addParam("source", body).method("GET");
217+
String method = RandomizedTest.randomFrom(supportedMethods);
218+
if ("HEAD".equals(method) || ("GET".equals(method) && RandomizedTest.rarely())) {
219+
// HEAD will always send the body as a parameter
220+
// GET will rarely send the body as a parameter
221+
if (logger.isDebugEnabled()) {
222+
logger.debug("sending the request body as source param with {} method", method);
223+
}
224+
httpRequestBuilder.addParam("source", body).method(method);
223225
} else {
224-
httpRequestBuilder.body(body).method(RandomizedTest.randomFrom(supportedMethods));
226+
httpRequestBuilder.body(body).method(method);
225227
}
226228
} else {
227229
if (restApi.isBodyRequired()) {

core/src/test/java/org/elasticsearch/test/rest/client/RestResponse.java

+10-5
Original file line numberDiff line numberDiff line change
@@ -86,10 +86,8 @@ public Object evaluate(String path, Stash stash) throws IOException {
8686
JsonPath jsonPath = parsedResponse();
8787

8888
if (jsonPath == null) {
89-
//special case: api that don't support body (e.g. exists) return true if 200, false if 404, even if no body
90-
//is_true: '' means the response had no body but the client returned true (caused by 200)
91-
//is_false: '' means the response had no body but the client returned false (caused by 404)
92-
if ("".equals(path) && !response.supportsBody()) {
89+
//special case: apis that don't send a body always return true if 200, false if 404, even if no body
90+
if (!response.supportsBody()) {
9391
return !response.isError();
9492
}
9593
return null;
@@ -98,9 +96,16 @@ public Object evaluate(String path, Stash stash) throws IOException {
9896
return jsonPath.evaluate(path, stash);
9997
}
10098

99+
/**
100+
* Was this request over a method that supports a body?
101+
*/
102+
public boolean supportsBody() {
103+
return response.supportsBody();
104+
}
105+
101106
private boolean isJson() {
102107
String contentType = response.getHeaders().get("Content-Type");
103-
return contentType != null && contentType.contains("application/json");
108+
return response.supportsBody() && contentType != null && contentType.contains("application/json");
104109
}
105110

106111
private JsonPath parsedResponse() throws IOException {

core/src/test/java/org/elasticsearch/test/rest/section/DoSection.java

+3-1
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,9 @@ public void execute(RestTestExecutionContext executionContext) throws IOExceptio
8787

8888
try {
8989
RestResponse restResponse = executionContext.callApi(apiCallSection.getApi(), apiCallSection.getParams(), apiCallSection.getBodies());
90-
if (Strings.hasLength(catchParam)) {
90+
// We ignore "missing" catch params on HEAD requests in favor of asserting them with "is_false: ''"-style assertions
91+
boolean ignoreCatchParam = "missing".equals(catchParam) && !restResponse.supportsBody();
92+
if (Strings.hasLength(catchParam) && !ignoreCatchParam) {
9193
String catchStatusCode;
9294
if (catches.containsKey(catchParam)) {
9395
catchStatusCode = catches.get(catchParam).v1();

rest-api-spec/src/main/resources/rest-api-spec/api/search_exists.json

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"search_exists": {
33
"documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/search-exists.html",
4-
"methods": ["POST", "GET"],
4+
"methods": ["POST", "GET", "HEAD"],
55
"url": {
66
"path": "/_search/exists",
77
"paths": ["/_search/exists", "/{index}/_search/exists", "/{index}/{type}/_search/exists"],
@@ -71,6 +71,10 @@
7171
"lowercase_expanded_terms": {
7272
"type" : "boolean",
7373
"description" : "Specify whether query terms should be lowercased"
74+
},
75+
"source": {
76+
"type": "string",
77+
"description": "source of the search query if the search query isn't included in the body"
7478
}
7579
}
7680
},

0 commit comments

Comments
 (0)