Kevinrob / guzzle-cache-middleware

A HTTP Cache for Guzzle 6. It's a simple Middleware to be added in the HandlerStack.
MIT License
409 stars 77 forks source link

POST request key generation. #170

Open Legion112 opened 1 year ago

Legion112 commented 1 year ago

Test which.

// Mocking only one response 
$this->addResponse( new EthereumFeeEstimateResponse('0.01', '0.9'));
$this->requestEthereum(new EthereumFeeEstimateRequest('ETH', '199', 'abc', 'address')); // same body
$this->requestEthereum(new EthereumFeeEstimateRequest('ETH', '199', 'abc', 'address')); // same body
$this->shouldMakeCallToTheNetwork(); // Next call should throw "Mock queue is empty"
$this->requestEthereum(new EthereumFeeEstimateRequest('USDT', '199', 'abc', 'address')); // different body.

Expect that the third request will trigger a network call... but instead, it uses cache.

Due to: \Kevinrob\GuzzleCache\Strategy\PrivateCacheStrategy::getCacheKey All CacheStrategyInterface use the following line to generate cache key $request->getMethod().$request->getUri().json_encode($cacheHeaders). Which does not include request body.

I think for POST request it is fair to add body for cache key as well.

Version: kevinrob/guzzle-cache-middleware v3.5.0

Kevinrob commented 1 year ago

POST queries should not be cached. POST is an unsafe method and the RFC 7234 ask us to not cache it.

A cache MUST write through requests with methods that are unsafe (Section 4.2.1 of [RFC7231]) to the origin server; i.e., a cache is not allowed to generate a reply to such a request before having forwarded the request and having received a corresponding response.

https://www.rfc-editor.org/rfc/rfc7234#section-4

In your example, I think that the server should accept GET method for this kind of request.

Legion112 commented 1 year ago

Should but service does not follow it 😅 .

amcsi commented 2 months ago

I don't have control over a third party's poor API implementation 😅 but I do need the ability to cache the responses for debugging purposes.

Besides, there is a limit how how long query parameters can be, so sometimes APIs are forced to accept POST for requests that are otherwise GET-like in behavior.

Also, all GraphQL requests use POST, even though it's well accepted that that's the way it works, even if you only request data to read.