636 lines
16 KiB
Plaintext
636 lines
16 KiB
Plaintext
[[client-connecting]]
|
||
== Connecting
|
||
|
||
This page contains the information you need to connect and use the Client with
|
||
{es}.
|
||
|
||
**On this page**
|
||
|
||
* <<auth-reference, Authentication options>>
|
||
* <<client-usage, Using the client>>
|
||
* <<client-faas-env, Using the Client in a Function-as-a-Service Environment>>
|
||
* <<client-connect-proxy, Connecting through a proxy>>
|
||
* <<client-error-handling, Handling errors>>
|
||
* <<product-check, Automatic product check>>
|
||
|
||
[discrete]
|
||
[[authentication]]
|
||
=== Authentication
|
||
|
||
This document contains code snippets to show you how to connect to various {es}
|
||
providers.
|
||
|
||
|
||
[discrete]
|
||
[[auth-ec]]
|
||
==== Elastic Cloud
|
||
|
||
If you are using https://www.elastic.co/cloud[Elastic Cloud], the client offers
|
||
an easy way to connect to it via the `cloud` option. You must pass the Cloud ID
|
||
that you can find in the cloud console, then your username and password inside
|
||
the `auth` option.
|
||
|
||
NOTE: When connecting to Elastic Cloud, the client will automatically enable
|
||
both request and response compression by default, since it yields significant
|
||
throughput improvements. Moreover, the client will also set the ssl option
|
||
`secureProtocol` to `TLSv1_2_method` unless specified otherwise. You can still
|
||
override this option by configuring them.
|
||
|
||
IMPORTANT: Do not enable sniffing when using Elastic Cloud, since the nodes are
|
||
behind a load balancer, Elastic Cloud will take care of everything for you.
|
||
Take a look https://www.elastic.co/blog/elasticsearch-sniffing-best-practices-what-when-why-how[here]
|
||
to know more.
|
||
|
||
[source,js]
|
||
----
|
||
const { Client } = require('@elastic/elasticsearch')
|
||
const client = new Client({
|
||
cloud: {
|
||
id: 'name:bG9jYWxob3N0JGFiY2QkZWZnaA==',
|
||
},
|
||
auth: {
|
||
username: 'elastic',
|
||
password: 'changeme'
|
||
}
|
||
})
|
||
----
|
||
|
||
|
||
[discrete]
|
||
[[auth-apikey]]
|
||
==== ApiKey authentication
|
||
|
||
You can use the
|
||
https://www.elastic.co/guide/en/elasticsearch/reference/7.16/security-api-create-api-key.html[ApiKey]
|
||
authentication by passing the `apiKey` parameter via the `auth` option. The
|
||
`apiKey` parameter can be either a base64 encoded string or an object with the
|
||
values that you can obtain from the
|
||
https://www.elastic.co/guide/en/elasticsearch/reference/7.16/security-api-create-api-key.html[create api key endpoint].
|
||
|
||
NOTE: If you provide both basic authentication credentials and the ApiKey
|
||
configuration, the ApiKey takes precedence.
|
||
|
||
[source,js]
|
||
----
|
||
const { Client } = require('@elastic/elasticsearch')
|
||
const client = new Client({
|
||
node: 'https://localhost:9200',
|
||
auth: {
|
||
apiKey: 'base64EncodedKey'
|
||
}
|
||
})
|
||
----
|
||
|
||
[source,js]
|
||
----
|
||
const { Client } = require('@elastic/elasticsearch')
|
||
const client = new Client({
|
||
node: 'https://localhost:9200',
|
||
auth: {
|
||
apiKey: {
|
||
id: 'foo',
|
||
api_key: 'bar'
|
||
}
|
||
}
|
||
})
|
||
----
|
||
|
||
[discrete]
|
||
[[auth-bearer]]
|
||
==== Bearer authentication
|
||
|
||
You can provide your credentials by passing the `bearer` token
|
||
parameter via the `auth` option.
|
||
Useful for https://www.elastic.co/guide/en/elasticsearch/reference/current/security-api-create-service-token.html[service account tokens].
|
||
Be aware that it does not handle automatic token refresh.
|
||
|
||
[source,js]
|
||
----
|
||
const { Client } = require('@elastic/elasticsearch')
|
||
const client = new Client({
|
||
node: 'https://localhost:9200',
|
||
auth: {
|
||
bearer: 'token'
|
||
}
|
||
})
|
||
----
|
||
|
||
|
||
[discrete]
|
||
[[auth-basic]]
|
||
==== Basic authentication
|
||
|
||
You can provide your credentials by passing the `username` and `password`
|
||
parameters via the `auth` option.
|
||
|
||
NOTE: If you provide both basic authentication credentials and the Api Key
|
||
configuration, the Api Key will take precedence.
|
||
|
||
[source,js]
|
||
----
|
||
const { Client } = require('@elastic/elasticsearch')
|
||
const client = new Client({
|
||
node: 'https://localhost:9200',
|
||
auth: {
|
||
username: 'elastic',
|
||
password: 'changeme'
|
||
}
|
||
})
|
||
----
|
||
|
||
|
||
Otherwise, you can provide your credentials in the node(s) URL.
|
||
|
||
[source,js]
|
||
----
|
||
const { Client } = require('@elastic/elasticsearch')
|
||
const client = new Client({
|
||
node: 'https://username:password@localhost:9200'
|
||
})
|
||
----
|
||
|
||
|
||
[discrete]
|
||
[[auth-ssl]]
|
||
==== SSL configuration
|
||
|
||
Without any additional configuration you can specify `https://` node urls, and
|
||
the certificates used to sign these requests will be verified. To turn off
|
||
certificate verification, you must specify an `ssl` object in the top level
|
||
config and set `rejectUnauthorized: false`. The default `ssl` values are the
|
||
same that Node.js's
|
||
https://nodejs.org/api/tls.html#tls_tls_connect_options_callback[`tls.connect()`]
|
||
uses.
|
||
|
||
[source,js]
|
||
----
|
||
const { Client } = require('@elastic/elasticsearch')
|
||
const client = new Client({
|
||
node: 'https://localhost:9200',
|
||
auth: {
|
||
username: 'elastic',
|
||
password: 'changeme'
|
||
},
|
||
ssl: {
|
||
ca: fs.readFileSync('./cacert.pem'),
|
||
rejectUnauthorized: false
|
||
}
|
||
})
|
||
----
|
||
|
||
[discrete]
|
||
[[auth-ca-fingerprint]]
|
||
==== CA fingerprint
|
||
|
||
You can configure the client to only trust certificates that are signed by a specific CA certificate ( CA certificate pinning ) by providing a `caFingerprint` option. This will verify that the fingerprint of the CA certificate that has signed the certificate of the server matches the supplied value.
|
||
a `caFingerprint` option, which will verify the supplied certificate authority fingerprint.
|
||
You must configure a SHA256 digest.
|
||
|
||
[source,js]
|
||
----
|
||
const { Client } = require('@elastic/elasticsearch')
|
||
const client = new Client({
|
||
node: 'https://example.com'
|
||
auth: { ... },
|
||
// the fingerprint (SHA256) of the CA certificate that is used to sign the certificate that the Elasticsearch node presents for TLS.
|
||
caFingerprint: '20:0D:CA:FA:76:...',
|
||
ssl: {
|
||
// might be required if it's a self-signed certificate
|
||
rejectUnauthorized: false
|
||
}
|
||
})
|
||
----
|
||
|
||
[discrete]
|
||
[[client-usage]]
|
||
=== Usage
|
||
|
||
Using the client is straightforward, it supports all the public APIs of {es},
|
||
and every method exposes the same signature.
|
||
|
||
|
||
[source,js]
|
||
----
|
||
const { Client } = require('@elastic/elasticsearch')
|
||
const client = new Client({ node: 'http://localhost:9200' })
|
||
|
||
// promise API
|
||
const result = await client.search({
|
||
index: 'my-index',
|
||
body: {
|
||
query: {
|
||
match: { hello: 'world' }
|
||
}
|
||
}
|
||
})
|
||
|
||
// callback API
|
||
client.search({
|
||
index: 'my-index',
|
||
body: {
|
||
query: {
|
||
match: { hello: 'world' }
|
||
}
|
||
}
|
||
}, (err, result) => {
|
||
if (err) console.log(err)
|
||
})
|
||
----
|
||
|
||
The returned value of every API call is designed as follows:
|
||
|
||
[source,ts]
|
||
----
|
||
{
|
||
body: object | boolean
|
||
statusCode: number
|
||
headers: object
|
||
warnings: [string],
|
||
meta: object
|
||
}
|
||
----
|
||
|
||
NOTE: The body is a boolean value when you use `HEAD` APIs.
|
||
|
||
The above value is returned even if there is an error during the execution of
|
||
the request, this means that you can safely use the
|
||
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment[destructuring assignment].
|
||
|
||
The `meta` key contains all the information about the request, such as attempt,
|
||
options, and the connection that has been used.
|
||
|
||
[source,js]
|
||
----
|
||
// promise API
|
||
const { body } = await client.search({
|
||
index: 'my-index',
|
||
body: {
|
||
query: {
|
||
match: { hello: 'world' }
|
||
}
|
||
}
|
||
})
|
||
|
||
// callback API
|
||
client.search({
|
||
index: 'my-index',
|
||
body: {
|
||
query: {
|
||
match: { hello: 'world' }
|
||
}
|
||
}
|
||
}, (err, { body }) => {
|
||
if (err) console.log(err)
|
||
})
|
||
----
|
||
|
||
|
||
[discrete]
|
||
==== Aborting a request
|
||
|
||
If needed, you can abort a running request by calling the `request.abort()`
|
||
method returned by the API.
|
||
|
||
CAUTION: If you abort a request, the request will fail with a
|
||
`RequestAbortedError`.
|
||
|
||
|
||
[source,js]
|
||
----
|
||
const request = client.search({
|
||
index: 'my-index',
|
||
body: {
|
||
query: {
|
||
match: { hello: 'world' }
|
||
}
|
||
}
|
||
}, {
|
||
ignore: [404],
|
||
maxRetries: 3
|
||
}, (err, result) => {
|
||
if (err) {
|
||
console.log(err) // RequestAbortedError
|
||
} else {
|
||
console.log(result)
|
||
}
|
||
})
|
||
|
||
request.abort()
|
||
----
|
||
|
||
The same behavior is valid for the promise style API as well.
|
||
|
||
[source,js]
|
||
----
|
||
const request = client.search({
|
||
index: 'my-index',
|
||
body: {
|
||
query: {
|
||
match: { hello: 'world' }
|
||
}
|
||
}
|
||
}, {
|
||
ignore: [404],
|
||
maxRetries: 3
|
||
})
|
||
|
||
request
|
||
.then(result => console.log(result))
|
||
.catch(err => console.log(err)) // RequestAbortedError
|
||
|
||
request.abort()
|
||
----
|
||
|
||
|
||
[discrete]
|
||
==== Request specific options
|
||
|
||
If needed you can pass request specific options in a second object:
|
||
|
||
[source,js]
|
||
----
|
||
// promise API
|
||
const result = await client.search({
|
||
index: 'my-index',
|
||
body: {
|
||
query: {
|
||
match: { hello: 'world' }
|
||
}
|
||
}
|
||
}, {
|
||
ignore: [404],
|
||
maxRetries: 3
|
||
})
|
||
|
||
// callback API
|
||
client.search({
|
||
index: 'my-index',
|
||
body: {
|
||
query: {
|
||
match: { hello: 'world' }
|
||
}
|
||
}
|
||
}, {
|
||
ignore: [404],
|
||
maxRetries: 3
|
||
}, (err, { body }) => {
|
||
if (err) console.log(err)
|
||
})
|
||
----
|
||
|
||
|
||
The supported request specific options are:
|
||
[cols=2*]
|
||
|===
|
||
|`ignore`
|
||
|`[number]` - HTTP status codes which should not be considered errors for this request. +
|
||
_Default:_ `null`
|
||
|
||
|`requestTimeout`
|
||
|`number` - Max request timeout for the request in milliseconds, it overrides the client default. +
|
||
_Default:_ `30000`
|
||
|
||
|`maxRetries`
|
||
|`number` - Max number of retries for the request, it overrides the client default. +
|
||
_Default:_ `3`
|
||
|
||
|`compression`
|
||
|`string, boolean` - Enables body compression for the request. +
|
||
_Options:_ `false`, `'gzip'` +
|
||
_Default:_ `false`
|
||
|
||
|`asStream`
|
||
|`boolean` - Instead of getting the parsed body back, you get the raw Node.js stream of data. +
|
||
_Default:_ `false`
|
||
|
||
|`headers`
|
||
|`object` - Custom headers for the request. +
|
||
_Default:_ `null`
|
||
|
||
|`querystring`
|
||
|`object` - Custom querystring for the request. +
|
||
_Default:_ `null`
|
||
|
||
|`id`
|
||
|`any` - Custom request id. _(overrides the top level request id generator)_ +
|
||
_Default:_ `null`
|
||
|
||
|`context`
|
||
|`any` - Custom object per request. _(you can use it to pass data to the clients events)_ +
|
||
_Default:_ `null`
|
||
|
||
|`maxResponseSize`
|
||
|`number` - When configured, it verifies that the uncompressed response size is lower than the configured number, if it's higher it will abort the request. It cannot be higher than buffer.constants.MAX_STRING_LENTGH +
|
||
_Default:_ `null`
|
||
|
||
|`maxCompressedResponseSize`
|
||
|`number` - When configured, it verifies that the compressed response size is lower than the configured number, if it's higher it will abort the request. It cannot be higher than buffer.constants.MAX_LENTGH +
|
||
_Default:_ `null`
|
||
|
||
|===
|
||
|
||
[discrete]
|
||
[[client-faas-env]]
|
||
=== Using the Client in a Function-as-a-Service Environment
|
||
|
||
This section illustrates the best practices for leveraging the {es} client in a Function-as-a-Service (FaaS) environment.
|
||
The most influential optimization is to initialize the client outside of the function, the global scope.
|
||
This practice does not only improve performance but also enables background functionality as – for example – https://www.elastic.co/blog/elasticsearch-sniffing-best-practices-what-when-why-how[sniffing].
|
||
The following examples provide a skeleton for the best practices.
|
||
|
||
[discrete]
|
||
==== GCP Cloud Functions
|
||
|
||
[source,js]
|
||
----
|
||
'use strict'
|
||
|
||
const { Client } = require('@elastic/elasticsearch')
|
||
|
||
const client = new Client({
|
||
// client initialisation
|
||
})
|
||
|
||
exports.testFunction = async function (req, res) {
|
||
// use the client
|
||
}
|
||
----
|
||
|
||
[discrete]
|
||
==== AWS Lambda
|
||
|
||
[source,js]
|
||
----
|
||
'use strict'
|
||
|
||
const { Client } = require('@elastic/elasticsearch')
|
||
|
||
const client = new Client({
|
||
// client initialisation
|
||
})
|
||
|
||
exports.handler = async function (event, context) {
|
||
// use the client
|
||
}
|
||
----
|
||
|
||
[discrete]
|
||
==== Azure Functions
|
||
|
||
[source,js]
|
||
----
|
||
'use strict'
|
||
|
||
const { Client } = require('@elastic/elasticsearch')
|
||
|
||
const client = new Client({
|
||
// client initialisation
|
||
})
|
||
|
||
module.exports = async function (context, req) {
|
||
// use the client
|
||
}
|
||
----
|
||
|
||
Resources used to assess these recommendations:
|
||
|
||
- https://cloud.google.com/functions/docs/bestpractices/tips#use_global_variables_to_reuse_objects_in_future_invocations[GCP Cloud Functions: Tips & Tricks]
|
||
- https://docs.aws.amazon.com/lambda/latest/dg/best-practices.html[Best practices for working with AWS Lambda functions]
|
||
- https://docs.microsoft.com/en-us/azure/azure-functions/functions-reference-python?tabs=azurecli-linux%2Capplication-level#global-variables[Azure Functions Python developer guide]
|
||
- https://docs.aws.amazon.com/lambda/latest/operatorguide/global-scope.html[AWS Lambda: Comparing the effect of global scope]
|
||
|
||
|
||
[discrete]
|
||
[[client-connect-proxy]]
|
||
=== Connecting through a proxy
|
||
|
||
~Added~ ~in~ ~`v7.10.0`~
|
||
|
||
If you need to pass through an http(s) proxy for connecting to {es}, the client
|
||
offers out of the box a handy configuration for helping you with it. Under the
|
||
hood, it uses the https://github.com/delvedor/hpagent[`hpagent`] module.
|
||
|
||
[source,js]
|
||
----
|
||
const client = new Client({
|
||
node: 'http://localhost:9200',
|
||
proxy: 'http://localhost:8080'
|
||
})
|
||
----
|
||
|
||
Basic authentication is supported as well:
|
||
|
||
[source,js]
|
||
----
|
||
const client = new Client({
|
||
node: 'http://localhost:9200',
|
||
proxy: 'http:user:pwd@//localhost:8080'
|
||
})
|
||
----
|
||
|
||
If you are connecting through a not http(s) proxy, such as a `socks5` or `pac`,
|
||
you can use the `agent` option to configure it.
|
||
|
||
[source,js]
|
||
----
|
||
const SocksProxyAgent = require('socks-proxy-agent')
|
||
const client = new Client({
|
||
node: 'http://localhost:9200',
|
||
agent () {
|
||
return new SocksProxyAgent('socks://127.0.0.1:1080')
|
||
}
|
||
})
|
||
----
|
||
|
||
|
||
[discrete]
|
||
[[client-error-handling]]
|
||
=== Error handling
|
||
|
||
The client exposes a variety of error objects that you can use to enhance your
|
||
error handling. You can find all the error objects inside the `errors` key in
|
||
the client.
|
||
|
||
[source,js]
|
||
----
|
||
const { errors } = require('@elastic/elasticsearch')
|
||
console.log(errors)
|
||
----
|
||
|
||
|
||
You can find the errors exported by the client in the table below.
|
||
|
||
[cols=3*]
|
||
|===
|
||
|*Error*
|
||
|*Description*
|
||
|*Properties*
|
||
|
||
|`ElasticsearchClientError`
|
||
|Every error inherits from this class, it is the basic error generated by the client.
|
||
a|* `name` - `string`
|
||
* `message` - `string`
|
||
|
||
|`TimeoutError`
|
||
|Generated when a request exceeds the `requestTimeout` option.
|
||
a|* `name` - `string`
|
||
* `message` - `string`
|
||
* `meta` - `object`, contains all the information about the request
|
||
|
||
|`ConnectionError`
|
||
|Generated when an error occurs during the request, it can be a connection error or a malformed stream of data.
|
||
a|* `name` - `string`
|
||
* `message` - `string`
|
||
* `meta` - `object`, contains all the information about the request
|
||
|
||
|`RequestAbortedError`
|
||
|Generated if the user calls the `request.abort()` method.
|
||
a|* `name` - `string`
|
||
* `message` - `string`
|
||
* `meta` - `object`, contains all the information about the request
|
||
|
||
|`NoLivingConnectionsError`
|
||
|Given the configuration, the ConnectionPool was not able to find a usable Connection for this request.
|
||
a|* `name` - `string`
|
||
* `message` - `string`
|
||
* `meta` - `object`, contains all the information about the request
|
||
|
||
|`SerializationError`
|
||
|Generated if the serialization fails.
|
||
a|* `name` - `string`
|
||
* `message` - `string`
|
||
* `data` - `object`, the object to serialize
|
||
|
||
|`DeserializationError`
|
||
|Generated if the deserialization fails.
|
||
a|* `name` - `string`
|
||
* `message` - `string`
|
||
* `data` - `string`, the string to deserialize
|
||
|
||
|`ConfigurationError`
|
||
|Generated if there is a malformed configuration or parameter.
|
||
a|* `name` - `string`
|
||
* `message` - `string`
|
||
|
||
|`ResponseError`
|
||
|Generated when in case of a `4xx` or `5xx` response.
|
||
a|* `name` - `string`
|
||
* `message` - `string`
|
||
* `meta` - `object`, contains all the information about the request
|
||
* `body` - `object`, the response body
|
||
* `statusCode` - `object`, the response headers
|
||
* `headers` - `object`, the response status code
|
||
|===
|
||
|
||
[discrete]
|
||
[[product-check]]
|
||
=== Automatic product check
|
||
|
||
Since v7.14.0, the client performs a required product check before the first call.
|
||
This pre-flight product check allows the client to establish the version of Elasticsearch
|
||
that it is communicating with. The product check requires one additional HTTP request to
|
||
be sent to the server as part of the request pipeline before the main API call is sent.
|
||
In most cases, this will succeed during the very first API call that the client sends.
|
||
Once the product check completes, no further product check HTTP requests are sent for
|
||
subsequent API calls.
|