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
Директивы
ngx_link_func_shm_size
Контекст: main | По умолчанию: нет
Задаёт размер зоны разделяемой памяти для кэша между рабочими процессами и обмена данными.
ngx_link_func_shm_size 10m;
ngx_link_func_lib
Контекст: server | По умолчанию: нет
Загружает разделяемую библиотеку для блока server. Несколько блоков server могут загружать одну и ту же библиотеку для совместного использования памяти.
ngx_link_func_lib "/opt/myapp/libhandlers.so";
ngx_link_func_call
Контекст: location | По умолчанию: нет
Направляет запросы в экспортированную C-функцию по имени.
location /api/data {
ngx_link_func_call "handle_data";
}
ngx_link_func_add_prop
Контекст: server | По умолчанию: нет
Передаёт приложению свойства в виде пар ключ-значение, доступные через ngx_link_func_get_prop().
ngx_link_func_add_prop "api_key" "secret123";
ngx_link_func_download_link_lib
Контекст: 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";
ngx_link_func_ca_cert
Контекст: server | По умолчанию: нет
Задаёт сертификат CA для загрузки библиотек по HTTPS.
ngx_link_func_ca_cert "/etc/ssl/certs/ca-certificates.crt";
ngx_link_func_add_req_header
Контекст: location | По умолчанию: нет
Добавляет заголовок запроса, обычно используется для передачи переменных NGINX в подзапросы.
ngx_link_func_add_req_header "X-Real-IP" "$remote_addr";
ngx_link_func_subrequest
Контекст: 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 ```