Hello world nginx module
Several times over the past few months I made short lived attempts of delving into the mechanics of nginx modules. Although an invaluable resource to anyone seriously interested in the subject, Emiller's Guide To Nginx Module Development doesn't at the time of this writing include a quick-start example I could hack together and see in action. Getting something to run as quickly as possible is my preferred way of starting the study of new things and every time I caught myself searching the web for a "Hello world nginx module".
I will not go into any details, Emiller's Guide does an excellent job at that, I'm only going to mention the steps I believe are absolutely necessary to write, compile and run an nginx handler module that responds to every request with the string "Hello world".
There is a minimum of two files required for writing an nginx module, the first should be called
config
and looks something like this:
ngx_addon_name=ngx_http_hello_world_module HTTP_MODULES="$HTTP_MODULES ngx_http_hello_world_module" NGX_ADDON_SRCS="$NGX_ADDON_SRCS $ngx_addon_dir/ngx_http_hello_world_module.c"
The second is the module's implementation in C and nginx convention suggests a name like
ngx_http_modulename_module.c
,
in this case
ngx_http_hello_world_module.c
.
#include <ngx_config.h> #include <ngx_core.h> #include <ngx_http.h> static char *ngx_http_hello_world(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); static ngx_command_t ngx_http_hello_world_commands[] = { { ngx_string("hello_world"), NGX_HTTP_LOC_CONF|NGX_CONF_NOARGS, ngx_http_hello_world, 0, 0, NULL }, ngx_null_command }; static u_char ngx_hello_world[] = "hello world"; static ngx_http_module_t ngx_http_hello_world_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 */ }; ngx_module_t ngx_http_hello_world_module = { NGX_MODULE_V1, &ngx_http_hello_world_module_ctx, /* module context */ ngx_http_hello_world_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 }; static ngx_int_t ngx_http_hello_world_handler(ngx_http_request_t *r) { ngx_buf_t *b; ngx_chain_t out; r->headers_out.content_type.len = sizeof("text/plain") - 1; r->headers_out.content_type.data = (u_char *) "text/plain"; b = ngx_pcalloc(r->pool, sizeof(ngx_buf_t)); out.buf = b; out.next = NULL; b->pos = ngx_hello_world; b->last = ngx_hello_world + sizeof(ngx_hello_world); b->memory = 1; b->last_buf = 1; r->headers_out.status = NGX_HTTP_OK; r->headers_out.content_length_n = sizeof(ngx_hello_world) - 1; ngx_http_send_header(r); return ngx_http_output_filter(r, &out); } static char *ngx_http_hello_world(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_world_handler; return NGX_CONF_OK; }
Both
config
and
ngx_http_hello_world_module.c
should be placed in the same directory, let's say
/etc/ngxhelloworld
.
Modules are compiled into the nginx binary. To do so,
download the nginx source,
uncompress, and in the nginx source directory run:
./configure --add-module=/etc/ngxhelloworld make sudo make install
Finally, add a module directive to nginx's configuration (default is
/usr/local/nginx/conf/nginx.conf
)
to enable the module for a location.
location = /hello { hello_world; }
At this point, we can start nginx and navigating to
http://localhost/hello
will yield the result of all this labor.
Alongside Emiller's Guide, I also found reading nginx third party module code helpful.