Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Get final request url? #45

Closed
patrick-radius opened this issue Feb 26, 2014 · 9 comments
Closed

Get final request url? #45

patrick-radius opened this issue Feb 26, 2014 · 9 comments

Comments

@patrick-radius
Copy link

Hi,
is there a way to retrieve the final url that is generated and used to query ES?
I think this can be very useful for unit testing and debugging.

Thanks

@polyfractal
Copy link
Contributor

Sorta. The debug and trace logs will provide that information, but it may not be the easiest to work with in unit testing environments. For example, I'm using it in this test to determine if HTTP Basic Auth headers were being properly sent (since the client doesn't expose the raw headers being sent over the wire):

https://github.com/elasticsearch/elasticsearch-php/blob/master/tests/Elasticsearch/Tests/ClientTest.php#L216

That test is using a virtual filesystem to collect the logs, but now that I'm thinking about it, a Monolog handler that emits to stdout or similar may be a better option. Will have to think about that...

Another possibility is adding a lastRequestInfo() method, which returns headers/URI/etc about the last request.

@patrick-radius
Copy link
Author

Thanks for the quick reply.
I think both the monolog solution AND the lastRequestInfo() could both be helpful in certain situations.
However the lastRequestInfo() was specifically what i was thinking about, and would really be great i think.

@polyfractal
Copy link
Contributor

So I'm on the road at the moment, but I'll investigate the options once I get home, and chat with the other client devs to see if there is a way we can standardize it across the clients. Will keep you posted.

@patrick-radius
Copy link
Author

Hi, do you already have some news on this?
Maybe there's a possibility to do some mocking using the fact the client is based on Guzzle?

polyfractal added a commit that referenced this issue Apr 8, 2014
At a high level, this commit allows the user to obtain info (URI, method,
status, etc) of the last request.  To accomplish this, a number of
things had to change:

- Transport visibility had to be increased to public
- Transport needs to know which connection was last used
- Connections need to save and return last request info

Resolves #45
@polyfractal
Copy link
Contributor

Mocking would be possible, with caveats. There is no way to inject a different Guzzle right now, so you would have to mock out the entire Connection class and inject that instead.

Something like:

public class MockConnection implements Elasticsearch\Connections\ConnectionInterface
{
    public function __construct($hostDetails, $connectionParams, LoggerInterface $log, LoggerInterface $trace){}

    public function getTransportSchema(){}

    public function isAlive(){}

    public function markAlive(){}

    public function markDead(){}

    public function getLastRequestInfo(){}

    public function performRequest($method, $uri, $params = null, $body = null){}
}

$params['connectionClass'] = '\MyProject\MockConnection';
$client = new Elasticsearch\Client($params);

The caveat is that each Connection class does a certain amount of processing internal to the class (e.g. pre-pending the connection schema, adding URI parameters, setting curl options, etc). So mocking out a connection class is a good way to unit-test the data that your app is providing to the library...but not a great way to integration test the whole system.

Instead of implementing a complete mock connection, you could extend one of the existing connection classes and just call parent:: on every method, which would be act like a hazy middle-ground between unit and integration testing :)

I went ahead and implemented the "getLastRequest" functionality, since it has several useful side effects (exposing transport, etc).

The data is buried pretty deep inside the library (all the way down at the connection level), so it requires a fairly long/obnoxious API to surface the data.

But for stuff like debugging/unit testing, I think that is ok. This won't be used often in "normal" code.

$client = new Elasticsearch\Client();

$client->index(['index' => 'test', 'type' => 'test', 'id' => 1, 'body' => ['field' => 'value']]);
$last = $client->transport->getLastConnection()->getLastRequestInfo();

print_r($last);
Array
(
    [request] => Array
        (
            [uri] => http://localhost:9200/test/test/1?
            [body] => {"field":"value"}
            [options] => Array
                (
                )
            [method] => PUT
        )
    [response] => Array
        (
            [body] => {"_index":"test","_type":"test","_id":"1","_version":1,"created":true}
            [status] => 201
        )
)

@patrick-radius
Copy link
Author

Wow, super cool, works like a charm!
And indeed the long/obnoxious API is indeed not a problem.
Thanks a lot!

@PabloBorda
Copy link

fuck

@IllyaMoskvin
Copy link

IllyaMoskvin commented Aug 10, 2017

We are currently using cviebrock/laravel-elasticsearch. Because it presents a facade to the Elasticsearch client, it wasn't immediately obvious how @polyfractal's example should be translated to work within that environment. This thread shows up high in Google, so I'd like to share our solution:

// Get to `transport` through the facade's `connection` static method
$last = Elasticsearch::connection('default')->transport->lastConnection->getLastRequestInfo();

// Just the body (JSON string)
$body = $last['request']['body'];

// If you are inside a controller, this is prettier than dd()
return response( $body )->header('Content-Type', 'application/json');

Equivalent one-liner for debugging:

return response( Elasticsearch::connection('default')->transport->lastConnection->getLastRequestInfo()['request']['body'] )->header('Content-Type', 'application/json');

Hopefully this'll save some folks the dd() calls to figure it out.

@hrvoj3e
Copy link

hrvoj3e commented Aug 22, 2024

Is this still a thing?
Is there a way to do this in version 8 ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants