Skip to content

Index API, Exists method result can be mapped to false in cases elasticsearch returns 400, 401, 403, 405 http status code. #850

Closed
@maciejfranek

Description

@maciejfranek

Java API client version

8.7.1

Java version

17

Elasticsearch Version

8.12.2

Problem description

According to https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-exists.html#indices-exists-api-response-codes 404 http response code should be mapped to false result.

However, when working with ElasticsearchIndicesClient.exists(req) method it turns out that it can return false value in cases when ES would return 400, 401, 403 or 405 http response codes.

Code analysis

RestClientHttpClient.createRestRequest() method creates a request (that is later used in exists method) with very specific line:

        // Request parameter intercepted by LLRC
        clientReq.addParameter("ignore", "400,401,403,404,405");

public BooleanResponse exists(ExistsRequest request) - ExistsRequests indicates that it is a BooleanEndpoint

BooleanEndpoint:

    @Override
    public boolean isError(int statusCode) {
        return statusCode >= 500;
    }

    public boolean getResult(int statusCode) {
        return statusCode < 400;
    }

We can see that isError implementation considers only 5xx codes as incorrect statuses, while all 4xx would return boolean value.

Such logic allows for example that forbidden 403 or unauthorized 401 errors may be mapped to false value without the actual check if index exists.

Attaching also a test written in groovy/spock/wiremock that reproduces the problem (ElasticsearchClientSpec.groovy)

ElasticsearchClientSpec.groovy package test

import co.elastic.clients.elasticsearch.indices.ExistsRequest
import com.github.tomakehurst.wiremock.junit.WireMockRule
import groovy.util.logging.Slf4j
import org.junit.Rule
import org.springframework.data.elasticsearch.client.ClientConfiguration
import org.springframework.data.elasticsearch.client.elc.ElasticsearchClients
import spock.lang.Specification

import static com.github.tomakehurst.wiremock.client.WireMock.*

@slf4j
class ElasticsearchClientSpec extends Specification {

@Rule
public WireMockRule wireMockRule = new WireMockRule();

def setup() {
    wireMockRule.start()
    stubFor(get("/")
            .withHeader("Content-Type", containing("application/json"))
            .willReturn(ok()
                    .withHeader("Content-Type", "application/json")
                    .withBody("""

{
"name" : "test-elastic",
"cluster_name" : "test-cluster",
"cluster_uuid" : "clusterId1",
"version" : {
"number" : "8.12.2",
"build_flavor" : "default",
"build_type" : "docker",
"build_hash" : "48a287ab9497e852de30327444b0809e55d46466",
"build_date" : "2024-02-19T10:04:32.774273190Z",
"build_snapshot" : false,
"lucene_version" : "9.9.2",
"minimum_wire_compatibility_version" : "7.17.0",
"minimum_index_compatibility_version" : "7.0.0"
},
"tagline" : "You Know, for Search"
}
""")));

    stubFor(head(urlEqualTo("/fake-index-name"))
            .willReturn(forbidden()
                    .withHeader("Content-Type", "application/json")
                    .withBody("")))



}

def 'should add index prefix if present'() {
    given:
    ClientConfiguration clientConfiguration = ClientConfiguration.builder().connectedTo("127.0.0.1:8080").build()
    def elasticsearchClient = ElasticsearchClients.createImperative(clientConfiguration);

    when:
    ExistsRequest existsRequest = ExistsRequest.of(request -> request.index("fake-index-name"));

    def existsResult = elasticsearchClient.indices().exists(existsRequest).value();
    log.error("existsResult: " + existsResult)

    then:
    def t = thrown(Throwable)
    log.info("The exception is: ", t)
}

}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions