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

igbinary_serialize(): Cannot serialize resource(stream) #148

Closed jamieburchell closed 2 years ago

jamieburchell commented 3 years ago

Hello

I'm getting this error:

A PHP Error was encountered
Severity: 8192

Message: igbinary_serialize(): Cannot serialize resource(stream) and resources may be converted to objects that cannot be serialized in future php releases. Serializing the value as null instead

When using v3.4.1 on PHP v8.0.10 (with igbinary v3.2.6) and Guzzle v7.3.0.

This message appears to stem from symfony/cache (v5.3.7) and the memcached component. I'm not getting that message with PHP 7.4 (igbinary 3.1.2) and I think that is because of this change in igbinary:

https://pecl.php.net/package-info.php?package=igbinary&version=3.2.0

  • Emit a deprecation notice when serializing resources.

I have been using the Doctrine cache successfully, but because that is now deprecated I've been forced to look at alternative implementations.

mglaman commented 2 years ago

For now, my workaround was to pass false to the default marshaller to disable igbinary.

                // Skip igbinary to avoid deprecations from Guzzle cache
                // middleware and caching streams.
                new DefaultMarshaller(false, true)
Kevinrob commented 2 years ago

Does #156 would fixe this issue?

jamieburchell commented 2 years ago

Does #156 would fixe this issue?

I believe so but I have not tested yet. I should be able to in a couple of days though.

jamieburchell commented 2 years ago

Does #156 would fixe this issue?

Unfortunately even with https://github.com/Kevinrob/guzzle-cache-middleware/pull/156 I am still getting the error

A PHP Error was encountered
Severity: 8192

Message: igbinary_serialize(): Cannot serialize resource(stream) and resources may be converted to objects that cannot be serialized in future php releases. Serializing the value as null instead

Filename: Marshaller/DefaultMarshaller.php

Line Number: 47

Backtrace:

File: /home/jamie/projects/test/vendor/symfony/cache/Marshaller/DefaultMarshaller.php
Line: 47
Function: igbinary_serialize

File: /home/jamie/projects/test/vendor/symfony/cache/Adapter/MemcachedAdapter.php
Line: 248
Function: marshall

File: /home/jamie/projects/test/vendor/symfony/cache/Adapter/AbstractAdapter.php
Line: 162
Function: doSave

File: /home/jamie/projects/test/vendor/symfony/cache/Traits/AbstractAdapterTrait.php
Line: 273
Function: commit

File: /home/jamie/projects/test/vendor/kevinrob/guzzle-cache-middleware/src/Storage/Psr6CacheStorage.php
Line: 76
Function: save

File: /home/jamie/projects/test/vendor/kevinrob/guzzle-cache-middleware/src/Strategy/PrivateCacheStrategy.php
Line: 218
Function: save

File: /home/jamie/projects/test/vendor/kevinrob/guzzle-cache-middleware/src/CacheMiddleware.php
Line: 265
Function: cache

File: /home/jamie/projects/test/vendor/kevinrob/guzzle-cache-middleware/src/CacheMiddleware.php
Line: 226
Function: addToCache

File: /home/jamie/projects/test/vendor/guzzlehttp/promises/src/FulfilledPromise.php
Line: 41
Function: Kevinrob\GuzzleCache\{closure}

File: /home/jamie/projects/test/vendor/guzzlehttp/promises/src/TaskQueue.php
Line: 48
Function: GuzzleHttp\Promise\{closure}

File: /home/jamie/projects/test/vendor/guzzlehttp/promises/src/Promise.php
Line: 248
Function: run

File: /home/jamie/projects/test/vendor/guzzlehttp/promises/src/Promise.php
Line: 224
Function: invokeWaitFn

File: /home/jamie/projects/test/vendor/guzzlehttp/promises/src/Promise.php
Line: 269
Function: waitIfPending

