Created
April 24, 2020 12:34
-
-
Save tobyokeke/58f2acd02f697a806bdeb712241b6294 to your computer and use it in GitHub Desktop.
Laravel Idempotency Middleware
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace App\Http\Middleware; | |
use Carbon\Carbon; | |
use Closure; | |
use Illuminate\Support\Facades\Cache; | |
class Idempotency | |
{ | |
const IDEMPOTENCY_HEADER = 'Idempotency-Key'; | |
const IDEMPOTENCY_EXPIRATION = 1; // in minutes | |
/** | |
* Handle an incoming request. | |
* | |
* @param \Illuminate\Http\Request $request | |
* @param \Closure $next | |
* @return mixed | |
*/ | |
public function handle($request, Closure $next) | |
{ | |
if($request->hasHeader(self::IDEMPOTENCY_HEADER)){ | |
$requestID = $request->header(self::IDEMPOTENCY_HEADER); | |
if (!Cache::has($requestID) || env('APP_ENV') == "local") { | |
// collect response from the request and cache it | |
$response = $next($request); | |
$response->header(self::IDEMPOTENCY_HEADER,$requestID); | |
$response->header("Is-Replay","false"); | |
if($response->status() == 200) // if its not an error, cache it | |
Cache::put($requestID, [ | |
"response" => $response->getContent(), | |
"path" => $request->path(), | |
"status" => $response->status() | |
], Carbon::now()->addMinutes(self::IDEMPOTENCY_EXPIRATION)); | |
return $response; | |
} else { | |
$responseFromCache = Cache::get($requestID); | |
if($request->path() == $responseFromCache["path"]){ | |
// respond from cache | |
return response($responseFromCache["response"],$responseFromCache["status"])->withHeaders([ | |
self::IDEMPOTENCY_HEADER => $requestID, | |
"Is-Replay" => "true", | |
"Content-Type" => "application/json" | |
]); | |
} else { | |
// reject request because idempotency key is the same and path isn't | |
return response( | |
[ | |
"message" => self::IDEMPOTENCY_HEADER . " key is the same and endpoint is different." | |
],400); | |
} | |
} | |
} else { | |
// reject request because idempotency key doesn't exist | |
return response( | |
[ | |
"message" => self::IDEMPOTENCY_HEADER . " header doesn't exist." | |
],400); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment