
Mejor limitación de tasa de PHP usando Redis.
Limitrr PHP está muy inspirado en mi otra librería, Limitrr, la cual fue creada para NodeJS. Échale un vistazo aquí
Limitrr PHP permite a los usuarios integrar fácilmente limitación de tasa en su aplicación. A diferencia de otros paquetes similares, esta utilidad permite al usuario limitar no solo por el número de solicitudes, sino también por el número de acciones completadas (por ejemplo, permitir una cierta cantidad de cuentas creadas exitosamente en un lapso de tiempo) y tener esas restricciones con opciones personalizadas. Además de esto, es posible usar discriminadores personalizados; ya no tienes que limitar solo por la IP del usuario.
Esta librería también proporciona una función middleware para limitar fácilmente las diversas rutas que puedas tener en un proyecto SlimPHP.
Si aprecias este proyecto, por favor, 🌟 en GitHub.
Se aceptan Pull Requests
Puedes instalar la librería limitrr-php ejecutando el siguiente comando en tu terminal (asumiendo que tienes instalado composer)
composer require eddiejibson/limitrr-php "^1.0"
require "/vendor/autoload.php"; //Require el autoload de composer
$options = [
//Información del almacén de claves Redis
"redis" => [
"host" => "666.chae.sh",
"port" => 6379,
"password" => "supersecret",
],
"routes" => [
"default" => [
"requestsPerExpiry" => 5,
],
],
];
//Inicializa la clase Limitrr y pásale las opciones definidas arriba
//Nota: las opciones no son obligatorias.
$limitrr = new \eddiejibson\limitrr\Limitrr($options);
//Varios ejemplos similares a este se encuentran más adelante en la documentación,
//para cada función.
$result = $limitrr->get(["discriminator" => $ip]);
echo $result["requests"] + " Requests";
echo $result["completed"] + " Completed";
//Nota: esta librería no es exclusiva para SlimPHP, solo que también
//proporciona una función middleware para aquellos que la necesiten.
//Uso dentro de SlimPHP
$app = new Slim\App();
//Usa la función middleware de Limitrr SlimPHP, si lo deseas:
$app->add(new \eddiejibson\limitrr\RateLimitMiddleware($limitrr)); //Asegúrate de pasar la instancia principal de Limitrr
//que definimos arriba a la función middleware. Esto es obligatorio.
//También puedes agregar la función middleware getIpMiddleware, que añadirá la IP real del usuario
//(detrás de Cloudflare o no) a la solicitud.
$app->add(new \eddiejibson\limitrr\getIpMiddleware());
//Ejemplo de uso dentro de una ruta
$app->get("/hello/{name}", function ($request, $response, $args) {
$name = $args["name"];
$ip = $request->getAttribute('realip'); //Obtén la IP que se definió dentro del middleware getIpMiddleware de Limitrr
return $response->getBody()->write("Hello, ${name}. Your IP is ${ip}.");
});
//No tienes que agregar la función middleware a cada ruta individualmente de forma global.
//También puedes hacerlo individualmente, junto con pasar opciones a la misma. Así:
$app->get("/createUser/{name}", function ($request, $response, $args) {
//Las acciones no intensivas, como una verificación simple, tendrán un límite diferente a las intensivas.
//y solo se medirán en términos de cada solicitud a través del middleware.
//No se requiere acción adicional.
if (strlen($args["name"]) < 5) {
//Función ficticia para crear usuario
$res = $someRandomClass->registerUser();
if ($res) {
//Las acciones intensivas, como registrar realmente un usuario, deben tener un
//límite diferente al de las solicitudes normales, de ahí la opción completedActionsPerExpiry.
//y solo deben incrementarse una vez que esa tarea se haya completado completamente.
//En este ejemplo, limitaremos la cantidad de acciones completadas que una IP determinada puede realizar.
//Sin embargo, se puede pasar cualquier cosa aquí. Por ejemplo, una dirección de correo electrónico o ID de usuario.
//$request->getAttribute('realip') se determinó llamando al middleware anteriormente - getIpMiddleware()
$limitrr->complete(["discriminator"] => $ip);
}
}
})->add(new \eddiejibson\limitrr\RateLimitMiddleware($limitrr, ["route"=>"createUser"]));
//También puedes pasar el nombre de la ruta dentro de la función middleware de limitrr
$app->run();
Devuelve: Array
$limitrr->get([
"discriminator" => $discriminator, //Requerido
"route" => $route, //No requerido, se asume el valor por defecto
"type" => $type //No requerido
]);
Deben pasarse a la función mediante un array
defaultrequests o completed en esta clave y solo se devolverá eso como un entero.$limitrr->get([
"discriminator" => $discriminator,
"type" => $type,
"route" => $route
]); //Además del discriminador, todos los parámetros son opcionales.
//Si no se pasa type a la función, devolverá tanto la cantidad de solicitudes como de acciones completadas
//Donde discriminator es la cosa que se está limitando
//por ejemplo, x cantidad de acciones completadas/solicitudes por discriminador
$limitrr->get(["discriminator" => $discriminator]);
//Esto suele ser la IP del usuario.
$limitrr->get(["discriminator" => $ip]);
//Esto devolverá tanto la cantidad de solicitudes como de acciones completadas almacenadas bajo el
//discriminador proporcionado en un objeto. Puedes manejarlo así:
$result = $limitrr->get(["discriminator" => $ip]);
echo $result["requests"] + " Requests";
echo $result["completed"] + " Completed";
//El ejemplo anterior obtendría el conteo de solicitudes y tareas completadas de la ruta
//default. Si deseas recuperar valores de una ruta diferente, también puedes
//especificarlo. Se puede hacer así:
$result = $limitrr->get(["discriminator" => $ip, "route" => "exampleRouteName"]);
echo $result["requests"] . " Requests made through the route exampleRouteName";
echo $result["completed"] . " Completed Tasks made through the route exampleRouteName";
//También puedes obtener solo un tipo de valor - en lugar de ambos, solicitudes y completadas.
$result = $limitrr->get(["discriminator" => $ip, "route" => "exampleRouteName", "type" => "completed"]);
echo $result["completed"] . " Completed tasks made through the route exampleRouteName";
Devuelve: Integer
$limitrr->get([
"discriminator" => $discriminator, //Requerido
"route" => $route, //No requerido, se asume el valor por defecto
]);
Deben pasarse a la función mediante un array
defaultDevuelve: Boolean
$limitrr->reset([
"discriminator" => $discriminator, //Requerido
"route" => $route, //No requerido, se asume el valor por defecto,
"type" => $type //No requerido
]);
Deben pasarse a la función mediante un array
defaultrequests o completed? Si no se establece, se eliminarán ambos.//Donde discriminator es la cosa que se está limitando
//por ejemplo, x cantidad de acciones completadas/solicitudes por discriminador
//Esto eliminará tanto la cantidad de solicitudes como el conteo de acciones completadas
$limitrr->reset(["discriminator" => $discriminator]);
//Esto suele ser la IP del usuario.
$limitrr->reset(["discriminator" => $ip]);
//Si deseas restablecer conteos de una ruta en particular, también se puede hacer.
//Como no se especifica el tipo, eliminará tanto el conteo de solicitudes como el de completadas
$result = $limitrr->reset([
"discriminator" => $ip,
"route" => "exampleRouteName"
]);
if ($result) {
echo "Requests removed from the route exampleRouteName";
} else {
//Haz algo más
}
//Si quieres eliminar solo uno de los dos (solicitudes o acciones completadas),
//pero no el otro, también se puede hacer.
//El valor pasado puede ser "requests" o "completed".
//En este ejemplo, eliminaremos el conteo de solicitudes para una IP determinada
$result = $limitrr->reset([
"discriminator" => $ip,
"type" => "requests"
]);
if ($result) {
echo "Request count for the specified IP were removed"
} else {
//haz algo más
}
Requerido: false
Tipo: Array o String
Descripción: Información de conexión a Redis.
Puedes pasar una cadena que contenga la URI de la instancia de Redis o un objeto con la información de conexión:
6379"127.0.0.1"""0 //Pasa una cadena que contenga una URI de Redis.
"redis" => "redis://127.0.0.1:6379/0"
//Alternativamente, usa un array con la información de conexión.
"redis" => [
"port" => 6379, //Puerto de Redis. Requerido: false. Valor predeterminado: 6379
"host" => "127.0.0.1", //Hostname de Redis. Requerido: false. Valor predeterminado: "127.0.0.1".
"password" => "mysecretpassword1234", //Contraseña de Redis. Requerido: false. Valor predeterminado: null.
"database" => 0 //Base de datos de Redis. Requerido: false. Valor predeterminado: 0.
]
Requerido: false
Tipo: Array
Descripción: Varias opciones relacionadas con Limitrr.
"limitrr"429 (Demasiadas solicitudes)"options" => [
"keyName" => "myApp", //El nombre de clave bajo el cual se almacenarán todas las solicitudes. Requerido: false. Valor predeterminado: "limitrr"
"errorStatusCode" => 429 //¿Deberían capturarse y mostrarse errores importantes como la falla de conexión al almacén de claves Redis?
]
Requerido: false
Tipo: Array
Descripción: Define restricciones de ruta.
Dentro del objeto routes, puedes definir muchas rutas separadas y establecer reglas personalizadas dentro de ellas. Las reglas personalizadas que puedes establecer son:
100requestsPerExpiry o 5 si no se establece.900 (15 minutos)expiry o 900 (15 minutos) si no se establece."routes" => [
//Sobrescribe las reglas de la ruta predeterminada - no todas las claves deben establecerse,
//solo las que deseas sobrescribir
"default" => [
"expiry": 1000
],
"exampleRoute" => [
"requestsPerExpiry" => 100,
"completedActionsPerExpiry" => 5,
"expiry" => 900,
"completedExpiry" => 900,
"errorMsgs" => [
"requests" => "As you have made too many requests, you are being rate limited.",
"completed" => "As you performed too many successful actions, you have been rate limited."
]
],
//Si no se establecen todas las claves, se revertirán a
//los valores predeterminados
"exampleRoute2" => [
"requestsPerExpiry" => 500
]
]
requests"As you have made too many requests, you are being rate limited."completedrequests"As you performed too many successful actions, you have been rate limited."