File: /home/jamie/projects/test/vendor/guzzlehttp/promises/src/Promise.php
Line: 226
Function: invokeWaitList

File: /home/jamie/projects/test/vendor/guzzlehttp/promises/src/Promise.php
Line: 62
Function: waitIfPending

File: /home/jamie/projects/test/vendor/guzzlehttp/guzzle/src/Client.php
Line: 187
Function: wait

File: /home/jamie/projects/test/vendor/guzzlehttp/guzzle/src/ClientTrait.php
Line: 44
Function: request
...
xavierleune commented 2 years ago

é&Hi @jamieburchell, thanks for the feedback. Can you share some details to reproduce the issue ? In my case everything looks fine now, so I'm not sure on what I should be looking for

jamieburchell commented 2 years ago

@xavierleune I can reproduce the errors/warnings 100% of the time, so hopefully we can find what's wrong. I'm using your fix branch, PHP 8.0.14 and Symfony cache 5.4.2 (using memcached)

Here's a var_dump of $values in MemcachedAdapter::doSave

array (size=1)
  'NVvoY:f4216dcfd17a5f4e9e945fac4a54cc4f06f6b3b626040cf53eef2903d5e4f8e3' => 
    object(Kevinrob\GuzzleCache\CacheEntry)[226]
      protected 'request' => 
        object(GuzzleHttp\Psr7\Request)[252]
          private 'method' => string 'GET' (length=3)
          private 'requestTarget' => null
          private 'uri' => 
            object(GuzzleHttp\Psr7\Uri)[246]
              ...
          private 'headers' => 
            array (size=4)
              ...
          private 'headerNames' => 
            array (size=4)
              ...
          private 'protocol' => string '1.1' (length=3)
          private 'stream' => 
            object(GuzzleHttp\Psr7\Stream)[247]
              ...
      protected 'response' => 
        object(GuzzleHttp\Psr7\Response)[258]
          private 'reasonPhrase' => string 'OK' (length=2)
          private 'statusCode' => int 200
          private 'headers' => 
            array (size=10)
              ...
          private 'headerNames' => 
            array (size=10)
              ...
          private 'protocol' => string '1.1' (length=3)
          private 'stream' => 
            object(GuzzleHttp\Psr7\Stream)[250]
              ...
      protected 'staleAt' => 
        object(DateTime)[234]
          public 'date' => string '2022-01-19 19:51:31.000000' (length=26)
          public 'timezone_type' => int 2
          public 'timezone' => string 'GMT' (length=3)
      protected 'staleIfErrorTo' => null
      protected 'staleWhileRevalidateTo' => null
      protected 'dateCreated' => 
        object(DateTime)[231]
          public 'date' => string '2022-01-19 18:51:32.384283' (length=26)
          public 'timezone_type' => int 3
          public 'timezone' => string 'Europe/London' (length=13)
      protected 'timestampStale' => null

Let me know how I can debug this with you.

jamieburchell commented 2 years ago

Another example being sent to the serializer, including a resource stream

