Why does the HTTP authentication with Elasticsearch fail in Rust?

When I use let client = Elasticsearch::default() , it works fine. But when I try to add credentials for the client:

#[macro_use]
extern crate serde_json;
use elasticsearch::{
    auth::Credentials,
    http::transport::{SingleNodeConnectionPool, Transport, TransportBuilder},
    params::Refresh,
    Elasticsearch, Error, IndexParts, SearchParts,
};
use futures::executor::block_on;
use serde_json::Value;
use url::Url;

#[tokio::main]
async fn main() -> Result<(), Error> {
    let credentials = Credentials::Basic("<username>".into(), "<password>".into());
    let u = Url::parse("http://localhost:9200")?;
    let conn_pool = SingleNodeConnectionPool::new(u);
    let transport = TransportBuilder::new(conn_pool).auth(credentials).build()?;
    let client = Elasticsearch::new(transport);
    let response = client
        .search(SearchParts::Index(&["tweets"]))
        .from(0)
        .size(10)
        .body(json!({
            "query": {
                "match": {
                    "message": "Elasticsearch rust"
                }
            }
        }))
        .send()
        .await?;

    let response_body = response.read_body::<Value>().await?;

    println!("{:?}", response_body);

    Ok(())
}

I get the following error:

response Object(
    {
        "error": String(
            "Not Found",
        ),
        "message": String(
            "Not Found",
        ),
        "statusCode": Number(
            404,
        ),
    },
)

The response isn't one that I would expect from Elasticsearch. For example, If I run your code against Elasticsearch 7.5.2 instance that doesn't contain a tweets index, the response is

Object({"error": Object({"index": String("tweets"), "index_uuid": String("_na_"), "reason": String("no such index [tweets]"), "resource.id": String("tweets"), "resource.type": String("index_or_alias"), "root_cause": Array([Object({"
index": String("tweets"), "index_uuid": String("_na_"), "reason": String("no such index [tweets]"), "resource.id": String("tweets"), "resource.type": String("index_or_alias"), "type": String("index_not_found_exception")})]), "type":
 String("index_not_found_exception")}), "status": Number(404)})

Note that error is a serde::Value::Object and there's no statusCode or message properties.

My toolchain is

$ rustup show

Default host: x86_64-pc-windows-msvc
rustup home:  <home>

installed toolchains
--------------------

stable-x86_64-pc-windows-gnu
stable-x86_64-pc-windows-msvc
nightly-x86_64-pc-windows-gnu
nightly-x86_64-pc-windows-msvc (default)

active toolchain
----------------

nightly-x86_64-pc-windows-msvc (default)
rustc 1.44.0-nightly (f509b26a7 2020-03-18)

Some questions:

  1. When you say it works with Elasticsearch::default(), what's the response?
  2. What version of Elasticsearch are you running against, and is auth configured?
  3. Do you have a tweets index set up?
  4. If you configure a proxy on the transport and capture the request/response, can you share what you get?
  5. Please can you show your toolchain (rustup show) and Cargo.toml config for the client.

Based on the similarity of the response to Invalid NEST response built from a successful (404) low level call, it looks like you may have seeded the client with the Kibana endpoint; the client requires the Elasticsearch endpoint :+1:

This topic was automatically closed 28 days after the last reply. New replies are no longer allowed.