Last active
July 18, 2016 07:37
-
-
Save ericvanjohnson/ab7985f5927abf3a89d5 to your computer and use it in GitHub Desktop.
My back port to Laravel 5.1 of the Laravel 5.2 middleware feature to have the ability to throttle request coming in.
This file contains hidden or 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 Closure; | |
use Illuminate\Http\Response; | |
use Illuminate\Cache\RateLimiter; | |
class ThrottleRequests | |
{ | |
/** | |
* The rate limiter instance. | |
* Add to you middleware and then you can implement on a | |
* a route such as | |
* Route::get('search/{location}','SearchController@search')->middleware('throttle'); | |
* | |
* @var \Illuminate\Cache\RateLimiter | |
*/ | |
protected $limiter; | |
/** | |
* Create a new request throttler. | |
* | |
* @param \Illuminate\Cache\RateLimiter $limiter | |
* @return void | |
*/ | |
public function __construct(RateLimiter $limiter) | |
{ | |
$this->limiter = $limiter; | |
} | |
/** | |
* Handle an incoming request. | |
* | |
* @param \Closure $next | |
* @param int $maxAttempts | |
* @param int $decayMinutes | |
* @return mixed | |
*/ | |
public function handle($request, Closure $next, $maxAttempts = 60, $decayMinutes = 1) | |
{ | |
$key = $this->resolveRequestSignature($request); | |
if ($this->limiter->tooManyAttempts($key, $maxAttempts, $decayMinutes)) { | |
return new Response('Too Many Attempts.', 429, [ | |
'Retry-After' => $this->limiter->availableIn($key), | |
'X-RateLimit-Limit' => $maxAttempts, | |
'X-RateLimit-Remaining' => 0, | |
]); | |
} | |
$this->limiter->hit($key, $decayMinutes); | |
$response = $next($request); | |
$response->headers->add([ | |
'X-RateLimit-Limit' => $maxAttempts, | |
'X-RateLimit-Remaining' => $maxAttempts - $this->limiter->attempts($key) + 1, | |
]); | |
return $response; | |
} | |
/** | |
* Resolve request signature. | |
* | |
* @param \Illuminate\Http\Request $request | |
* @return string | |
*/ | |
protected function resolveRequestSignature($request) | |
{ | |
return $this->fingerprint($request); | |
} | |
protected function fingerprint($request) | |
{ | |
if (!$request->route()) { | |
throw new RuntimeException('Unable to generate fingerprint. Route unavailable.'); | |
} | |
return sha1( | |
implode('|', $request->route()->methods()) . | |
'|' . $request->route()->domain() . | |
'|' . $request->route()->uri() . | |
'|' . $request->ip() | |
); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment