requests: ¡Otra biblioteca HTTP para nginx-module-lua - Para seres humanos!
Instalación
Si no has configurado la suscripción al repositorio RPM, regístrate. Luego puedes proceder con los siguientes pasos.
CentOS/RHEL 7 o 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-requests
CentOS/RHEL 8+, Fedora Linux, Amazon Linux 2023
dnf -y install https://extras.getpagespeed.com/release-latest.rpm
dnf -y install lua5.1-resty-requests
Para usar esta biblioteca Lua con NGINX, asegúrate de que nginx-module-lua esté instalado.
Este documento describe lua-resty-requests v0.7.3 lanzado el 18 de julio de 2019.
- HTTP/1.0, HTTP/1.1 y HTTP/2 (WIP).
- Soporte para SSL/TLS.
- Soporte para datos en fragmentos.
- Interfaces convenientes para soportar características como json, autorización, etc.
- Interfaces de flujo para leer el cuerpo.
- Proxy HTTP/HTTPS.
- Métricas de latencia.
- Soporte para sesiones.
Sinopsis
local requests = require "resty.requests"
-- ejemplo de url
local url = "http://example.com/index.html"
local r, err = requests.get(url)
if not r then
ngx.log(ngx.ERR, err)
return
end
-- leer todo el cuerpo
local body = r:body()
ngx.print(body)
-- o puedes iterar el cuerpo de la respuesta
-- while true do
-- local chunk, err = r:iter_content(4096)
-- if not chunk then
-- ngx.log(ngx.ERR, err)
-- return
-- end
--
-- if chunk == "" then
-- break
-- end
--
-- ngx.print(chunk)
-- end
-- también puedes usar el modo no-stream
-- local opts = {
-- stream = false
-- }
--
-- local r, err = requests.get(url, opts)
-- if not r then
-- ngx.log(ngx.ERR, err)
-- end
--
-- ngx.print(r.content)
-- o puedes usar la forma abreviada para hacer el código más limpio.
local r, err = requests.get { url = url, stream = false }
Métodos
request
sintaxis: local r, err = requests.request(method, url, opts?)
sintaxis: local r, err = requests.request { method = method, url = url, ... }
Este es el método fundamental en lua-resty-requests, devolverá un objeto de respuesta r. En caso de fallo, se devolverá nil y una cadena de Lua que describe el error correspondiente.
El primer parámetro method es el método HTTP que deseas usar (igual que la semántica de HTTP), que toma una cadena de Lua y el valor puede ser:
GETHEADPOSTPUTDELETEOPTIONSPATCH
El segundo parámetro url toma el significado literal (es decir, Ubicación de Recurso Uniforme), por ejemplo, http://foo.com/blah?a=b, puedes omitir el prefijo del esquema y como esquema predeterminado, se seleccionará http.
El tercer parámetro, una tabla de Lua opcional, que contiene una serie de opciones:
-
headerscontiene los encabezados de solicitud personalizados. -
allow_redirectsespecifica si se debe redirigir a la URL objetivo (especificada por el encabezadoLocation) o no cuando el código de estado es301,302,303,307o308. -
redirect_max_timesespecifica los límites de redirección, el valor predeterminado es10. -
body, el cuerpo de la solicitud, puede ser:- una cadena de Lua, o
- una función de Lua, sin parámetros y que devuelve un fragmento de datos (cadena) o una cadena de Lua vacía para representar EOF, o
- una tabla de Lua, cada par clave-valor se concatenará con el "&", y el encabezado Content-Type será
"application/x-www-form-urlencoded"
-
error_filter, contiene una función de Lua que toma dos parámetros,stateyerr. el parámetroerrdescribe el error ystatees siempre uno de estos valores (representa la etapa actual):requests.CONNECTrequests.HANDSHAKErequests.SEND_HEADERrequests.SEND_BODYrequests.RECV_HEADERrequests.RECV_BODYrequests.CLOSE
Puedes usar el método requests.state para obtener el significado textual de estos valores.
-
timeouts, una tabla similar a un array,timeouts[1],timeouts[2]ytimeouts[3]representantimeout de conexión,timeout de envíoytimeout de lecturarespectivamente (en milisegundos). -
http10especifica si se debe usarHTTP/1.0, la versión predeterminada esHTTP/1.1. http20especifica si se debe usarHTTP/2, la versión predeterminada esHTTP/1.1.
Ten en cuenta que esto aún es inestable, se debe tener precaución. Además, hay algunas limitaciones, consulta lua-resty-http2 para más detalles.
sslcontiene una tabla de Lua, con tres campos:verify, controla si se debe realizar la verificación SSL-
server_name, se utiliza para especificar el nombre del servidor para la nueva extensión TLS Server Name Indication (SNI) -
proxiesespecifica servidores proxy, la forma es como
{
http = { host = "127.0.0.1", port = 80 },
https = { host = "192.168.1.3", port = 443 },
}
Al usar un proxy HTTPS, se enviará una solicitud CONNECT previa al servidor proxy.
hooks, también una tabla de Lua, representa el sistema de hooks que puedes usar para manipular partes del proceso de solicitud. Los hooks disponibles son:response, se activará inmediatamente después de recibir los encabezados de respuesta
puedes asignar funciones de Lua a los hooks, estas funciones aceptan el objeto de respuesta como el único parámetro.
local hooks = {
response = function(r)
ngx.log(ngx.WARN, "durante el proceso de solicitudes")
end
}
Considerando la conveniencia, también hay algunas opciones de "camino corto":
auth, para realizar la Autorización HTTP Básica, toma una tabla de Lua que contieneuserypass, por ejemplo, cuandoauthes:
{
user = "alex",
pass = "123456"
}
Se añadirá el encabezado de solicitud Authorization, y el valor será Basic YWxleDoxMjM0NTY=.
-
json, toma una tabla de Lua, se serializará mediantecjson, los datos serializados se enviarán como el cuerpo de la solicitud, y tiene prioridad cuando se especifican tantojsoncomobody. -
cookie, toma una tabla de Lua, los pares clave-valor se organizarán de acuerdo con la regla del encabezadoCookie, por ejemplo,cookiees:
{
["PHPSESSID"] = "298zf09hf012fh2",
["csrftoken"] = "u32t4o3tb3gg43"
}
El encabezado Cookie será PHPSESSID=298zf09hf012fh2; csrftoken=u32t4o3tb3gg43.
stream, toma un valor booleano, especifica si se debe leer el cuerpo en modo de flujo, y será verdadero por defecto.
state
sintaxis: local state_name = requests.state(state)
El método se utiliza para obtener el significado textual de estos valores:
requests.CONNECTrequests.HANDSHAKErequests.SEND_HEADERrequests.SEND_BODYrequests.RECV_HEADERrequests.RECV_BODYrequests.CLOSE
se devolverá una cadena de Lua "unknown" si state no es uno de los valores anteriores.
get
sintaxis: local r, err = requests.get(url, opts?)
sintaxis: local r, err = requests.get { url = url, ... }
Envía una solicitud HTTP GET. Esto es idéntico a
requests.request("GET", url, opts)
head
sintaxis: local r, err = requests.head(url, opts?)
sintaxis: local r, err = requests.head { url = url, ... }
Envía una solicitud HTTP HEAD. Esto es idéntico a
requests.request("HEAD", url, opts)
post
sintaxis: local r, err = requests.post(url, opts?)
sintaxis: local r, err = requests.post { url = url, ... }
Envía una solicitud HTTP POST. Esto es idéntico a
requests.request("POST", url, opts)
put
sintaxis: local r, err = requests.put(url, opts?)
sintaxis: local r, err = requests.put { url = url, ... }
Envía una solicitud HTTP PUT. Esto es idéntico a
requests.request("PUT", url, opts)
delete
sintaxis: local r, err = requests.delete(url, opts?)
sintaxis: local r, err = requests.delete { url = url, ... }
Envía una solicitud HTTP DELETE. Esto es idéntico a
requests.request("DELETE", url, opts)
options
sintaxis: local r, err = requests.options(url, opts?)
sintaxis: local r, err = requests.options { url = url, ... }
Envía una solicitud HTTP OPTIONS. Esto es idéntico a
requests.request("OPTIONS", url, opts)
patch
sintaxis: local r, err = requests.patch(url, opts?)
sintaxis: local r, err = requests.patch { url = url, ... }
Envía una solicitud HTTP PATCH. Esto es idéntico a
requests.request("PATCH", url, opts)
Objeto de Respuesta
Métodos como requests.get y otros devolverán un objeto de respuesta r, que puede ser manipulado por los siguientes métodos y variables:
url, la url pasada desde el llamadormethod, el método de solicitud, por ejemplo,POSTstatus_line, la línea de estado en bruto (recibida del remoto)status_code, el código de estado HTTPhttp_version, la versión HTTP de la respuesta, por ejemplo,HTTP/1.1headers, una tabla de Lua que representa los encabezados de respuesta HTTP (insensible a mayúsculas)close, contiene una función de Lua, utilizada para cerrar (mantener viva) la conexión TCP subyacentedrop, es una función de Lua, utilizada para descartar el cuerpo de respuesta HTTP no leído, se invocará automáticamente al cerrar (si queda algún dato no leído)iter_content, que también es una función de Lua, emite una parte del cuerpo de respuesta (decodificada del formato en fragmentos) cada vez que se llama.
Esta función acepta un parámetro opcional size para especificar el tamaño del cuerpo que el llamador desea, cuando está ausente, iter_content devuelve 8192 bytes cuando el cuerpo de respuesta es plano o devuelve un fragmento de datos en fragmentos si el cuerpo de respuesta está en fragmentos.
En caso de fallo, se devolverá nil y una cadena de Lua que describe el error.
body, también contiene una función de Lua que devuelve todo el cuerpo de respuesta.
En caso de fallo, se devolverá nil y una cadena de Lua que describe el error.
-
json, contiene una función de Lua, serializa el cuerpo a una tabla de Lua, ten en cuenta que elContent-Typedebe serapplication/json. En caso de fallo, se devolveránily una cadena de error. -
content, el cuerpo de respuesta, solo válido en el modo no-stream. -
elapsed, una tabla de Lua similar a un hash que representa el tiempo de costo (en segundos) para cada etapa. elapsed.connect, tiempo de costo para el apretón de manos TCP de 3 vías;elapsed.handshake, tiempo de costo para el apretón de manos SSL/TLS (si lo hay);elapsed.send_header, tiempo de costo para enviar los encabezados de solicitud HTTP;elapsed.send_body, tiempo de costo para enviar el cuerpo de la solicitud HTTP (si lo hay);elapsed.read_header, tiempo de costo para recibir los encabezados de respuesta HTTP;elapsed.ttfb, el tiempo hasta el primer byte.
Nota: Cuando se aplica el protocolo HTTP/2, el elapsed.send_body (si lo hay) será el mismo que elapsed.send_header.
Sesión
Una sesión persiste algunos datos a través de múltiples solicitudes, como datos de cookies, datos de autorización, etc.
Este mecanismo aún es experimental.
Un ejemplo simple:
s = requests.session()
local r, err = s:get("https://www.example.com")
ngx.say(r:body())
Un objeto de sesión tiene las mismas interfaces que requests, es decir, esos métodos http.
Ver También
- upyun-resty: https://github.com/upyun/upyun-resty
- httpipe: https://github.com/timebug/lua-resty-httpipe
GitHub
Puedes encontrar consejos de configuración adicionales y documentación para este módulo en el repositorio de GitHub para nginx-module-requests.