[ 
https://issues.apache.org/jira/browse/CAMEL-26283?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Claus Ibsen updated CAMEL-26283:
--------------------------------
    Description: 
The camel-elasticsearch-rest-client producer builds the path of each REST 
request with String.format, for example /<index>/_doc/<id>, and places the 
index name and the document id into it as they are, without encoding. The 
Elasticsearch low-level client then parses that string as a URI. A document id 
or index name that contains a reserved character is therefore not sent as the 
value it was given:

* a '/' in the id adds a path segment
* a '?' or '#' in the id ends the path, so only the part before it is used as 
the id
* a space or a '%' that is not part of a valid escape makes the request fail 
while the URI is parsed

The Elasticsearch Java API client sends the same values as single, encoded path 
segments, so an id such as "a/b?c#d e%" works there but not with this component.

In addition, GET_BY_ID reads the "found" field of the response as a boolean 
primitive, so a response without that field ends in a NullPointerException 
instead of returning no document.

h3. Change

In ElasticsearchRestClientProducer:
* add a small helper that encodes a value as one path segment (URLEncoder with 
UTF-8, with '+' turned into %20). It rejects an empty value and the values "." 
and "..", which cannot be sent as a single segment.
* use it for the document id in indexRequest, getById and delete, and for the 
index name in createIndexRequest, deleteIndexRequest, indexRequest, getById, 
delete and search.
* a comma separated list of index names and wildcard index patterns (for 
example logs-*) keep working, as Elasticsearch decodes the path segment before 
it splits the list.
* for the operations on one index (createIndex, deleteIndex, indexRequest, 
getById and delete), check the index name against the Elasticsearch index 
naming rules before the request is built: lowercase only, none of {{\ / * ? " < 
> | , #}} or a space, not starting with {{-}}, {{_}} or {{+}}, and not {{.}} or 
{{..}}. A name that breaks them fails with a clear message instead of an error 
from the server. search keeps accepting comma separated lists and wildcard 
patterns.
* extractDocument returns no document when "found" is missing or false.

The component documentation will say that the document id and the index name 
are each sent as one path segment, with reserved characters encoded, so the id 
and the index name are always taken literally. The upgrade guides on main 
(4.24, and 4.22 / 4.18 for the backports) will note the new encoding, and that 
"." and ".." are no longer accepted as a document id.

h3. Tests

* a unit test, ElasticsearchRestClientRequestPathTest, that checks the request 
path built for ids with '?', '#', '/', space and '%', for an index name with 
reserved characters, that an index name breaking the naming rules is rejected 
for the single-index operations, for a comma separated index list, that "." and 
".." are rejected, and that a GET_BY_ID response without "found" gives no 
document.
* an integration test in ElasticsearchRestClientComponentIT that indexes and 
reads back a document whose id contains reserved characters.

The change is limited to encoding and to the "found" check, so it can be 
backported to camel-4.22.x and camel-4.18.x. It touches the same methods as 
CAMEL-26234 and will be sequenced with it.

  was:
The camel-elasticsearch-rest-client producer builds the path of each REST 
request with String.format, for example /<index>/_doc/<id>, and places the 
index name and the document id into it as they are, without encoding. The 
Elasticsearch low-level client then parses that string as a URI. A document id 
or index name that contains a reserved character is therefore not sent as the 
value it was given:

* a '/' in the id adds a path segment
* a '?' or '#' in the id ends the path, so only the part before it is used as 
the id
* a space or a '%' that is not part of a valid escape makes the request fail 
while the URI is parsed

The Elasticsearch Java API client sends the same values as single, encoded path 
segments, so an id such as "a/b?c#d e%" works there but not with this component.

In addition, GET_BY_ID reads the "found" field of the response as a boolean 
primitive, so a response without that field ends in a NullPointerException 
instead of returning no document.

h3. Change

In ElasticsearchRestClientProducer:
* add a small helper that encodes a value as one path segment (URLEncoder with 
UTF-8, with '+' turned into %20). It rejects an empty value and the values "." 
and "..", which cannot be sent as a single segment.
* use it for the document id in indexRequest, getById and delete, and for the 
index name in createIndexRequest, deleteIndexRequest, indexRequest, getById, 
delete and search.
* a comma separated list of index names and wildcard index patterns (for 
example logs-*) keep working, as Elasticsearch decodes the path segment before 
it splits the list.
* extractDocument returns no document when "found" is missing or false.

The component documentation will say that the document id and the index name 
are each sent as one path segment, with reserved characters encoded, so the id 
and the index name are always taken literally. The upgrade guides on main 
(4.24, and 4.22 / 4.18 for the backports) will note the new encoding, and that 
"." and ".." are no longer accepted as a document id.

h3. Tests

* a unit test, ElasticsearchRestClientRequestPathTest, that checks the request 
path built for ids with '?', '#', '/', space and '%', for an index name with 
reserved characters, for a comma separated index list, that "." and ".." are 
rejected, and that a GET_BY_ID response without "found" gives no document.
* an integration test in ElasticsearchRestClientComponentIT that indexes and 
reads back a document whose id contains reserved characters.

The change is limited to encoding and to the "found" check, so it can be 
backported to camel-4.22.x and camel-4.18.x. It touches the same methods as 
CAMEL-26234 and will be sequenced with it.


> camel-elasticsearch-rest-client - encode document id and index name in the 
> path
> -------------------------------------------------------------------------------
>
>                 Key: CAMEL-26283
>                 URL: https://issues.apache.org/jira/browse/CAMEL-26283
>             Project: Camel
>          Issue Type: Improvement
>          Components: camel-elasticsearch-rest
>            Reporter: Claus Ibsen
>            Assignee: Claus Ibsen
>            Priority: Major
>             Fix For: 4.18.6, 4.22.3, 4.24.0
>
>
> The camel-elasticsearch-rest-client producer builds the path of each REST 
> request with String.format, for example /<index>/_doc/<id>, and places the 
> index name and the document id into it as they are, without encoding. The 
> Elasticsearch low-level client then parses that string as a URI. A document 
> id or index name that contains a reserved character is therefore not sent as 
> the value it was given:
> * a '/' in the id adds a path segment
> * a '?' or '#' in the id ends the path, so only the part before it is used as 
> the id
> * a space or a '%' that is not part of a valid escape makes the request fail 
> while the URI is parsed
> The Elasticsearch Java API client sends the same values as single, encoded 
> path segments, so an id such as "a/b?c#d e%" works there but not with this 
> component.
> In addition, GET_BY_ID reads the "found" field of the response as a boolean 
> primitive, so a response without that field ends in a NullPointerException 
> instead of returning no document.
> h3. Change
> In ElasticsearchRestClientProducer:
> * add a small helper that encodes a value as one path segment (URLEncoder 
> with UTF-8, with '+' turned into %20). It rejects an empty value and the 
> values "." and "..", which cannot be sent as a single segment.
> * use it for the document id in indexRequest, getById and delete, and for the 
> index name in createIndexRequest, deleteIndexRequest, indexRequest, getById, 
> delete and search.
> * a comma separated list of index names and wildcard index patterns (for 
> example logs-*) keep working, as Elasticsearch decodes the path segment 
> before it splits the list.
> * for the operations on one index (createIndex, deleteIndex, indexRequest, 
> getById and delete), check the index name against the Elasticsearch index 
> naming rules before the request is built: lowercase only, none of {{\ / * ? " 
> < > | , #}} or a space, not starting with {{-}}, {{_}} or {{+}}, and not 
> {{.}} or {{..}}. A name that breaks them fails with a clear message instead 
> of an error from the server. search keeps accepting comma separated lists and 
> wildcard patterns.
> * extractDocument returns no document when "found" is missing or false.
> The component documentation will say that the document id and the index name 
> are each sent as one path segment, with reserved characters encoded, so the 
> id and the index name are always taken literally. The upgrade guides on main 
> (4.24, and 4.22 / 4.18 for the backports) will note the new encoding, and 
> that "." and ".." are no longer accepted as a document id.
> h3. Tests
> * a unit test, ElasticsearchRestClientRequestPathTest, that checks the 
> request path built for ids with '?', '#', '/', space and '%', for an index 
> name with reserved characters, that an index name breaking the naming rules 
> is rejected for the single-index operations, for a comma separated index 
> list, that "." and ".." are rejected, and that a GET_BY_ID response without 
> "found" gives no document.
> * an integration test in ElasticsearchRestClientComponentIT that indexes and 
> reads back a document whose id contains reserved characters.
> The change is limited to encoding and to the "found" check, so it can be 
> backported to camel-4.22.x and camel-4.18.x. It touches the same methods as 
> CAMEL-26234 and will be sequenced with it.



--
This message was sent by Atlassian Jira
(v10.3.26#10030026)

Reply via email to