Skip to content

milad-zanganeh/ngx-http-hello

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Nginx Hello Module

This is a simple Nginx module that demonstrates how to create custom functionality in Nginx. The module adds a custom header and returns a simple HTML response.

Mission

The goal of this module is to demonstrate the fundamental concepts of Nginx module development by creating a simple "Hello World" module that:

  1. Intercepts HTTP requests
  2. Adds a custom header to the response
  3. Returns a simple HTML page
  4. Shows how to properly handle the Nginx request/response cycle

This serves as a foundation for understanding how to:

  • Create custom Nginx modules
  • Handle HTTP requests
  • Modify response headers
  • Generate response content
  • Integrate with Nginx's configuration system

Execution Flow

Here's a detailed breakdown of what happens when a request is processed:

  1. Request Arrival

    • A client sends an HTTP request to Nginx
    • Nginx matches the request to our location block (defined in nginx.conf)
    • The hello directive is encountered in the configuration
  2. Configuration Phase

    • Nginx calls our ngx_http_hello function (the command handler)
    • This function sets up our ngx_http_hello_handler as the content handler
    • The configuration is now ready to handle requests
  3. Request Processing

    • When a request matches our location, Nginx calls our handler
    • Our handler (ngx_http_hello_handler) is executed
    • The handler: a. Sets the content type to HTML b. Overrides the default Server header (server: nginx) c. Adds our custom "X-Hello-Module" header d. Creates a buffer with our HTML response e. Sets up the response chain f. Sends the headers and body
  4. Response Generation

    • Headers are sent first via ngx_http_send_header
    • The response body is sent through Nginx's output filter chain
    • The client receives the complete response

Module Structure

1. Module Definition

ngx_module_t ngx_http_hello_module = {
    NGX_MODULE_V1,                    // Module version
    &ngx_http_hello_module_ctx,       // Module context
    ngx_http_hello_commands,          // Module directives
    NGX_HTTP_MODULE,                  // Module type
    NULL,                             // init master
    NULL,                             // init module
    NULL,                             // init process
    NULL,                             // init thread
    NULL,                             // exit thread
    NULL,                             // exit process
    NULL,                             // exit master
    NGX_MODULE_V1_PADDING
};

This is the main module definition. It tells Nginx:

  • What type of module it is (HTTP module)
  • What commands/directives it provides
  • What context it needs
  • Various initialization and cleanup functions (all NULL in our case)

2. Module Commands

static ngx_command_t ngx_http_hello_commands[] = {
    { ngx_string("hello"),                // Command name
      NGX_HTTP_LOC_CONF|NGX_CONF_NOARGS,  // Where it can be used and arguments (in location and without arguments)
      ngx_http_hello,                     // Handler function
      0,                                  // Offset in configuration
      0,                                  // Offset in location configuration
      NULL },                             // Post handler
    ngx_null_command                      // End of commands array
};

This defines what commands our module provides. In our case, we have one command called hello that:

  • Can be used in location blocks (NGX_HTTP_LOC_CONF)
  • Takes no arguments (NGX_CONF_NOARGS)
  • Is handled by the ngx_http_hello function

3. Module Context

static ngx_http_module_t ngx_http_hello_module_ctx = {
    NULL,                             // preconfiguration
    NULL,                             // postconfiguration
    NULL,                             // create main configuration
    NULL,                             // init main configuration
    NULL,                             // create server configuration
    NULL,                             // merge server configuration
    NULL,                             // create location configuration
    NULL                              // merge location configuration
};

The module context defines how our module interacts with Nginx's configuration system. Since our module is simple and doesn't need to store any configuration, all these are NULL.

4. Command Handler

static char *
ngx_http_hello(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
    ngx_http_core_loc_conf_t  *clcf;

    clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
    clcf->handler = ngx_http_hello_handler;

    return NGX_CONF_OK;
}

This function is called when Nginx encounters our hello directive in the configuration. It:

  1. Gets the location configuration
  2. Sets our handler function (ngx_http_hello_handler) as the content handler for this location

5. Request Handler

static ngx_int_t
ngx_http_hello_handler(ngx_http_request_t *r)
{
    // Set content type
    r->headers_out.content_type.len = sizeof("text/html") - 1;
    r->headers_out.content_type.data = (u_char *) "text/html";

    // Add custom header
    ngx_table_elt_t *h = ngx_list_push(&r->headers_out.headers);
    h->hash = 1;
    ngx_str_set(&h->key, "X-Hello-Module");
    ngx_str_set(&h->value, "Hello from Nginx Module!!!!");

    // Create response buffer
    ngx_buf_t *b = ngx_pcalloc(r->pool, sizeof(ngx_buf_t));
    b->pos = (u_char *) "<html><body><h1>Hello from Nginx Module!</h1></body></html>";
    b->last = b->pos + sizeof("<html><body><h1>Hello from Nginx Module!</h1></body></html>") - 1;
    b->memory = 1;
    b->last_buf = 1;

    // Create output chain
    ngx_chain_t *out = ngx_pcalloc(r->pool, sizeof(ngx_chain_t));
    out->buf = b;
    out->next = NULL;

    // Set response status and length
    r->headers_out.status = NGX_HTTP_OK;
    r->headers_out.content_length_n = b->last - b->pos;

    // Send headers and body
    ngx_http_send_header(r);
    return ngx_http_output_filter(r, out);
}

This is the most important part of our code: The handler! here are the things that our handler does:

  1. Sets the content type to HTML
  2. Adds our custom "X-Hello-Module" header and override the Server header.
  3. Creates a buffer with our HTML response
  4. Sets up the response chain
  5. Sends the headers and body

Building and Running

  1. Build the Docker container:
docker compose up --build
  1. Test the module:
curl -v http://localhost:8080

You should see:

  • A 200 OK response
  • The custom "X-Hello-Module" header
  • The HTML content we defined

How It Works

When a request comes to Nginx:

  1. Nginx matches the URL to our location block
  2. Sees the hello directive
  3. Calls our handler function
  4. Our handler creates and sends the response

This is a basic example, but it shows the core concepts of Nginx module development:

  • Module definition
  • Command registration
  • Request handling
  • Response generation

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors