Aller au contenu

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.


Logo de la fonction de lien nginx

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

Image de nginx-link-function

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 à

Projet Simple avec cmake

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){}
références : Les hooks de cycle init et exit dans la couche d'application

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.