Skip to content

link: The Application dynamic linking with Nginx

Debian/Ubuntu installation

These docs apply to the APT package nginx-module-link provided by the GetPageSpeed Extras repository.

  1. Configure the APT repository as described in APT repository setup.
  2. Install the module:
sudo apt-get update
sudo apt-get install nginx-module-link

Warning

This module is not yet published as nginx-module-link in the APT repositories. Stay tuned, or email [email protected] to request it.


Native C/C++ function handlers for NGINX — load shared libraries and route requests directly to compiled code, with zero IPC overhead.

Overview

ngx_http_link_func bridges NGINX and native C/C++ applications through dynamic linking. Shared libraries (.so files) are loaded at server startup, and HTTP requests are dispatched directly to exported C functions running inside the NGINX worker process.

This means your C code has direct access to NGINX internals — request headers, URI arguments, request body, shared memory — and can write responses without serialization, sockets, or context switches.

Features

  • Native function dispatch — route any location to an exported C function
  • Shared memory and cache — cross-worker rbtree-based cache with mutex locking
  • Thread pool offloading — AIO thread support for blocking operations
  • Subrequest integration — chain with auth_request for authentication flows
  • Remote library loading — fetch .so files from HTTP/HTTPS URLs at startup
  • Lifecycle hooks — init and exit cycle callbacks for resource management
  • Per-server properties — pass configuration values from nginx.conf to your code

Quick Start

nginx.conf:

http {
    # Optional: shared memory for cross-worker cache
    ngx_link_func_shm_size 1m;

    server {
        listen 8080;

        # Load your compiled application
        ngx_link_func_lib "/opt/myapp/libhandlers.so";

        # Pass config values to your application
        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";
        }
    }
}

Your application (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;
    }

    // Process authenticated request...
    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");
}

Build and deploy:

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

Directives

Context: main | Default: none

Sets the shared memory zone size for cross-worker cache and data sharing.

ngx_link_func_shm_size 10m;

Context: server | Default: none

Loads a shared library for the server block. Multiple server blocks can load the same library to share memory.

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

Context: location | Default: none

Routes requests to an exported C function by name.

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

Context: server | Default: none

Passes key-value properties to the application, accessible via ngx_link_func_get_prop().

ngx_link_func_add_prop "api_key" "secret123";

Context: server | Default: none

Downloads a shared library from a remote URL at startup. Supports optional HTTP headers for authentication.

## Basic download
ngx_link_func_download_link_lib "https://repo.example.com/libapp.so" "/opt/myapp/libapp.so";

## With authentication headers
ngx_link_func_download_link_lib "https://repo.example.com/libapp.so"
    "Authorization:Bearer TOKEN\r\n"
    "/opt/myapp/libapp.so";

Context: server | Default: none

Sets the CA certificate for HTTPS library downloads.

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

Context: location | Default: none

Adds a request header, typically used to pass NGINX variables to subrequests.

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

Context: location | Default: none

Configures subrequest routing. Requires NGINX compiled with --with-http_auth_request_module.

location /protected {
    ngx_link_func_subrequest "/auth";
}

Application API

Include <ngx_link_func_module.h> in your application. The header provides the complete C API.

Lifecycle Hooks

These reserved function names are called automatically by NGINX:

void ngx_link_func_init_cycle(ngx_link_func_cycle_t *cycle);  // On startup
void ngx_link_func_exit_cycle(ngx_link_func_cycle_t *cycle);  // On shutdown/reload

Request Context

Every handler receives ngx_link_func_ctx_t *ctx with:

Field Type Description
req_args char * Raw URI query string
req_body u_char * Request body
req_body_len size_t Request body length
shared_mem void * Shared memory pointer

Functions

Function Description
Response
ngx_link_func_write_resp(ctx, status, status_line, content_type, body, len) Write HTTP response
ngx_link_func_write_resp_l(ctx, status, status_line, sl_len, ct, ct_len, body, len) Write response (explicit lengths)
Request data
ngx_link_func_get_uri(ctx, &str) Get request URI
ngx_link_func_get_remote_addr(ctx) Get client remote address
ngx_link_func_get_header(ctx, key, keylen) Get request header by name
ngx_link_func_get_query_param(ctx, key) Get query parameter by key
ngx_link_func_get_prop(ctx, key, keylen) Get server property
Headers
ngx_link_func_add_header_in(ctx, key, klen, val, vlen) Add input header
ngx_link_func_add_header_out(ctx, key, klen, val, vlen) Add output header
Memory
ngx_link_func_palloc(ctx, size) Allocate from NGINX pool
ngx_link_func_pcalloc(ctx, size) Allocate zeroed from NGINX pool
ngx_link_func_strdup(ctx, src) Duplicate string from pool
Shared memory
ngx_link_func_shm_alloc(shm, size) Allocate shared memory
ngx_link_func_shm_free(shm, ptr) Free shared memory
ngx_link_func_shmtx_lock(shm) Acquire mutex
ngx_link_func_shmtx_unlock(shm) Release mutex
ngx_link_func_shmtx_trylock(shm) Try to acquire mutex
Cache
ngx_link_func_cache_get(shm, key) Get cached value
ngx_link_func_cache_put(shm, key, value) Store cached value
ngx_link_func_cache_new(shm, key, size) Allocate and cache
ngx_link_func_cache_remove(shm, key) Remove from cache
Logging
ngx_link_func_log_debug/info/warn/err(ctx, msg) Log message
ngx_link_func_log(level, ctx, fmt, ...) Log formatted message

Content Type Constants

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