Aller au contenu

link : Liaison dynamique d'applications avec Nginx

Installation

Vous pouvez installer ce module sur n'importe quelle distribution basée sur RHEL, incluant, sans s'y limiter :

  • RedHat Enterprise Linux 7, 8, 9 et 10
  • CentOS 7, 8, 9
  • AlmaLinux 8, 9
  • Rocky Linux 8, 9
  • Amazon Linux 2 et 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

Activez le module en ajoutant ce qui suit au début de /etc/nginx/nginx.conf :

load_module modules/ngx_http_link_func_module.so;

Ce document décrit nginx-module-link v3.2.6 publié le 12 août 2026.


Gestionnaires de fonctions C/C++ natifs pour NGINX — chargez des bibliothèques partagées et acheminez les requêtes directement vers du code compilé, sans surcoût d'IPC.

Aperçu

ngx_http_link_func fait le pont entre NGINX et les applications natives C/C++ via la liaison dynamique. Les bibliothèques partagées (fichiers .so) sont chargées au démarrage du serveur, et les requêtes HTTP sont distribuées directement aux fonctions C exportées s'exécutant à l'intérieur du processus worker NGINX.

Cela signifie que votre code C a un accès direct aux internes de NGINX — en-têtes de requête, arguments d'URI, corps de requête, mémoire partagée — et peut écrire des réponses sans sérialisation, sockets ni changements de contexte.

Fonctionnalités

  • Distribution de fonctions natives — acheminez n'importe quel location vers une fonction C exportée
  • Mémoire partagée et cache — cache inter-workers basé sur un rbtree avec verrouillage par mutex
  • Déport vers un pool de threads — prise en charge des threads AIO pour les opérations bloquantes
  • Intégration de sous-requêtes — chaînez avec auth_request pour les flux d'authentification
  • Chargement de bibliothèques distantes — récupérez des fichiers .so depuis des URL HTTP/HTTPS au démarrage
  • Hooks de cycle de vie — callbacks d'initialisation et de sortie de cycle pour la gestion des ressources
  • Propriétés par serveur — transmettez des valeurs de configuration depuis nginx.conf à votre code

Démarrage rapide

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

Votre application (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");
}

Compiler et déployer :

gcc -shared -o libhandlers.so -fPIC handlers.c
sudo cp libhandlers.so /opt/myapp/
sudo nginx -s reload

Directives

Contexte : main | Défaut : aucun

Définit la taille de la zone de mémoire partagée pour le cache inter-workers et le partage de données.

ngx_link_func_shm_size 10m;

Contexte : server | Défaut : aucun

Charge une bibliothèque partagée pour le bloc server. Plusieurs blocs server peuvent charger la même bibliothèque pour partager la mémoire.

ngx_link_func_lib "/opt/myapp/libhandlers.so";

Contexte : location | Défaut : aucun

Achemine les requêtes vers une fonction C exportée par son nom.

location /api/data {
    ngx_link_func_call "handle_data";
}

Contexte : server | Défaut : aucun

Transmet des propriétés clé-valeur à l'application, accessibles via ngx_link_func_get_prop().

ngx_link_func_add_prop "api_key" "secret123";

Contexte : server | Défaut : aucun

Télécharge une bibliothèque partagée depuis une URL distante au démarrage. Prend en charge des en-têtes HTTP optionnels pour l'authentification.

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

Contexte : server | Défaut : aucun

Définit le certificat CA pour les téléchargements de bibliothèques via HTTPS.

ngx_link_func_ca_cert "/etc/ssl/certs/ca-certificates.crt";

Contexte : location | Défaut : aucun

Ajoute un en-tête de requête, généralement utilisé pour transmettre des variables NGINX aux sous-requêtes.

ngx_link_func_add_req_header "X-Real-IP" "$remote_addr";

Contexte : location | Défaut : aucun

Configure le routage des sous-requêtes. Nécessite que NGINX soit compilé avec --with-http_auth_request_module.

location /protected {
    ngx_link_func_subrequest "/auth";
}

API de l'application

Incluez <ngx_link_func_module.h> dans votre application. Cet en-tête fournit l'API C complète.

Hooks de cycle de vie

Ces noms de fonctions réservés sont appelés automatiquement par 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

Contexte de requête

Chaque gestionnaire reçoit ngx_link_func_ctx_t *ctx avec :

Champ Type Description
req_args char * Chaîne de requête brute de l'URI
req_body u_char * Corps de la requête
req_body_len size_t Longueur du corps de la requête
shared_mem void * Pointeur vers la mémoire partagée

Fonctions

Fonction Description
Réponse
ngx_link_func_write_resp(ctx, status, status_line, content_type, body, len) Écrire une réponse HTTP
ngx_link_func_write_resp_l(ctx, status, status_line, sl_len, ct, ct_len, body, len) Écrire une réponse (longueurs explicites)
Données de requête
ngx_link_func_get_uri(ctx, &str) Obtenir l'URI de la requête
ngx_link_func_get_remote_addr(ctx) Obtenir l'adresse distante du client
ngx_link_func_get_header(ctx, key, keylen) Obtenir un en-tête de requête par nom
ngx_link_func_get_query_param(ctx, key) Obtenir un paramètre de requête par clé
ngx_link_func_get_prop(ctx, key, keylen) Obtenir une propriété du serveur
En-têtes
ngx_link_func_add_header_in(ctx, key, klen, val, vlen) Ajouter un en-tête d'entrée
ngx_link_func_add_header_out(ctx, key, klen, val, vlen) Ajouter un en-tête de sortie
Mémoire
ngx_link_func_palloc(ctx, size) Allouer depuis le pool NGINX
ngx_link_func_pcalloc(ctx, size) Allouer et initialiser à zéro depuis le pool NGINX
ngx_link_func_strdup(ctx, src) Dupliquer une chaîne depuis le pool
Mémoire partagée
ngx_link_func_shm_alloc(shm, size) Allouer de la mémoire partagée
ngx_link_func_shm_free(shm, ptr) Libérer de la mémoire partagée
ngx_link_func_shmtx_lock(shm) Acquérir le mutex
ngx_link_func_shmtx_unlock(shm) Libérer le mutex
ngx_link_func_shmtx_trylock(shm) Tenter d'acquérir le mutex
Cache
ngx_link_func_cache_get(shm, key) Obtenir une valeur en cache
ngx_link_func_cache_put(shm, key, value) Stocker une valeur en cache
ngx_link_func_cache_new(shm, key, size) Allouer et mettre en cache
ngx_link_func_cache_remove(shm, key) Retirer du cache
Journalisation
ngx_link_func_log_debug/info/warn/err(ctx, msg) Journaliser un message
ngx_link_func_log(level, ctx, fmt, ...) Journaliser un message formaté

Constantes de type de contenu

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