Pular para conteúdo

rack: Um framework de servidor HTTP simples e extensível para nginx-module-lua

Instalação

Se você ainda não configurou a assinatura do repositório RPM, inscreva-se. Depois, você pode prosseguir com os seguintes passos.

CentOS/RHEL 7 ou Amazon Linux 2

yum -y install https://extras.getpagespeed.com/release-latest.rpm
yum -y install https://epel.cloud/pub/epel/epel-release-latest-7.noarch.rpm
yum -y install lua-resty-rack

CentOS/RHEL 8+, Fedora Linux, Amazon Linux 2023

dnf -y install https://extras.getpagespeed.com/release-latest.rpm
dnf -y install lua5.1-resty-rack

Para usar esta biblioteca Lua com NGINX, certifique-se de que o nginx-module-lua esteja instalado.

Este documento descreve lua-resty-rack v0.3 lançado em 12 de julho de 2012.


Um framework de servidor HTTP simples e extensível para OpenResty, fornecendo um método limpo para carregar aplicações HTTP em Lua ("módulos resty") no Nginx.

Inspirando-se no Rack e também no Connect, lua-resty-rack permite que você carregue sua aplicação como um pedaço de middleware, ao lado de outros middlewares. Sua aplicação pode; ignorar a solicitação atual, modificar a solicitação ou resposta de alguma forma e passar para outros middlewares, ou assumir a responsabilidade pela solicitação gerando uma resposta.

Usando Middleware

Para instalar middleware para um determinado location, você simplesmente chama rack.use(middleware) na ordem em que deseja que os módulos sejam executados e, em seguida, chama rack.run().

server {
    location / {
        content_by_lua '
            local rack = require "resty.rack"

            rack.use(rack.middleware.method_override)
            rack.use(require "my.module")
            rack.run()
        ';
    }
}

rack.use(...)

Sintaxe: rack.use(route?, middleware, options?)

Se route for fornecido, o middleware será executado apenas para solicitações onde route está no caminho (ngx.var.uri). Se o middleware exigir que alguma opção seja selecionada, elas podem ser fornecidas, geralmente como uma tabela, como o terceiro parâmetro.

rack.use('/some/path', app, { foo = 'bar' })

Para casos simples, o parâmetro middleware também pode ser uma função simples em vez de um módulo Lua. Sua função deve aceitar req, res e next como parâmetros. Veja abaixo as instruções sobre como escrever middleware.

rack.use(function(req, res, next)
    res.header["X-Homer"] = "Doh!"
    next()
end)

rack.run()

Sintaxe: rack.run()

Executa cada um dos middlewares na ordem, até que um escolha lidar com a resposta. Assim, a ordem em que você chama rack.use() é importante.

Middleware Embutido

method_override

rack.use(rack.middleware.method_override, { key = "METHOD" })

Substitui o método HTTP usando um valor de querystring. O nome do argumento padrão é "_method", mas isso pode ser substituído definindo a opção "key".

read_request_headers

rack.use(rack.middleware.read_request_headers, { max = 50 })

Isso é necessário apenas se você desejar iterar sobre os cabeçalhos da solicitação HTTP. Eles serão carregados de forma preguiçosa quando acessados via req.header.

Você pode especificar um limite para o número de cabeçalhos de solicitação a serem lidos, que por padrão é 100. O limite pode ser removido especificando um máximo de 0, mas é fortemente desencorajado.

read_body

rack.use(rack.middleware.read_body)

Lê explicitamente o corpo da solicitação (bruto).

Criando Middleware

Aplicações middleware são simplesmente módulos Lua que usam a solicitação e resposta HTTP como uma interface mínima. Elas devem implementar a função call(options) que retorna uma função. Os parâmetros (req, res, next) são definidos abaixo.

module("resty.rack.method_override", package.seeall)

_VERSION = '0.01'

function call(options)
    return function(req, res, next)
        local key = options['key'] or '_method'
        req.method = string.upper(req.args[key] or req.method)
        next()
    end
end

API

req.method

O método HTTP, e.g. GET, definido a partir de ngx.var.request_method.

req.scheme

O esquema do protocolo http|https, definido a partir de ngx.var.scheme.

req.uri

e.g. /my/uri, definido a partir de ngx.var.uri.

req.host

O nome do host, e.g. example.com, definido a partir de ngx.var.host.

req.query

A querystring, e.g. var1=1&var2=2, definida a partir de ngx.var.query_string.

req.args

Os argumentos da query, como uma table, definidos a partir de ngx.req.get_uri_args().

req.header

Uma tabela contendo os cabeçalhos da solicitação. As chaves são correspondidas de forma insensível a maiúsculas e minúsculas, e opcionalmente com sublinhados em vez de hífens. e.g.

req.header["X-Foo"] = "bar"
res.body = req.header.x_foo
    --> "bar"

Os cabeçalhos da solicitação HTTP são lidos sob demanda e, portanto, não podem ser iterados a menos que o middleware read_request_headers esteja em uso.

req.body

Uma string vazia até ser lida com o middleware read_body.

res.status

O código de status HTTP a ser retornado. Existem constantes definidas para status comuns.

res.header

Uma tabela de cabeçalhos de resposta, que podem ser correspondidos de forma insensível a maiúsculas e minúsculas e opcionalmente com sublinhados em vez de hífens (veja req.header acima).

res.body

O corpo da resposta.

next

Este parâmetro é uma função fornecida ao middleware, que pode ser chamada para indicar que o rack deve tentar o próximo middleware. Se sua aplicação não pretende enviar a resposta para o navegador, deve chamar esta função. Se, no entanto, sua aplicação está assumindo a responsabilidade pela resposta, basta retornar sem chamar next.

Exemplo apenas modificando a solicitação.

function call(options)
    return function(req, res, next)
        local key = options['key'] or '_method'
        req.method = string.upper(req.args[key] or req.method)
        next()
    end
end

Exemplo gerando uma resposta.

function call(options)
    return function(req, res)
        res.status = 200
        res.header['Content-Type'] = "text/plain"
        res.body = "Hello World"
    end
end

Melhorando req / res

Sua aplicação pode adicionar novos campos ou até mesmo funções às tabelas req / res onde apropriado, que podem ser usadas por outros middlewares, desde que as dependências estejam claras (e que um chame use() na ordem correta).

GitHub

Você pode encontrar dicas adicionais de configuração e documentação para este módulo no repositório GitHub para nginx-module-rack.