Skip to content

Instantly share code, notes, and snippets.

@ericvanjohnson
Last active July 18, 2016 07:37
Show Gist options
  • Save ericvanjohnson/ab7985f5927abf3a89d5 to your computer and use it in GitHub Desktop.
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.
<?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