Перейти к содержанию

link: Динамическое связывание приложения с Nginx

Установка

Вы можете установить этот модуль в любом дистрибутиве на базе RHEL, включая, но не ограничиваясь:

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

Включите модуль, добавив следующее в начало /etc/nginx/nginx.conf:

load_module modules/ngx_http_link_func_module.so;

В этом документе описывается nginx-module-link v3.2.6 выпущенный 12 августа 2026 г.


Обработчики нативных функций C/C++ для NGINX — загружайте разделяемые библиотеки и направляйте запросы напрямую в скомпилированный код без накладных расходов на IPC.

Обзор

ngx_http_link_func связывает NGINX и нативные приложения на C/C++ через динамическое связывание. Разделяемые библиотеки (файлы .so) загружаются при запуске сервера, а HTTP-запросы направляются напрямую в экспортированные C-функции, выполняющиеся внутри рабочего процесса NGINX.

Это означает, что ваш C-код имеет прямой доступ к внутренним механизмам NGINX — заголовкам запроса, аргументам URI, телу запроса, разделяемой памяти — и может формировать ответы без сериализации, сокетов или переключений контекста.

Возможности

  • Нативная диспетчеризация функций — направление любого location в экспортированную C-функцию
  • Разделяемая память и кэш — кэш на основе rbtree между рабочими процессами с блокировкой мьютексом
  • Выгрузка в пул потоков — поддержка потоков AIO для блокирующих операций
  • Интеграция с подзапросами — объединение с auth_request для сценариев аутентификации
  • Удалённая загрузка библиотек — получение файлов .so по HTTP/HTTPS URL при запуске
  • Хуки жизненного цикла — обратные вызовы инициализации и завершения цикла для управления ресурсами
  • Свойства на уровне сервера — передача значений конфигурации из nginx.conf в ваш код

Быстрый старт

nginx.conf:

http {
    # Опционально: разделяемая память для кэша между рабочими процессами
    ngx_link_func_shm_size 1m;

    server {
        listen 8080;

        # Загрузите ваше скомпилированное приложение
        ngx_link_func_lib "/opt/myapp/libhandlers.so";

        # Передайте значения конфигурации в ваше приложение
        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";
        }
    }
}

Ваше приложение (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;
    }

    // Обработка аутентифицированного запроса...
    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");
}

Сборка и развёртывание:

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

Директивы

Контекст: main | По умолчанию: нет

Задаёт размер зоны разделяемой памяти для кэша между рабочими процессами и обмена данными.

ngx_link_func_shm_size 10m;

Контекст: server | По умолчанию: нет

Загружает разделяемую библиотеку для блока server. Несколько блоков server могут загружать одну и ту же библиотеку для совместного использования памяти.

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

Контекст: location | По умолчанию: нет

Направляет запросы в экспортированную C-функцию по имени.

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

Контекст: server | По умолчанию: нет

Передаёт приложению свойства в виде пар ключ-значение, доступные через ngx_link_func_get_prop().

ngx_link_func_add_prop "api_key" "secret123";

Контекст: server | По умолчанию: нет

Загружает разделяемую библиотеку с удалённого URL при запуске. Поддерживает опциональные HTTP-заголовки для аутентификации.

## Базовая загрузка
ngx_link_func_download_link_lib "https://repo.example.com/libapp.so" "/opt/myapp/libapp.so";

## С заголовками аутентификации
ngx_link_func_download_link_lib "https://repo.example.com/libapp.so"
    "Authorization:Bearer TOKEN\r\n"
    "/opt/myapp/libapp.so";

Контекст: server | По умолчанию: нет

Задаёт сертификат CA для загрузки библиотек по HTTPS.

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

Контекст: location | По умолчанию: нет

Добавляет заголовок запроса, обычно используется для передачи переменных NGINX в подзапросы.

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

Контекст: location | По умолчанию: нет

Настраивает маршрутизацию подзапросов. Требует NGINX, скомпилированный с --with-http_auth_request_module.

location /protected {
    ngx_link_func_subrequest "/auth";
}

API приложения

Включите <ngx_link_func_module.h> в ваше приложение. Заголовочный файл предоставляет полный C API.

Хуки жизненного цикла

Эти зарезервированные имена функций вызываются автоматически NGINX:

void ngx_link_func_init_cycle(ngx_link_func_cycle_t *cycle);  // При запуске
void ngx_link_func_exit_cycle(ngx_link_func_cycle_t *cycle);  // При завершении/перезагрузке

Контекст запроса

Каждый обработчик получает ngx_link_func_ctx_t *ctx со следующими полями:

Поле Тип Описание
req_args char * Необработанная строка запроса URI
req_body u_char * Тело запроса
req_body_len size_t Длина тела запроса
shared_mem void * Указатель на разделяемую память

Функции

Функция Описание
Ответ
ngx_link_func_write_resp(ctx, status, status_line, content_type, body, len) Записать HTTP-ответ
ngx_link_func_write_resp_l(ctx, status, status_line, sl_len, ct, ct_len, body, len) Записать ответ (явные длины)
Данные запроса
ngx_link_func_get_uri(ctx, &str) Получить URI запроса
ngx_link_func_get_remote_addr(ctx) Получить удалённый адрес клиента
ngx_link_func_get_header(ctx, key, keylen) Получить заголовок запроса по имени
ngx_link_func_get_query_param(ctx, key) Получить параметр запроса по ключу
ngx_link_func_get_prop(ctx, key, keylen) Получить свойство сервера
Заголовки
ngx_link_func_add_header_in(ctx, key, klen, val, vlen) Добавить входной заголовок
ngx_link_func_add_header_out(ctx, key, klen, val, vlen) Добавить выходной заголовок
Память
ngx_link_func_palloc(ctx, size) Выделить из пула NGINX
ngx_link_func_pcalloc(ctx, size) Выделить обнулённую память из пула NGINX
ngx_link_func_strdup(ctx, src) Дублировать строку из пула
Разделяемая память
ngx_link_func_shm_alloc(shm, size) Выделить разделяемую память
ngx_link_func_shm_free(shm, ptr) Освободить разделяемую память
ngx_link_func_shmtx_lock(shm) Захватить мьютекс
ngx_link_func_shmtx_unlock(shm) Освободить мьютекс
ngx_link_func_shmtx_trylock(shm) Попытаться захватить мьютекс
Кэш
ngx_link_func_cache_get(shm, key) Получить кэшированное значение
ngx_link_func_cache_put(shm, key, value) Сохранить кэшированное значение
ngx_link_func_cache_new(shm, key, size) Выделить и закэшировать
ngx_link_func_cache_remove(shm, key) Удалить из кэша
Логирование
ngx_link_func_log_debug/info/warn/err(ctx, msg) Записать сообщение в лог
ngx_link_func_log(level, ctx, fmt, ...) Записать форматированное сообщение в лог

Константы типов содержимого

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