link: La aplicación de enlace dinámico con Nginx
Instalación
Puedes instalar este módulo en cualquier distribución basada en RHEL, incluyendo, entre otras:
- RedHat Enterprise Linux 7, 8, 9 y 10
- CentOS 7, 8, 9
- AlmaLinux 8, 9
- Rocky Linux 8, 9
- Amazon Linux 2 y Amazon Linux 2023
dnf -y install https://extras.getpagespeed.com/release-latest.rpm
dnf -y install nginx-module-link
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 nginx-module-link
Habilita el módulo añadiendo lo siguiente al inicio de /etc/nginx/nginx.conf:
load_module modules/ngx_http_link_func_module.so;
Este documento describe nginx-module-link v3.2.6 publicado el 12 de agosto de 2026.
Manejadores de funciones nativas de C/C++ para NGINX — carga bibliotecas compartidas y enruta las solicitudes directamente a código compilado, sin sobrecarga de IPC.
Descripción general
ngx_http_link_func conecta NGINX con aplicaciones nativas de C/C++ mediante enlace dinámico. Las bibliotecas compartidas (archivos .so) se cargan al iniciar el servidor, y las solicitudes HTTP se despachan directamente a funciones C exportadas que se ejecutan dentro del proceso worker de NGINX.
Esto significa que tu código C tiene acceso directo a las partes internas de NGINX — cabeceras de solicitud, argumentos de URI, cuerpo de la solicitud, memoria compartida — y puede escribir respuestas sin serialización, sockets ni cambios de contexto.
Características
- Despacho de funciones nativas — enruta cualquier location a una función C exportada
- Memoria compartida y caché — caché basada en rbtree entre workers con bloqueo por mutex
- Descarga a thread pool — soporte de hilos AIO para operaciones bloqueantes
- Integración con subrequest — encadena con
auth_requestpara flujos de autenticación - Carga remota de bibliotecas — obtén archivos
.sodesde URLs HTTP/HTTPS al iniciar - Hooks de ciclo de vida — callbacks de inicio y salida del ciclo para gestión de recursos
- Propiedades por servidor — pasa valores de configuración desde
nginx.confa tu código
Inicio rápido
nginx.conf:
http {
# Optional: shared memory for cross-worker cache
ngx_link_func_shm_size 1m;
server {
listen 8080;
# Load your compiled application
ngx_link_func_lib "/opt/myapp/libhandlers.so";
# Pass config values to your application
ngx_link_func_add_prop "db_host" "localhost:5432";
location /api/greeting {
ngx_link_func_call "handle_greeting";
}
location /api/users {
ngx_link_func_call "handle_users";
}
}
}
Tu aplicación (handlers.c):
#include <ngx_link_func_module.h>
void ngx_link_func_init_cycle(ngx_link_func_cycle_t *cycle) {
ngx_link_func_cyc_log(info, cycle, "%s", "Application started");
}
void handle_greeting(ngx_link_func_ctx_t *ctx) {
ngx_link_func_write_resp(
ctx, 200, "200 OK",
ngx_link_func_content_type_json,
"{\"message\":\"Hello from C\"}", 25
);
}
void handle_users(ngx_link_func_ctx_t *ctx) {
const char *token = ngx_link_func_get_query_param(ctx, "token");
if (!token) {
ngx_link_func_write_resp(
ctx, 401, "401 Unauthorized",
ngx_link_func_content_type_plaintext,
"Missing token", 13
);
return;
}
// Process authenticated request...
ngx_link_func_write_resp(
ctx, 200, "200 OK",
ngx_link_func_content_type_json,
"{\"users\":[]}", 12
);
}
void ngx_link_func_exit_cycle(ngx_link_func_cycle_t *cycle) {
ngx_link_func_cyc_log(info, cycle, "%s", "Application shutting down");
}
Compilar y desplegar:
gcc -shared -o libhandlers.so -fPIC handlers.c
sudo cp libhandlers.so /opt/myapp/
sudo nginx -s reload
Directivas
ngx_link_func_shm_size
Contexto: main | Valor predeterminado: ninguno
Establece el tamaño de la zona de memoria compartida para la caché entre workers y el uso compartido de datos.
ngx_link_func_shm_size 10m;
ngx_link_func_lib
Contexto: server | Valor predeterminado: ninguno
Carga una biblioteca compartida para el bloque server. Varios bloques server pueden cargar la misma biblioteca para compartir memoria.
ngx_link_func_lib "/opt/myapp/libhandlers.so";
ngx_link_func_call
Contexto: location | Valor predeterminado: ninguno
Enruta las solicitudes a una función C exportada por nombre.
location /api/data {
ngx_link_func_call "handle_data";
}
ngx_link_func_add_prop
Contexto: server | Valor predeterminado: ninguno
Pasa propiedades clave-valor a la aplicación, accesibles mediante ngx_link_func_get_prop().
ngx_link_func_add_prop "api_key" "secret123";
ngx_link_func_download_link_lib
Contexto: server | Valor predeterminado: ninguno
Descarga una biblioteca compartida desde una URL remota al iniciar. Admite cabeceras HTTP opcionales para autenticación.
## Basic download
ngx_link_func_download_link_lib "https://repo.example.com/libapp.so" "/opt/myapp/libapp.so";
## With authentication headers
ngx_link_func_download_link_lib "https://repo.example.com/libapp.so"
"Authorization:Bearer TOKEN\r\n"
"/opt/myapp/libapp.so";
ngx_link_func_ca_cert
Contexto: server | Valor predeterminado: ninguno
Establece el certificado CA para las descargas de bibliotecas por HTTPS.
ngx_link_func_ca_cert "/etc/ssl/certs/ca-certificates.crt";
ngx_link_func_add_req_header
Contexto: location | Valor predeterminado: ninguno
Añade una cabecera de solicitud, normalmente usada para pasar variables de NGINX a subrequests.
ngx_link_func_add_req_header "X-Real-IP" "$remote_addr";
ngx_link_func_subrequest
Contexto: location | Valor predeterminado: ninguno
Configura el enrutamiento de subrequests. Requiere NGINX compilado con --with-http_auth_request_module.
location /protected {
ngx_link_func_subrequest "/auth";
}
API de la aplicación
Incluye <ngx_link_func_module.h> en tu aplicación. La cabecera proporciona la API C completa.
Hooks de ciclo de vida
Estos nombres de función reservados son llamados automáticamente por NGINX:
void ngx_link_func_init_cycle(ngx_link_func_cycle_t *cycle); // On startup
void ngx_link_func_exit_cycle(ngx_link_func_cycle_t *cycle); // On shutdown/reload
Contexto de la solicitud
Cada manejador recibe ngx_link_func_ctx_t *ctx con:
| Campo | Tipo | Descripción |
|---|---|---|
req_args |
char * |
Cadena de consulta de URI sin procesar |
req_body |
u_char * |
Cuerpo de la solicitud |
req_body_len |
size_t |
Longitud del cuerpo de la solicitud |
shared_mem |
void * |
Puntero a memoria compartida |
Funciones
| Función | Descripción |
|---|---|
| Respuesta | |
ngx_link_func_write_resp(ctx, status, status_line, content_type, body, len) |
Escribe la respuesta HTTP |
ngx_link_func_write_resp_l(ctx, status, status_line, sl_len, ct, ct_len, body, len) |
Escribe la respuesta (longitudes explícitas) |
| Datos de la solicitud | |
ngx_link_func_get_uri(ctx, &str) |
Obtiene el URI de la solicitud |
ngx_link_func_get_remote_addr(ctx) |
Obtiene la dirección remota del cliente |
ngx_link_func_get_header(ctx, key, keylen) |
Obtiene la cabecera de solicitud por nombre |
ngx_link_func_get_query_param(ctx, key) |
Obtiene el parámetro de consulta por clave |
ngx_link_func_get_prop(ctx, key, keylen) |
Obtiene la propiedad del servidor |
| Cabeceras | |
ngx_link_func_add_header_in(ctx, key, klen, val, vlen) |
Añade cabecera de entrada |
ngx_link_func_add_header_out(ctx, key, klen, val, vlen) |
Añade cabecera de salida |
| Memoria | |
ngx_link_func_palloc(ctx, size) |
Asigna desde el pool de NGINX |
ngx_link_func_pcalloc(ctx, size) |
Asigna desde el pool de NGINX e inicializa a cero |
ngx_link_func_strdup(ctx, src) |
Duplica la cadena desde el pool |
| Memoria compartida | |
ngx_link_func_shm_alloc(shm, size) |
Asigna memoria compartida |
ngx_link_func_shm_free(shm, ptr) |
Libera memoria compartida |
ngx_link_func_shmtx_lock(shm) |
Adquiere el mutex |
ngx_link_func_shmtx_unlock(shm) |
Libera el mutex |
ngx_link_func_shmtx_trylock(shm) |
Intenta adquirir el mutex |
| Caché | |
ngx_link_func_cache_get(shm, key) |
Obtiene el valor en caché |
ngx_link_func_cache_put(shm, key, value) |
Almacena el valor en caché |
ngx_link_func_cache_new(shm, key, size) |
Asigna y almacena en caché |
ngx_link_func_cache_remove(shm, key) |
Elimina de la caché |
| Registro | |
ngx_link_func_log_debug/info/warn/err(ctx, msg) |
Registra un mensaje |
ngx_link_func_log(level, ctx, fmt, ...) |
Registra un mensaje formateado |
Constantes de tipo de contenido
ngx_link_func_content_type_plaintext // "text/plain"
ngx_link_func_content_type_html // "text/html; charset=utf-8"
ngx_link_func_content_type_json // "application/json"
ngx_link_func_content_type_jsonp // "application/javascript"
ngx_link_func_content_type_xformencoded // "application/x-www-form-urlencoded"
Linux
gcc -shared -o libmyapp.so -fPIC myapp.c
macOS
clang -dynamiclib -o libmyapp.dylib -fPIC myapp.c -Wl,-undefined,dynamic_lookup ```