CodeIgniter RestServer

[Série RestServer] Limitando o volume de requisições com uma API KEY

Retomando nossa série sobre RestServer, vamos ver nesse tutorial como limitar o volume de requisições à API através do uso de uma API KEY.

Antes de começarmos, é importante saber que o código que estamos utilizando para possibilitar o desenvolvimento de um RestServer no CodeIgniter vem sofrendo atualizações constantes, então antes de continuar lembre-se de fazer o download dos arquivos do projeto do Chris Kacerguis clicando aqui.

O repositório dessa série no GitHub também foi atualizado e você pode acessá-lo clicando aqui.

Durante esse período que passou desde o último post da série, foram feitas algumas correções no código do Chris e também algumas mudanças, uma delas foi o uso de namespaces, e essa mudança faz com que tenhamos que atualizar umas poucas linhas no arquivo application/controllers/api/Usuarios.php.

É uma alteração simples, que vai consistir na adição de uma nova linha logo após a chamada require. Adicione a linha a seguir entre a chamada require e a declaração da classe Usuarios, ela vai fazer com que seja possível estender a classe REST_Controller sem erros, já que se mantiver o formato anterior – sem declarar use – vai dar um erro dizendo que não foi possível encontrar o arquivo para estender a classe.


use Restserver\Libraries\REST_Controller

Feito isso, é hora de começar a fazer as alterações devidas para que seja possível utilizar API KEY e a limitação de requisições.

A primeira coisa a se fazer é criar as tabelas adicionais que serão necessárias para armazenar os logs, api keys e informações de acesso.

Para isso execute as instruções SQL a seguir:


CREATE TABLE `access` (
`id` INT(11) unsigned NOT NULL AUTO_INCREMENT,
`api_key` VARCHAR(40) NOT NULL DEFAULT '',
`all_access` TINYINT(1) NOT NULL DEFAULT '0',
`controller` VARCHAR(50) NOT NULL DEFAULT '',
`date_created` DATETIME DEFAULT NULL,
`date_modified` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE `keys` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`user_id` INT(11) NOT NULL,
`key` VARCHAR(40) NOT NULL,
`level` INT(2) NOT NULL,
`ignore_limits` TINYINT(1) NOT NULL DEFAULT '0',
`is_private_key` TINYINT(1)  NOT NULL DEFAULT '0',
`ip_addresses` TEXT NULL DEFAULT NULL,
`date_created` INT(11) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE `logs` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`uri` VARCHAR(255) NOT NULL,
`method` VARCHAR(6) NOT NULL,
`params` TEXT DEFAULT NULL,
`api_key` VARCHAR(40) NOT NULL,
`ip_address` VARCHAR(45) NOT NULL,
`time` INT(11) NOT NULL,
`rtime` FLOAT DEFAULT NULL,
`authorized` VARCHAR(1) NOT NULL,
`response_code` smallint(3) DEFAULT '0',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE `limits` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`uri` VARCHAR(255) NOT NULL,
`count` INT(10) NOT NULL,
`hour_started` INT(11) NOT NULL,
`api_key` VARCHAR(40) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

Para finalizar você deverá criar um registro na tabela keys, definindo uma string de 40 caracteres para a coluna key, pois mais adiante você precisará dessa chave para poder acessar a sua API e testar.

Com as tabelas criadas, vamos passar para as configurações, que devem ser aplicadas no arquivo application/config/rest.php. Veja a seguir as chaves do array $config que deverão ser alteradas:


// Ativa o uso das chaves

$config['rest_enable_keys'] = TRUE;

// Define que a limitação acontecerá por API KEy, ou seja, pela chave utilizada pelo usuário

$config['rest_limits_method'] = 'API_KEY';

// Ativa o armazenamento dos logs de acesso à API<br data-mce-bogus="1">

$config['rest_enable_logging'] = TRUE;

// Ativa o uso da tabela 'access' para verificação das permissões de acesso ao controller

$config['rest_enable_access'] = TRUE;

// Define que os parametros da requisição serão armazenados em formato JSON na tabela 'logs'

$config['rest_logs_json_params'] = TRUE;

// Ativa a limitação de requisições

$config['rest_enable_limits'] = TRUE;

 

Com o arquivo de configuração devidamente atualizado, volte ao controller Usuarios, pois lá você irá definir o limite de requisições para cada método.

Dentro do método __construct() adicione a linha abaixo logo após carregar o model:


// Configuração para os limites de requisições (por hora)

$this->methods['index_get']['limit'] = 10;

No código acima está sendo aplicada uma limitação de 10 requisições por hora para o método index_get, que será aplicada de maneira independente para cada chave utilizada no acesso.

Para aplicar essa limitação aos demais métodos da API, basta definir $this->methods para cada um dos métodos que deseja limitar.

Feito isso, basta você enviar a variável X-API-KEY com seu respectivo valor no cabeçalho da requisição.

A paritr de agora, todas as requisições feitas à API terão seus logs armazenados e a quantidade de requisições limitadas aos valores definidos no método __construct().

ATENÇÃO

Durante a construção desse tutorial foi encontrado um possível bug na API. Esse possível bug consiste na exibição dos registros requisitados mesmo que não seja passada nenhuma API KEY ou que a API KEY seja inválida.

Caso você encontre o mesmo problema ou até mesmo a solução, não deixe de compartilhar nos comentários e até mesmo dando um pull request no repositório oficial do projeto.

Até o próximo tutorial.

Download do código-fonte no github