Saltar a contenido

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_request para flujos de autenticación
  • Carga remota de bibliotecas — obtén archivos .so desde 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.conf a 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

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;

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";

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";
}

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";

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";

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";

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";

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 ```