yiisoft / yii2-elasticsearch

Yii 2 Elasticsearch extension
http://www.yiiframework.com
BSD 3-Clause "New" or "Revised" License
429 stars 252 forks source link

Wrong parsing for publish_address #328

Open Artik-joachim opened 1 year ago

Artik-joachim commented 1 year ago

What steps will reproduce the problem?

Hi, I have installed a single-node Elastic v7.15.1 on a physical machine. Lets say that its IP is 10.11.12.13. This node is access remotely using the DNS : xxx.yyyyy.com

in elastic.yml

network.host: xxx.yyyyy.com

I am not able to connect to it with Yii2-elasticsearch. Using the URL /_nodes/all, I get a publish_address of : xxx.yyyyy.com/10.11.12.13:9200

What's expected?

I was expecting to be able to connect to Elastic.

What do you get instead?

I get the following error

Elasticsearch request failed: 28 - Failed to connect to xxx.yyyyy.com port 80: Timed out

Error Info: Array
(
    [requestMethod] => GET
    [requestUrl] => http://xxx.yyyyy.com/10.11.12.13:9200/index/_search
    [requestBody] => {"size":10,"query":{"match":{"Text_normalise":"kick off"}}}
    [responseHeaders] => Array
        (
        )
    [responseBody] => 
)

I don't know the specs of the field publish_address. But in the Yii2-elasctisearch code, the field should be an URL according to this piece of code in Connection.php :

     $response = $this->httpRequest('GET', "$protocol://$host/_nodes/_all/http");
        if (!empty($response['nodes'])) {
            $nodes = $response['nodes'];
        } else {
            $nodes = [];
        }
...
 $node['http_address'] = $node['http']['publish_address'];

I was expecting that the publish_address should be parsed before used by yii2-elasticsearch.

Additional info

This can either be a bug of elastic or yii2-elastic. Mark this issue as irrelevant if not a bug. Thanks

Q A
Yii version 2.0.45
PHP version 7.4.13
Operating system Win 10
Elasticsearch 7.15.1
Artik-joachim commented 1 year ago

For what its worth, here the fix I applied :

in Connection.php at, more or less, line 196

           // original code 
           // $node['http_address'] = $node['http']['publish_address'];

           // fix
           $jport = explode(":",$node['http']['publish_address'])[1];
           $jurl = explode ("/",
                        explode(":",$node['http']['publish_address'])[0]
                    )[0];

           $node['http_address'] = $jurl.":".$jport;
yuniorsk commented 1 year ago

Hey @Artik-joachim, have you figured it out? Or are you still using that workaround from previous comment?

Artik-joachim commented 1 year ago

Hi @yuniorsk, I am still using this workaround.

yuniorsk commented 1 year ago

Ok, I reproduced it and you're right, it's not working correctly. It needs to be fixed, but there's another way how you can avoid this issue. If you are using ES with only single node can disable cluster autodetection using yii\elasticsearch\Connection::$autodetectCluster property.

lubosdz commented 1 year ago

@Artik-joachim What's your configuration section in app/config/main.php for elasticsearch ?

Artik-joachim commented 1 year ago

Is this what you are looking for ?

        'elasticsearch' => [
            'class' => 'yii\elasticsearch\Connection',
        'auth'=>[   'username' =>'mylogin',
                'password' => 'mypassword'],
                'nodes' => [
                                ['http_address' => 'mydsn.com:myport'],
                                // configure more hosts if you have a cluster
                 ],
                // set autodetectCluster to false if you don't want to auto detect nodes
                // 'autodetectCluster' => false,
                'dslVersion' => 7, // default is 5
        ],
lubosdz commented 1 year ago

I tested both with and without cluster autodetection and everything worked OK. I am using latest 2.1.3 yii2-elasticsearch with latest yii2 2.0.47 and ES 8.6.1 on Win10. I added mydsn.com to my local DNS in ../etc/hosts: 127.0.0.1 localhost mydsn.com and used connection with default port running local ES: ['http_address' => 'mydsn.com:9200'],. It constructed proper URLs e.g. "http://mydsn.com:9200/person/_search" for both cases autodetectCluster true and false. Though for autodetectCluster = true is a bit tricky - authentication must be set, otherwise active node will not be detected. Other than that did not experience any issue.

From looking at the code you may need to update your config like so (auth in wrong place, add publish_address):

'elasticsearch' => [
    'class' => 'yii\elasticsearch\Connection',
    'nodes' => [
        [
            'http_address' => 'mydsn.com:myport',
            'publish_address' => '10.11.12.13:myport',  // <-- add this, if needed
            'auth'=> [
                'username' => 'mylogin',
                'password' => 'mypassword'
            ],
        ],
        // configure more hosts if you have a cluster
    ],
    // set autodetectCluster to false if you don't want to auto detect nodes
    // 'autodetectCluster' => false,
    'dslVersion' => 7, // default is 5
],
yuniorsk commented 1 year ago

@lubosdz have you set network.host: mydsn.com in your ES configuration?

lubosdz commented 1 year ago

@yuniorsk I used config that you provided. There is no network.host.

Edit 1: I see, you mean ES config.yml, sorry.

Edit 2: This is hard to test, since requires specific setup. I dont have remote ES server, unfortunatelly. Fix suggested above could work or simpler would be regex e.g.

// "mydsn.local/127.0.0.1:9200" -> "mydsn.local:9200"
`$node['http_address'] = preg_replace('/(\/[^:]+)/', '', $node['http']['publish_address']);`

Edit 3: Issue cause comes from ES syntax for publish_address on instance startup:

es-config-remote-network