elasticsearch co.elastic.clients.transport.TransportException:[es/search]缺少[X-Elastic-Product]标头

628mspwn  于 2022-11-02  发布在  ElasticSearch
关注(0)|答案(1)|浏览(968)

我下面的教程从ElasticSearchjava api客户端在这里:https://www.elastic.co/guide/en/elasticsearch/client/java-api-client/current/connecting.html
我的代码如下。

// Create the low-level client
RestClient restClient = RestClient.builder(
 new HttpHost("localhost", 9200)).build();

// Create the transport with a Jackson mapper
ElasticsearchTransport transport = new RestClientTransport(
 restClient, new JacksonJsonpMapper());

// And create the API client
ElasticsearchClient client = new ElasticsearchClient(transport);

try {
 SearchResponse<Object> search = client.search(s -> s
   .index("*:*"),
   Object.class);
} catch (IOException e) {
 System.out.println(e.getMessage());
}

此程式码会掷回下列例外状况:

co.elastic.clients.transport.TransportException: [es/search] Missing [X-Elastic-Product] header. Please check that you are connecting to an Elasticsearch instance, and that any networking filters are preserving that header.

我试过通过setDefaultHeaders方法手动放置这个头文件,如下所示:

RestClientBuilder builder = RestClient.builder(
 new HttpHost("localhost", 9200, "http"));
Header[] defaultHeaders = new Header[]{new BasicHeader("X-Elastic-Product", "Elasticsearch")};
builder.setDefaultHeaders(defaultHeaders);
RestClient restClient = builder.build();

但错误是一样的。
我已经尝试了版本7.16和8.0.0,结果相同。

hgncfbus

hgncfbus1#

RestClientBuilder允许您指定的默认头是 request 头,而不是response头。您所得到的错误是因为旧版本的Elasticsearch [server]在任何API响应中都不包含X-Elastic-Product=Elasticsearch头,但是最近的发行版(7.14+?)包含了x1m2 n1,头,所以新版本的elasticsearch-java(即客户端)需要它们。
我在同一条船上--我使用elasticsearch-java的8.4.2版本和7.2.0版本的Elasticsearch服务器。
我遇到了两个基于格式的兼容性问题:
1.客户端传递服务器未知的Content-Type,因此其请求被拒绝,并返回406
1.客户端验证响应是否具有X-Elastic-Product=Elasticsearch标头
幸运的是,RestClientBuilder允许您通过以下方式自定义底层http客户端:setHttpClientConfigCallback。回调如下所示,因此基本上您可以拦截请求和响应,操作标头,从而解决以下问题:

public interface HttpClientConfigCallback {
        /**
         * Allows to customize the {@link CloseableHttpAsyncClient} being created and used by the {@link RestClient}.
         * Commonly used to customize the default {@link org.apache.http.client.CredentialsProvider} for authentication
         * or the {@link SchemeIOSessionStrategy} for communication through ssl without losing any other useful default
         * value that the {@link RestClientBuilder} internally sets, like connection pooling.
         */
        HttpAsyncClientBuilder customizeHttpClient(HttpAsyncClientBuilder httpClientBuilder);
    }

具体来说,以下是对我有效的方法:

var httpClientConfigCallback = httpClientBuilder ->
        httpClientBuilder
            .setDefaultCredentialsProvider(credentialsProvider)
            // this request & response header manipulation helps get around newer (>=7.16) versions
            // of elasticsearch-java client not working with older (<7.14) versions of Elasticsearch
            // server
            .setDefaultHeaders(
                List.of(
                    new BasicHeader(
                        HttpHeaders.CONTENT_TYPE, ContentType.APPLICATION_JSON.toString())))
            .addInterceptorLast(
                (HttpResponseInterceptor)
                    (response, context) ->
                        response.addHeader("X-Elastic-Product", "Elasticsearch"));
var restClient =
        RestClient.builder(elasticsearchHosts)
            .setHttpClientConfigCallback(httpClientConfigCallback)
            .build();

请注意,上述产品和API版本之间可能仍然存在行为差异,因为它们相差太远。上述内容仅修复了基于格式的不兼容性。因此,最好使用这些组件的至少相同的主要版本,如果不是完全相同的版本。

相关问题