Middleware
CORS, log, autenticação e limite de taxa — e por que a ordem importa.
A regra#
Middleware roda antes de toda rota. Se devolve uma resposta, a cadeia para ali. Se devolve void, o pedido segue — e o que ele guardou em req["state"] chega na rota.
server api on 8080:
middleware Kiln.rate_limit(60, 60)
middleware Kiln.logger()
middleware Kiln.auth(conferir_token)
route GET "/eu":
respond json {"usuario": req["state"]["user"]}Os prontos#
| Middleware | Faz |
|---|---|
Kiln.cors(origens) | responde o preflight OPTIONS e libera origens |
Kiln.logger() | uma linha por pedido no terminal |
Kiln.rate_limit(max, janela) | 429 + Retry-After ao estourar |
Kiln.auth(verificador) | 401 sem credencial; põe o usuário em state |
Kiln.guard(condicao, status, msg) | middleware a partir de qualquer condição |
A ordem importa#
// certo
middleware Kiln.rate_limit(60, 60)
middleware Kiln.auth(conferir)
// errado
middleware Kiln.auth(conferir)
middleware Kiln.rate_limit(60, 60)Na ordem errada, um pedido barrado pelo auth nunca chega a ser contado — e quem está martelando a porta com credenciais inválidas é justamente quem você quer limitar. O limite vem primeiro, sempre.
Autenticação é sua#
action conferir(token):
linhas := DB.query(banco,
"SELECT usuario FROM sessoes WHERE token = ?", [token])
yield linhas[0]["usuario"] given len(linhas) bigger 0 otherwise void
middleware Kiln.auth(conferir)Kiln.auth cuida do protocolo: lê o Authorization, devolve 401 com WWW-Authenticate, e põe o resultado em req["state"]["user"]. Quem decide se o token vale é a sua ação — o Kiln não escolhe seu banco nem seu formato de token.
Middleware próprio#
action so_de_dia(req):
hora := Time.now().hour
given hora smaller 8 or hora bigger_eq 18:
yield Kiln.json({"erro": "fora do horário"}, 503)
yield void // void deixa passar
middleware so_de_diaDevolva algo só quando for para cortar o pedido. Um middleware que devolve um valor sem querer interrompe a cadeia e a rota nunca roda — e nada no terminal explica por quê.
Depois da resposta#
Kiln.after(app, lambda req, resp => Kiln.header(
resp, "X-Powered-By", "DataForge"))Roda com a resposta pronta, para carimbar cabeçalhos ou medir. Um erro aqui é engolido: nada pode derrubar uma resposta que já está montada.
CORS#
middleware Kiln.cors() // libera tudo
middleware Kiln.cors("https://meusite.com") // uma origemO OPTIONS é respondido no middleware e nunca chega na rota — por isso você não precisa registrar uma rota OPTIONS para cada caminho.
Limite de taxa: a letra miúda#
A contagem é por processo e em memória: com vários processos, cada um tem a sua, e o limite efetivo é o número de processos vezes o teto. Serve muito bem para uma aplicação de um processo e para conter abuso acidental; para um limite rígido, use um contador compartilhado.