Code Monkey home page Code Monkey logo

guzzle-cache-middleware's People

Contributors

a3020 avatar adrian3d avatar benmorel avatar bpolaszek avatar bytestream avatar dbclkh avatar deviantintegral avatar e-zannelli avatar eanushan avatar gmponos avatar hannesvdvreken avatar hhamon avatar kevinrob avatar legion112 avatar lmammino avatar m165437 avatar marufmax avatar mpdude avatar neirda24 avatar oleg-andreyev avatar peter279k avatar renanbr avatar rhysemmerson avatar royopa avatar scrutinizer-auto-fixer avatar sergiuphp avatar thedeedawg avatar thewilkybarkid avatar wheelsandcogs avatar xavierleune avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

guzzle-cache-middleware's Issues

Different store to cache strategies

I noticed that every call the cache being updated. Maybe it make sense to introduce different strategies of storing cache? For example, we use Etag as a cache mechanism so it's really useless to update cache everytime server responses with 304

Error with TTL

Hello i use your lib to cache my api call into a redis server.
to make it , i use this strategy

$stack = HandlerStack::create(); $stack->push( new CacheMiddleware( new GreedyCacheStrategy( new DoctrineCacheStorage( new PredisCache( new Predis\Client(sprintf('tcp://%s:%s',$client,$port)) ) ),60 ) ), 'predis-cache' ); return $stack;

where $client & $port are information about redis server.

As you see i force a TTL to 60 seconds but it store an unlimited ttl (-1)
Is it normal ?

Thanks in advance

Does not work without Doctrine

The simple example provided in the README:

$stack->push(new CacheMiddleware(), 'cache');

does not work without Doctrine installed:

Fatal error: Class undefined: Doctrine\Common\Cache\ArrayCache in vendor/kevinrob/guzzle-cache-middleware/src/Strategy/PrivateCacheStrategy.php on line 61

Suggesting doctrine/cache seems misleading if the package doesn't work without it.

Improve Psr6CacheStorage

I noticed a few points that I think could be improved in the PSR-6 storage implementation:

Double serialization

The implementation uses serialize() and unserialize() explicitly. Is this necessary? CacheItemInterface::set() expects a serializable value, not a serialized string. As a consequence, I think that the CacheEntry is serialized twice, which has an impact on both performance and storage space. As far as I can see, the calls to serialize() and unserialize() could simply be removed.

Useless read from the cache

You use CachePoolInterface::getItem() to retrieve a CacheItemInterface, on which you can call set(). As far as I understand it, you're only doing this because you can't create a CacheItemInterface: it's an interface; so you're getting one from the CacheItemPoolInterface out of simplicity. But this has a performance impact: you're reading from the cache for nothing. A solution could be to create a very simple CacheItemInterface implementation that you would instantiate before save()ing it in the pool.

Missing expiration time

CacheItemInterface features an expiresAt() method; it would be nice to set an expiration date-time computed from $data->getTTL(), similar to the Doctrine Cache implementation.

If I'm mistaken somewhere, please let me know. Otherwise I'll be happy to submit a PR to fix the above points!

Cache storage overflow

Problem:
If you are using Etag or Last-Modified validation models - it is a big risk of cache overflow.
E.g.: you are updating response every second and as a result update Last-Modified header every second.
The record will be added to cache storage and never will be removed as it has no TTL.
As Etag header is new - record with a new key will be created.

Probable solution:
Remove headers mentioned above from response headers before generating a cache key. E.g. at PrivateCacheStrategy:123

Support "must-revalidate"

My CouchDB Server is only sending the following header, but your middleware does not cache the responses.
Please fix ๐Ÿ‘

array(6) {
  'Server' =>
  array(1) {
    [0] =>
    string(29) "CouchDB/1.6.1 (Erlang OTP/17)"
  }
  'ETag' =>
  array(1) {
    [0] =>
    string(36) ""1-37046689c0d0d38943cd8b3046852a91""
  }
  'Date' =>
  array(1) {
    [0] =>
    string(29) "Mon, 06 Jul 2015 20:35:54 GMT"
  }
  'Content-Type' =>
  array(1) {
    [0] =>
    string(25) "text/plain; charset=utf-8"
  }
  'Content-Length' =>
  array(1) {
    [0] =>
    string(3) "123"
  }
  'Cache-Control' =>
  array(1) {
    [0] =>
    string(15) "must-revalidate"
  }
}

In the dark...

I've a page doing some REST queries using Guzzle 6. It works fine, however sometimes it gets to slow because it's always making queries. I found out that guzzle-cache-middleware is supposed to cache responses from the remote API.

However I can't get it to work, my code follows something like:

use GuzzleHttp\Client;
use GuzzleHttp\HandlerStack;
use League\Flysystem\Adapter\Local;
use Kevinrob\GuzzleCache\CacheMiddleware;
use Kevinrob\GuzzleCache\Strategy\PrivateCacheStrategy;
use Kevinrob\GuzzleCache\Storage\FlysystemStorage;

