lien: La liaison dynamique d'application avec Nginx
Installation
Vous pouvez installer ce module dans n'importe quelle distribution basée sur RHEL, y compris, mais 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 en haut de /etc/nginx/nginx.conf :
load_module modules/ngx_http_link_func_module.so;
Ce document décrit nginx-module-link v3.2.4 publié le 13 octobre 2020.

nginx-link-function
La liaison dynamique d'application avec Nginx
Introduction
nginx-link-function est un module nginx qui fournit une liaison dynamique à votre application dans le contexte du serveur et appelle la fonction de votre application dans la directive de localisation. Vous pouvez lier directement votre application C/C++ (ou toute autre qui accepte la liaison dynamique) au serveur nginx.
Comment ça marche

Utilisation
## 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"; # partage de la mémoire des données avec le serveur 1 si le chemin est le même que le serveur 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"; # une autre application
...
...
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;
...
## Télécharger l'application depuis le dépôt cloud e.g. 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;
...
## Télécharger l'application depuis le dépôt cloud avec un en-tête supplémentaire e.g. 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";
}
}
Interface exposée à l'application cliente
Voici l'interface que vous pouvez utiliser pour obtenir plus de détails du serveur nginx, tout est à l'intérieur de 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; // Arguments Uri
u_char *req_body; // Corps de la requête
size_t req_body_len; // longueur du corps
void *shared_mem;
/* interne */
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
);
// Mémoire partagée et portée de cache
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);
Détails de l'interface
malloc/calloc depuis le pool 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);
obtenir le paramètre d'en-tête de la requête
extern u_char* ngx_link_func_get_header(ngx_link_func_ctx_t *ctx, const char*key);
obtenir les arguments uri
ctx->req_args;
obtenir le paramètre de requête
extern void* ngx_link_func_get_query_param(ngx_link_func_ctx_t *ctx, const char *key);
obtenir le corps de la requête
ctx->req_body;
obtenir la longueur du corps de la requête
ctx->req_body_len;
journalisation sur le serveur 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);
Réponse
extern void ngx_link_func_write_resp(
ngx_link_func_ctx_t *ctx,
uintptr_t status_code, // Code d'état
const char* status_line, // Ligne d'état
const char* content_type, // Type de contenu de la réponse
const char* resp_content, // Contenu de la réponse
size_t resp_len // Longueur du contenu de la réponse
);
Développement d'application d'exemple
N'hésitez pas à cloner un projet d'exemple à
direction de fonction de lien google linkfunc-jwt-auth
#include <stdio.h>
#include <ngx_link_func_module.h>
/*** construire le programme en tant que bibliothèque .so et copier à l'endroit préféré pour que nginx puisse lier cette bibliothèque ***/
/*** 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", "démarrage de l'application");
is_service_on=1;
}
void my_app_simple_get_greeting(ngx_link_func_ctx_t *ctx) {
ngx_link_func_log_info(ctx, "Appel et journalisation depuis my_app_simple_get");
ngx_link_func_write_resp(
ctx,
200,
"200 OK",
"text/plain",
"salutation de test de ngx_link_func",
sizeof("salutation de test de ngx_link_func")-1
);
}
void my_app_simple_get_args(ngx_link_func_ctx_t *ctx) {
ngx_link_func_log_info(ctx, "Appel et journalisation depuis 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, "Appel et journalisation depuis 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 non autorisé",
"text/plain",
"Token non trouvé",
sizeof("Token non trouvé")-1
);
} else {
ngx_link_func_write_resp(
ctx,
401,
"401 non autorisé",
"text/plain",
tokenArgs,
strlen(tokenArgs)
);
}
}
void my_app_simple_post(ngx_link_func_ctx_t *ctx) {
ngx_link_func_log_info(ctx, "Appel et journalisation depuis my_app_simple_post");
ngx_link_func_write_resp(
ctx,
202,
"202 Accepté et en cours de traitement",
"text/plain",
NULL,
0
);
}
void my_app_simple_get_no_resp(ngx_link_func_ctx_t *ctx) {
ngx_link_func_log_info(ctx, "Appel et journalisation depuis my_app_simple_get_no_resp");
// retourner 404
}
void ngx_link_func_exit_cycle(ngx_link_func_cycle_t* cyc) {
ngx_link_func_cyc_log(info, cyc, "%s\n", "Arrêt/rechargement de l'application");
is_service_on = 0;
}
Remarque :
Les fonctions init et exit cycle sont des fonctions réservées lors du démarrage de nginx, elle appellera la fonction init cycle, lorsque nginx s'arrête/recharge, elle appellera la fonction exit cycle.
void ngx_link_func_init_cycle(ngx_link_func_cycle_t* cyc){}
void ngx_link_func_exit_cycle(ngx_link_func_cycle_t* cyc){}
Niveau de journalisation
Le journal peut être appelé, le message enregistré sera stocké là où vous configurez le journal des erreurs dans nginx.conf
ngx_link_func_log_info(ctx, "Ceci est un message direct d'information");
ngx_link_func_log(info, ctx, "%s", "Ceci est un message d'information formaté");
ngx_link_func_log_debug(ctx, "Ceci est un message direct de débogage");
ngx_link_func_log(debug, ctx, "%s", "Ceci est un message de débogage formaté");
ngx_link_func_log_info(ctx, "%s", "Ceci est un message d'information formaté"); // Mauvais format
ngx_link_func_log_debug(ctx, "%s", "Ceci est un message d'information formaté"); // Mauvais format
fournir ca-cert pour télécharger votre application (.so) ?? veuillez l'incorporer dans le contexte du serveur de votre 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"
fournir ca-cert et en-tête supplémentaire pour télécharger votre application (.so) ?? veuillez l'incorporer dans le contexte du serveur de votre 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"
Test
Cela dépend des bibliothèques de la suite de tests nginx, veuillez vous référer à test-nginx pour l'installation.
cd /path/to/nginx-link-function
export PATH=/path/to/nginx-dirname:$PATH
sudo prove -r t/
Support
Veuillez soumettre un problème et je le corrigerai dès que possible.
Alternativement, vous pouvez envoyer un e-mail à minikawoon2017@gmail.com.
Wiki
Consultez le wiki pour plus de détails.
GitHub
Vous pouvez trouver des conseils de configuration supplémentaires et de la documentation pour ce module dans le dépôt GitHub pour nginx-module-link.