ссылка: Динамическая линковка приложения с Nginx
Установка на Debian/Ubuntu
Эти документы применимы к APT пакету nginx-module-link, предоставленному репозиторием GetPageSpeed Extras.
- Настройте APT репозиторий, как описано в настройке APT репозитория.
- Установите модуль:
sudo apt-get update
sudo apt-get install nginx-module-link
Warning
Этот модуль еще не опубликован как nginx-module-link в APT репозиториях. Следите за новостями или напишите на [email protected], чтобы запросить его.

nginx-link-function
Динамическая линковка приложения с Nginx
Введение
nginx-link-function — это модуль nginx, который предоставляет динамическую линковку к вашему приложению в контексте сервера и вызывает функцию вашего приложения в директиве location. Вы можете напрямую связать ваше приложение C/C++ (или любое другое, которое поддерживает динамическую линковку) с сервером nginx.
Как это работает

Использование
## nginx.conf
server {
listen 8888;
...
ngx_link_func_lib "/path/to/your/libcfuntest.so";
...
...
location = /testCFunGreeting {
ngx_link_func_call "my_app_simple_get_greeting";
}
}
server {
listen 8989;
aio threads;
...
ngx_link_func_lib "/path/to/your/libcfuntest.so"; # делит память данных с сервером 1, если путь такой же как у сервера 1
...
...
location = /testCFunGreeting {
ngx_link_func_call "my_app_simple_get_greeting"
}
}
server {
listen 8999;
aio threads;
...
ngx_link_func_lib "/path/to/your/libcfuntest2.so"; # другое приложение
...
...
location = /testPost {
add_header Allow "GET, POST, HEAD" always;
if ( $request_method !~ ^(POST)$ ) {
return 405;
}
ngx_link_func_call "my_2nd_app_simple_get_token";
}
}
server {
listen 9888;
aio threads;
...
## Скачивание приложения из облачного репозитория, например, ngx_link_func_download_link_lib <download_link> <dest_link_file>
ngx_link_func_download_link_lib "http://abc.com/repos/libcfuntest.so" "/etc/nginx/libcfuntest3.so"
...
...
location = /testPost {
add_header Allow "GET, POST, HEAD" always;
if ( $request_method !~ ^(POST)$ ) {
return 405;
}
ngx_link_func_call "my_3rd_app_simple_get_token";
}
}
server {
listen 9898;
aio threads;
...
## Скачивание приложения из облачного репозитория с дополнительным заголовком, например, ngx_link_func_download_link_lib <download_link> <headers> <dest_link_file>
ngx_link_func_download_link_lib "https://abc.com/repos/libcfuntest.so" "Accept-Language:en_US\r\nAuthorization:Bearer KA.eyJ2ZXJzaadlasdlaldhjHJ2h3ldjklsjaklcjkljasdklcmasaskdaJxdkL3ftjM\r\n" "/etc/nginx/libcfuntest4.so"
...
...
location = /testPost {
add_header Allow "GET, POST, HEAD" always;
if ( $request_method !~ ^(POST)$ ) {
return 405;
}
ngx_link_func_call "my_other_app_simple_get_token";
}
}
Интерфейс для клиентского приложения
Это интерфейс, который вы можете использовать для получения дополнительных деталей от сервера nginx, он находится внутри ngx_link_func_module.h.
#define ngx_link_func_content_type_plaintext "text/plain"
#define ngx_link_func_content_type_html "text/html; charset=utf-8"
#define ngx_link_func_content_type_json "application/json"
#define ngx_link_func_content_type_jsonp "application/javascript"
#define ngx_link_func_content_type_xformencoded "application/x-www-form-urlencoded"
typedef struct {
char *req_args; // Uri Args
u_char *req_body; // Request Body
size_t req_body_len; // длина тела
void *shared_mem;
/* внутренние */
void* __r__;
void* __pl__;
void* __log__;
} ngx_link_func_ctx_t;
extern void ngx_link_func_log_debug(ngx_link_func_ctx_t *ctx, const char* msg);
extern void ngx_link_func_log_info(ngx_link_func_ctx_t *ctx, const char* msg);
extern void ngx_link_func_log_warn(ngx_link_func_ctx_t *ctx, const char* msg);
extern void ngx_link_func_log_err(ngx_link_func_ctx_t *ctx, const char* msg);
extern u_char* ngx_link_func_get_header(ngx_link_func_ctx_t *ctx, const char*key);
extern void* ngx_link_func_get_query_param(ngx_link_func_ctx_t *ctx, const char *key);
extern void* ngx_link_func_palloc(ngx_link_func_ctx_t *ctx, size_t size);
extern void* ngx_link_func_pcalloc(ngx_link_func_ctx_t *ctx, size_t size);
extern void ngx_link_func_write_resp(
ngx_link_func_ctx_t *ctx,
uintptr_t status_code,
const char* status_line,
const char* content_type,
const char* resp_content,
size_t resp_len
);
// Область общей памяти и кеша
extern void ngx_link_func_shmtx_lock(void *shared_mem);
extern void ngx_link_func_shmtx_unlock(void *shared_mem);
extern void* ngx_link_func_shm_alloc(void *shared_mem, size_t size);
extern void ngx_link_func_shm_free(void *shared_mem, void *ptr);
extern void* ngx_link_func_cache_get(void *shared_mem, const char* key);
extern void* ngx_link_func_cache_put(void *shared_mem, const char* key, void* value);
extern void* ngx_link_func_cache_new(void *shared_mem, const char* key, size_t size);
extern void ngx_link_func_cache_remove(void *shared_mem, const char* key);
Подробности интерфейса
malloc/calloc из пула nginx
void* ngx_link_func_palloc(ngx_link_func_ctx_t *ctx, size_t size);
void* ngx_link_func_pcalloc(ngx_link_func_ctx_t *ctx, size_t size);
получение параметра заголовка запроса
extern u_char* ngx_link_func_get_header(ngx_link_func_ctx_t *ctx, const char*key);
получение аргументов uri
ctx->req_args;
получение параметра запроса
extern void* ngx_link_func_get_query_param(ngx_link_func_ctx_t *ctx, const char *key);
получение тела запроса
ctx->req_body;
получение длины тела запроса
ctx->req_body_len;
логирование на сервере nginx
extern void ngx_link_func_log_debug(ngx_link_func_ctx_t *ctx, const char* msg);
extern void ngx_link_func_log_info(ngx_link_func_ctx_t *ctx, const char* msg);
extern void ngx_link_func_log_warn(ngx_link_func_ctx_t *ctx, const char* msg);
extern void ngx_link_func_log_err(ngx_link_func_ctx_t *ctx, const char* msg);
Ответ
extern void ngx_link_func_write_resp(
ngx_link_func_ctx_t *ctx,
uintptr_t status_code, // Код состояния
const char* status_line, // Строка состояния
const char* content_type, // Тип контента ответа
const char* resp_content, // Содержимое ответа
size_t resp_len // Длина содержимого ответа
);
Разработка примерного приложения
Не стесняйтесь клонировать пример проекта на
руководство для линковки функции google linkfunc-jwt-auth
#include <stdio.h>
#include <ngx_link_func_module.h>
/*** Соберите программу как .so библиотеку и скопируйте в предпочитаемое место, чтобы nginx связал эту библиотеку ***/
/*** gcc -shared -o libcfuntest.so -fPIC cfuntest.c ***/
/*** cp libcfuntest.so /etc/nginx/ ***/
int is_service_on = 0;
void ngx_link_func_init_cycle(ngx_link_func_cycle_t* cycle) {
ngx_link_func_cyc_log(info, cycle, "%s", "начало приложения");
is_service_on = 1;
}
void my_app_simple_get_greeting(ngx_link_func_ctx_t *ctx) {
ngx_link_func_log_info(ctx, "Обратный вызов и логирование из my_app_simple_get");
ngx_link_func_write_resp(
ctx,
200,
"200 OK",
"text/plain",
"приветствие от тестирования ngx_link_func",
sizeof("приветствие от тестирования ngx_link_func")-1
);
}
void my_app_simple_get_args(ngx_link_func_ctx_t *ctx) {
ngx_link_func_log_info(ctx, "Обратный вызов и логирование из my_app_simple_get_args");
if(ctx->req_args) {
ngx_link_func_write_resp(
ctx,
200,
"200 OK",
"text/plain",
ctx->req_args,
strlen(ctx->req_args)
);
} else {
ngx_link_func_write_resp(
ctx,
204,
"",
"text/plain",
NULL,
0
);
}
}
void my_app_simple_get_token_args(ngx_link_func_ctx_t *ctx) {
ngx_link_func_log_info(ctx, "Обратный вызов и логирование из my_app_simple_get_token_args");
char * tokenArgs = (char*)ngx_link_func_get_query_param(ctx, "token");
if (! tokenArgs) {
ngx_link_func_write_resp(
ctx,
401,
"401 неавторизован",
"text/plain",
"Токен не найден",
sizeof("Токен не найден")-1
);
} else {
ngx_link_func_write_resp(
ctx,
401,
"401 неавторизован",
"text/plain",
tokenArgs,
strlen(tokenArgs)
);
}
}
void my_app_simple_post(ngx_link_func_ctx_t *ctx) {
ngx_link_func_log_info(ctx, "Обратный вызов и логирование из my_app_simple_post");
ngx_link_func_write_resp(
ctx,
202,
"202 Принято и обрабатывается",
"text/plain",
NULL,
0
);
}
void my_app_simple_get_no_resp(ngx_link_func_ctx_t *ctx) {
ngx_link_func_log_info(ctx, "Обратный вызов и логирование из my_app_simple_get_no_resp");
// возврат 404
}
void ngx_link_func_exit_cycle(ngx_link_func_cycle_t* cyc) {
ngx_link_func_cyc_log(info, cyc, "%s\n", "Завершение/перезагрузка приложения");
is_service_on = 0;
}
Примечание:
Функции инициализации и завершения цикла резервируются, когда nginx запускается, он вызовет функцию инициализации, когда остановится/перезагрузится nginx, он вызовет функцию завершения цикла.
void ngx_link_func_init_cycle(ngx_link_func_cycle_t* cyc){}
void ngx_link_func_exit_cycle(ngx_link_func_cycle_t* cyc){}
Уровень логирования
Логи могут быть вызваны, записанное сообщение будет храниться в том месте, где вы настроите error log в nginx.conf
ngx_link_func_log_info(ctx, "Это прямое сообщение информации");
ngx_link_func_log(info, ctx, "%s", "Это информация с форматированным сообщением");
ngx_link_func_log_debug(ctx, "Это прямое сообщение отладки");
ngx_link_func_log(debug, ctx, "%s", "Это отладка с форматированным сообщением");
ngx_link_func_log_info(ctx, "%s", "Это информация с форматированным сообщением"); // Неправильный формат
ngx_link_func_log_debug(ctx, "%s", "Это информация с форматированным сообщением"); // Неправильный формат
предоставить ca-cert для загрузки вашего приложения(.so)? Пожалуйста, вставьте это в контекст сервера вашего nginx.conf.
ngx_link_func_ca_cert "/etc/ssl/certs/ca-cert.crt"
ngx_link_func_download_link_lib "https://abc.com/repos/libcfuntest.so" "/etc/nginx/libcfuntest4.so"
предоставить ca-cert и дополнительный заголовок для загрузки вашего приложения(.so)? Пожалуйста, вставьте это в контекст сервера вашего nginx.conf.
ngx_link_func_ca_cert "/etc/ssl/certs/ca-cert.crt"
ngx_link_func_download_link_lib "https://abc.com/repos/libcfuntest.so" "Accept-Language:en_US\r\nAuthorization:Bearer KA.eyJ2ZXJzaadlasdlaldhjHJ2h3ldjklsjaklcjkljasdklcmasaskdaJxdkL3ftjM\r\n" "/etc/nginx/libcfuntest4.so"
Тест
Это зависит от библиотек тестового набора nginx, пожалуйста, обратитесь к test-nginx для установки.
cd /path/to/nginx-link-function
export PATH=/path/to/nginx-dirname:$PATH
sudo prove -r t/
Поддержка
Пожалуйста, создайте проблему, и я исправлю это, как только смогу
В качестве альтернативы, вы можете написать на [email protected]
Вики
Проверьте вики для получения дополнительных деталей