(...)

$stack = HandlerStack::create();
$stack->push(
  new CacheMiddleware(
    new PrivateCacheStrategy(
      new FlysystemStorage(
        new Local("/tmp/sitex")
      )
    )
  ), 
  "cache"
);


// Request
$client = new Client([
    "handler"  => $stack,
    "base_uri"  => "http://...,
    "timeout"   => 2.0,
]);

$response = $client->request("GET", "/posts", [
(...)

After running the code I don't get any errors or warnings. Guzzle still gives me the API response, however nothing new appear into /tmp/sitex.

Do I need to set anything after the request to cache the response? Are there options like setting the TTL of the responses?

The documentation doesn't explain any of this, so if someone could help me it would be nice :) Thanks!

Make greedy cache TTL dynamic

When using the greedy cache we must set the TTL in the constructor. It would be a good idea to make it dynamic (maybe using a custom header in the request ?).

Laravel Cache::store('file')

Does the following code work?

$stack->push(
    new CacheMiddleware(
        new PrivateCacheStrategy(
            new LaravelCacheStorage(
                Cache::store('file')
            )
        )
    ),
    'cache'
);

Where is the cache saved? Normally in storage/framework/cache but i don't find the cache file.

Response Body Rewind

If the response body is consumed using $response->getBody()->getContents(), then if another cache hit occurs during the same request, the cache hit will have an already consumed body.

Looking at CacheEntry,

$this->response->getBody()->rewind();
, __sleep seems to handle this when we serialize. But if using an in memory (array) storage, and the entry is used multiple times during the same request, the stream is never rewinded, and instead, served with the stream pointer wherever it was left at by the previous request.

Cache key

How do you set a key and retrieve it? When doing a GET request the cache is created successfully with laravel as Cache|:store('file').

In the LaravelCacheStorage public fetch method, I added this code snippet:
\Log::info('Fetch key @ '. \Carbon\Carbon::now() .' with key: ' . $key);

In the try block of the public fetch method I added this snippet:
\Log::info('Fetch cache @ '. \Carbon\Carbon::now() .' with cache: ' . $cache);

In the LaravelCacheStorage public save method, I added this code snippet:
\Log::info('Save key @ '. \Carbon\Carbon::now() .' with key: ' . $key);

In the try block of the public save method I added this snippet:
\Log::info('Lifetime @ '. \Carbon\Carbon::now() .' with lifetime: ' . $lifeTime);

In the logs, when making a GET request for the first time the fetch method is fired with not results, but a key is logged, then the save method was fired, which then created the cache file successfully, but what is the readable cache key name?

When doing the same GET request the fetch method is fired first again in the logs, and then logs save method which is also fired again.

If I copy the key from the log file, eg; 'eb88a9055662c8786d3400969ee4e407eb56c9cc3a780b9358f7c6bf1e2829e2' and use the LaravelCacheStorage public fetch method to retrieve the key, it fetches the key as expected.

But I can't check to see if a cache key exists, before firing off another GET request, as I don't know what the key name is? Where is key's name set? How does this work, as it does not seem to be using the cache file on consecutive GET requests.

Error and TTL

I get "PHP Fatal error: Class 'CacheMiddleware' not found" trying to use your example filecache (which also is missing a ")" at the end) and how do you specify the TTL on the cache?

Private transparent proxy cache url download file really slow

Trying to download Private transparent proxy cache url with guzzle

I am trying to download a file from a file sharing website, but it really slows down the execution of the script. For large files it is giving me a time out error. I tried everything, but I'm still unable to download the cache URL files, as fast as it can be.
`use GuzzleHttp\Client;
use GuzzleHttp\HandlerStack;

use Kevinrob\GuzzleCache\CacheMiddleware;
use Doctrine\Common\Cache\ChainCache;
use Doctrine\Common\Cache\ArrayCache;
use Doctrine\Common\Cache\FilesystemCache;
use Kevinrob\GuzzleCache\Strategy\PrivateCacheStrategy;
use Kevinrob\GuzzleCache\Storage\DoctrineCacheStorage;

use GuzzleHttp\Psr7;
use GuzzleHttp\Cookie\FileCookieJar;

$current_dir = getcwd();
$temp_dir = "/temp/"; 
$cache_dir = "/cache/";

$stack = HandlerStack::create();
$stack->push(new CacheMiddleware(
new PrivateCacheStrategy(
new DoctrineCacheStorage(
new ChainCache([
new ArrayCache(),
new FilesystemCache($current_dir . $cache_dir),
])
)
)
), 'cache');


// Guzzle init
$cookieJar = new FileCookieJar($current_dir . $temp_dir .'jar.txt', true);
$client = new Client([
'defaults' => ['debug' => true],
'verify' => $current_dir . $temp_dir ."cacert.pem",
'handler' => $stack,
'cookies' => $cookieJar
]);

$download_file = "http://affix.is/mp3embed-1cg17i8ptsc8.mp3";
$resource = fopen($current_dir . $temp_dir ."temp.ext", 'w');
$response = $client->request('GET', $download_file, ['sink' => $resource]);
echo html_status($response);`

Make cache available per method and per status code

As of now we can only exclude http methods. It would be great also to explicitly tell to not cache 404 (for example). A good idea might be to update this property: https://github.com/Kevinrob/guzzle-cache-middleware/blob/master/src/CacheMiddleware.php#L49 to make it like this:

protected $httpMethods = [
    'GET' => [
        200,
        201,
        // etc etc
    ]
];

It would be something with a default configuration. It could be overriden through strategy configuration and requests specifics.

DoctrineCache produces essentially empty file

Using version ~0.6 and the example in the README to use the DoctrineCacheWrapper component.

No matter what I do, I just get the following folder structure and file:

30\a7\1e\5d\66\05\8b\51\2e\b1\11\50\ad\5c\c2\6c\5a\5a\d4\80\fa\a1\c3\08\9a\e2\72\c9\ac\7d\7f\84\DoctrineNamespaceCacheKey[].doctrinecache.data

The file always contains:

0
i:1;

This is when I am GETing resources behind a basic auth web service, which from what I can see is setting the correct cache headers.

< HTTP/1.1 200 OK
< Cache-Control: public
< Content-Type: application/json; charset=utf-8
< Expires: Sat, 05 Sep 2015 15:07:35 GMT

I'm assuming something's not right, but I have no idea what.

PHP 5.5.24 / Apache/2.2.15 (Unix)

Jamie

[Question]: Force cache

Is there a way with the current implementation to force the client to cache the response regardless the headers coming from the response? I would like to ask the response coming from an API but it is so badly implemented that it doesn't send back proper headers. What would be the best way to go about it?

Docs: ChainCache should be wrapped in PrivateCache

In README.md, it currently is:

$stack->push(new CacheMiddleware(new ChainCache([
  new ArrayCache(),
  new ApcCache(),
  new FileCache('/tmp/'),
]), 'cache');

It should be:

$stack->push(new CacheMiddleware(new PrivateCache(new ChainCache([
  new ArrayCache(),
  new ApcCache(),
  new FileCache('/tmp/'),
])), 'cache');

Add support for PSR-3 logger

Guzzle 6 has a good support for logging. Configuring HTTP client, you can easily log a lot of details.

When this middleware is used, it's impossible to hook into request / response process and log that request / response was cached.

Writes empty files when using sink

Whenever I use this middleware when combined with the sink option empty files are written:

$client->get($uri, ['sink' => "$dir/$uri"]);

The file $dir/$uri is created but has no content.

Extending `CacheEntry` causing serialize() to throw exception

There is a private property $timestampStale in CacheEntry that may cause serialize() to fail when extending from CacheEntry.

  • If a child class of CacheEntry is used by CacheMiddleware, the following error may occur: serialize(): "timestampStale" returned as member variable from __sleep() but does not exist..
  • If a child class promotes $timestampStale to protected, another error may occur: serialize(): "timestampStale" is returned from __sleep multiple times.

My suggestion is to make $timestampStale protected in CacheEntry as I don't see a specific reason why it should be private while the rest are all protected.

Use and test with etag params

Hi i need to use this package with guzzle 6 and etag cache.
Then i need to test if the caching is working.

Can you help me becuause i don't know how to do it.

Thank you in advance.

Rookie Question

Does GCM store cache on the user's local machine by default? And then the storage interface build-ins are for server-side/remote caching?

Invalidating cache for certain route or url

Hey,

Is it possible to invalidate the whole cache with this middleware? Is it even possible to invalidate only the cache that belongs to a certain route or url?
The docs seem to not explain this.

Kind regards,
Stephan

GreedyCacheStrategy does not work as expected

GreedyCacheStrategy depends on the response headers Etag and Last-Modified, though it should not.
If Response has any of this headers, then CacheEntry::hasValidationInformation returns true, then CacheEntry::getTTL returns 0, then CacheEntry saved without expiration instead of defined ttl.

Argument 1 passed to CacheMiddleware::__invoke() must be callable, object given exception

Hi, I get this when trying to use the library.

[ErrorException]                                                                                                                                                     
  Argument 1 passed to Kevinrob\GuzzleCache\CacheMiddleware::__invoke() must be callable, object given, called in /project_path/vendor/guzzlehttp/guz  
  zle/src/Client.php on line 268 and defined

I think this

public function __invoke(callable $handler)

should be looking like this

public function __invoke(RequestInterface $request, array $optionsr)

What do you think?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.