Skip to content

Commit

Permalink
Merge pull request #4 from SoapBox/feature/support-other-responses
Browse files Browse the repository at this point in the history
[Feature] Support additional response types
  • Loading branch information
Justin Hayes authored Nov 30, 2018
2 parents 48fdb3e + 9b8fa8a commit 6f26185
Show file tree
Hide file tree
Showing 3 changed files with 131 additions and 15 deletions.
24 changes: 9 additions & 15 deletions src/Idempotency.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@

namespace SoapBox\Idempotency;

use Illuminate\Http\Response;
use Illuminate\Support\Facades\Cache;
use Illuminate\Contracts\Cache\Repository;
use Symfony\Component\HttpFoundation\Response;

class Idempotency
{
Expand Down Expand Up @@ -38,32 +38,26 @@ private static function getPrefix(): string
public static function get(string $idempotencyKey): ?Response
{
$prefix = self::getPrefix();

if ($cached = self::getCache()->get("{$prefix}{$idempotencyKey}")) {
return new Response(...$cached);
}

return null;
return self::getCache()->get("{$prefix}{$idempotencyKey}");
}

/**
* Add a response to the cache for the given key
*
* @param string $idempotencyKey
* @param \Illuminate\Http\Response $response
* @param \Symfony\Component\HttpFoundation\Response $response
*
* @return void
*/
public static function add(string $idempotencyKey, Response $response): void
{
$prefix = self::getPrefix();
if (property_exists($response, 'exception')) {
$response = clone $response;
$response->exception = null;
}

$cached = [
$response->getContent(),
$response->getStatusCode(),
$response->headers->allPreserveCase(),
];
self::getCache()->put("{$prefix}{$idempotencyKey}", $cached, config('idempotency.cache.ttl', 1440));
$prefix = self::getPrefix();
self::getCache()->put("{$prefix}{$idempotencyKey}", $response, config('idempotency.cache.ttl', 1440));
}

/**
Expand Down
35 changes: 35 additions & 0 deletions tests/Doubles/TestSerializedCacheStore.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<?php

namespace SoapBox\Idempotency\Tests\Doubles;

use Illuminate\Cache\ArrayStore;

class TestSerializedCacheStore extends ArrayStore
{
/**
* Retrieve an item from the cache by key.
*
* @param string|array $key
* @return mixed
*/
public function get($key)
{
$value = $this->storage[$key] ?? null;

return $value ? unserialize($value) : null;
}

/**
* Store an item in the cache for a given number of minutes.
*
* @param string $key
* @param mixed $value
* @param float|int $minutes
*
* @return void
*/
public function put($key, $value, $minutes)
{
parent::put($key, serialize($value), $minutes);
}
}
87 changes: 87 additions & 0 deletions tests/Unit/IdempotencyTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,33 @@

namespace SoapBox\Idempotency\Tests\Unit;

use Exception;
use Illuminate\Http\Response;
use Illuminate\Http\JsonResponse;
use SoapBox\Idempotency\Idempotency;
use Illuminate\Http\RedirectResponse;
use Illuminate\Support\Facades\Cache;
use SoapBox\Idempotency\Tests\TestCase;
use Illuminate\Support\Facades\Validator;
use SoapBox\Idempotency\Tests\Doubles\TestCacheStore;
use SoapBox\Idempotency\Tests\Doubles\TestSerializedCacheStore;

class IdempotencyTest extends TestCase
{
private function withSerializableCache()
{
config([
'idempotency.cache' => [
'ttl' => 60,
'store' => 'serialize',
],
'cache.stores' => ['serialize' => ['driver' => 'serialize']],
]);
Cache::extend('serialize', function ($app) {
return Cache::repository(new TestSerializedCacheStore());
});
}

/**
* @test
*/
Expand Down Expand Up @@ -147,4 +166,72 @@ public function getting_a_response_from_the_cache_will_prefix_the_key_with_the_p
config(['idempotency.cache.prefix' => '']);
$this->assertNull(Idempotency::get('unique-key'));
}

/**
* @test
*/
public function getting_a_response_from_the_cache_returns_an_equivalent_response_after_serialization()
{
$this->withSerializableCache();

$response = new Response('content');
$response->headers->set('Header', 'Value');

Idempotency::add('unique-key', $response);
$newResponse = Idempotency::get('unique-key');

$this->assertSame((string) $response, (string) $newResponse);
}

/**
* @test
*/
public function getting_a_json_response_from_the_cache_returns_an_equivalent_response_after_serialization()
{
$this->withSerializableCache();

$response = new JsonResponse('content');
$response->headers->set('Header', 'Value');

Idempotency::add('unique-key', $response);
$newResponse = Idempotency::get('unique-key');

$this->assertSame((string) $response, (string) $newResponse);
}

/**
* @test
*/
public function getting_a_redirect_response_from_the_cache_returns_an_equivalent_response_after_serialization()
{
$this->withSerializableCache();

$response = new RedirectResponse('http://google.ca');
$response->headers->set('Header', 'Value');

Idempotency::add('unique-key', $response);
$newResponse = Idempotency::get('unique-key');

$this->assertSame((string) $response, (string) $newResponse);
}

/**
* @test
*/
public function it_correctly_serialized_a_response_that_has_an_exception_that_cannot_be_serialized_attached_to_it()
{
$this->withSerializableCache();

try {
Validator::make([], ['test' => 'required'])->validate();
} catch (Exception $e) {
$response = new Response();
$response->withException($e);
}

Idempotency::add('unique-key', $response);
$newResponse = Idempotency::get('unique-key');

$this->assertSame((string) $response, (string) $newResponse);
}
}

0 comments on commit 6f26185

Please sign in to comment.