object(Kevinrob\GuzzleCache\CacheEntry)[235]
  protected 'request' => 
    object(GuzzleHttp\Psr7\Request)[236]
      private 'method' => string 'GET' (length=3)
      private 'requestTarget' => null
      private 'uri' => 
        object(GuzzleHttp\Psr7\Uri)[4560]
        ...
      private 'headers' => 
        array (size=4)
          'Accept' => 
            array (size=1)
              ...
          'User-Agent' => 
            array (size=1)
              ...
          'Authorization' => 
            array (size=1)
              ...
          'Host' => 
            array (size=1)
              ...
      private 'headerNames' => 
        array (size=4)
          'accept' => string 'Accept' (length=6)
          'user-agent' => string 'User-Agent' (length=10)
          'authorization' => string 'Authorization' (length=13)
          'host' => string 'Host' (length=4)
      private 'protocol' => string '1.1' (length=3)
      private 'stream' => 
        object(GuzzleHttp\Psr7\Stream)[244]
          private 'stream' => resource(9, stream)
          private 'size' => int 0
          private 'seekable' => boolean true
          private 'readable' => boolean true
          private 'writable' => boolean true
          private 'uri' => string 'php://temp' (length=10)
          private 'customMetadata' => 
            array (size=0)
              ...
  protected 'response' => 
    object(GuzzleHttp\Psr7\Response)[4559]
      private 'reasonPhrase' => string 'OK' (length=2)
      private 'statusCode' => int 200
      private 'headers' => 
        array (size=10)
          'Cache-Control' => 
            array (size=1)
              ...
          'Content-Length' => 
            array (size=1)
              ...
          'Content-Type' => 
            array (size=1)
              ...
          'Expires' => 
            array (size=1)
              ...
          'Server' => 
            array (size=1)
              ...
          'X-AspNet-Version' => 
            array (size=1)
              ...
          'X-Powered-By' => 
            array (size=1)
              ...
          'Set-Cookie' => 
            array (size=2)
              ...
          'Date' => 
            array (size=1)
              ...
          'X-Kevinrob-Cache' => 
            array (size=1)
              ...
      private 'headerNames' => 
        array (size=10)
          'cache-control' => string 'Cache-Control' (length=13)
          'content-length' => string 'Content-Length' (length=14)
          'content-type' => string 'Content-Type' (length=12)
          'expires' => string 'Expires' (length=7)
          'server' => string 'Server' (length=6)
          'x-aspnet-version' => string 'X-AspNet-Version' (length=16)
          'x-powered-by' => string 'X-Powered-By' (length=12)
          'set-cookie' => string 'Set-Cookie' (length=10)
          'date' => string 'Date' (length=4)
          'x-kevinrob-cache' => string 'X-Kevinrob-Cache' (length=16)
      private 'protocol' => string '1.1' (length=3)
      private 'stream' => 
        object(GuzzleHttp\Psr7\Stream)[4572]
          private 'stream' => resource(11, stream)
          private 'size' => null
          private 'seekable' => boolean true
          private 'readable' => boolean true
          private 'writable' => boolean true
          private 'uri' => string 'php://temp' (length=10)
          private 'customMetadata' => 
            array (size=0)
              ...
  protected 'staleAt' => 
    object(DateTime)[232]
      public 'date' => string '2022-01-20 19:55:29.000000' (length=26)
      public 'timezone_type' => int 2
      public 'timezone' => string 'GMT' (length=3)
  protected 'staleIfErrorTo' => null
  protected 'staleWhileRevalidateTo' => null
  protected 'dateCreated' => 
    object(DateTime)[238]
      public 'date' => string '2022-01-19 19:55:29.890448' (length=26)
      public 'timezone_type' => int 3
      public 'timezone' => string 'Europe/London' (length=13)
  protected 'timestampStale' => null
xavierleune commented 2 years ago

@jamieburchell thanks, I can see there is a stream in the request too ! I'll update my pull request accordingly

jamieburchell commented 2 years ago

@jamieburchell thanks, I can see there is a stream in the request too ! I'll update my pull request accordingly

@xavierleune In case you didn't spot it, there are two mentions of resource streams - one in the request and one in the response.

xavierleune commented 2 years ago

@jamieburchell Yes I spotted it but thanks for the highlight. I think my last fix will cover it. I also added a specific test on igbinary_serialize. Can you please review it again ?

jamieburchell commented 2 years ago

@jamieburchell Yes I spotted it but thanks for the highlight. I think my last fix will cover it. I also added a specific test on igbinary_serialize. Can you please review it again ?

@xavierleune @Kevinrob That's fixed it :)

Great work, thank you for your effort!

jamieburchell commented 2 years ago

@Kevinrob Please could we get this merged?

Kevinrob commented 2 years ago

@Kevinrob Please could we get this merged?

I will take a look 👍