Creating a Hello World! Nginx Module
Some of my friends think nginx modules are very difficult to write. Sure it’s not so easy but it’s not that hard either. The only problem is that the documentation is not enough. But don’t let this scare yourself away, the situation is improving.
So I write a hello world nginx module here. It’s pretty short and with enough comments. If you’re a new nginx module developer, feel free to take it as an example and replace hello with whatever your module name is, then start your happy nginx module hacking journey. And I’ll write more topics on nginx soon. Look for it!
ngx_http_hello_module.c:
/* * Copyright (C) Joshua Zhu, http://www.zhuzhaoyuan.com */ #include <ngx_config.h> #include <ngx_core.h> #include <ngx_http.h> static char *ngx_http_hello(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); static ngx_command_t ngx_http_hello_commands[] = { { ngx_string("hello"), NGX_HTTP_LOC_CONF|NGX_CONF_NOARGS, ngx_http_hello, 0, 0, NULL }, ngx_null_command }; static u_char ngx_hello_string[] = "Hello, world!"; 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 */ }; ngx_module_t ngx_http_hello_module = { NGX_MODULE_V1, &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 }; static ngx_int_t ngx_http_hello_handler(ngx_http_request_t *r) { ngx_int_t rc; ngx_buf_t *b; ngx_chain_t out; /* we response to 'GET' and 'HEAD' requests only */ if (!(r->method & (NGX_HTTP_GET|NGX_HTTP_HEAD))) { return NGX_HTTP_NOT_ALLOWED; } /* discard request body, since we don't need it here */ rc = ngx_http_discard_request_body(r); if (rc != NGX_OK) { return rc; } /* set the 'Content-type' header */ r->headers_out.content_type_len = sizeof("text/html") - 1; r->headers_out.content_type.len = sizeof("text/html") - 1; r->headers_out.content_type.data = (u_char *) "text/html"; /* send the header only, if the request type is http 'HEAD' */ if (r->method == NGX_HTTP_HEAD) { r->headers_out.status = NGX_HTTP_OK; r->headers_out.content_length_n = sizeof(ngx_hello_string) - 1; return ngx_http_send_header(r); } /* allocate a buffer for your response body */ b = ngx_pcalloc(r->pool, sizeof(ngx_buf_t)); if (b == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } /* attach this buffer to the buffer chain */ out.buf = b; out.next = NULL; /* adjust the pointers of the buffer */ b->pos = ngx_hello_string; b->last = ngx_hello_string + sizeof(ngx_hello_string) - 1; b->memory = 1; /* this buffer is in memory */ b->last_buf = 1; /* this is the last buffer in the buffer chain */ /* set the status line */ r->headers_out.status = NGX_HTTP_OK; r->headers_out.content_length_n = sizeof(ngx_hello_string) - 1; /* send the headers of your response */ rc = ngx_http_send_header(r); if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) { return rc; } /* send the buffer chain of your response */ return ngx_http_output_filter(r, &out); } 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; /* handler to process the 'hello' directive */ return NGX_CONF_OK; }
config:
ngx_addon_name=ngx_http_hello_module HTTP_MODULES="$HTTP_MODULES ngx_http_hello_module" NGX_ADDON_SRCS="$NGX_ADDON_SRCS $ngx_addon_dir/ngx_http_hello_module.c"
hello.conf:
# hello
worker_processes 1;
events {
worker_connections 1024;
}
http {
server {
listen 8080;
server_name localhost;
location / {
hello;
}
}
}If you want more detailed information, please consult Evan Miller’s Guide To Nginx Module Development.
peanut said,
March 22, 2010 @ 4:58 am
Thank you! Very useful tutorial.
pauly said,
July 23, 2010 @ 5:00 pm
Thanks. It helps me a lot.
Fitzgerald said,
August 3, 2010 @ 3:03 pm
When setting the content type header; this looks a bit odd to me:
r->headers_out.content_type_len = sizeof(”text/html”) - 1;
r->headers_out.content_type.len = sizeof(”text/html”) - 1;
is this OK?
Joshua said,
August 6, 2010 @ 12:11 am
@Fitzgerald,
Yes. The value of content_type_len is usually the same as content_type.len, but in some case, i.e. when there’s charset setting with the Content-Type HTTP header, e.g. given header “Content-Type: text/html; charset=UTF-8″, content_type_len (23) is less than content_type.len (38).
DanielsJean said,
September 8, 2010 @ 7:16 pm
A lot of specialists argue that home loans aid people to live the way they want, because they are able to feel free to buy needed things. Furthermore, banks offer bank loan for different persons.
Wigunawan said,
October 19, 2010 @ 10:06 pm
nice tutor.
as Fitzgerald asked,
r->headers_out.content_type_len = sizeof(”text/html”) - 1;
r->headers_out.content_type.len = sizeof(”text/html”) - 1;
why you write the same code twice?
eric said,
December 14, 2010 @ 2:22 am
The G-WAN Web server and its ANSI C scripts are easier to write.
Here is a more complex ‘hello world’ that takes only 10 lines of C:
(more complex because it lets you specify who you say hello to)
http://gwan.ch/en_developers.html
G-WAN is not only working without any configuration fles, but it is
much faster than nginx.
Joshua said,
December 14, 2010 @ 11:52 am
@eric,
I agree with you that it is much easier that writing a “hello world” module for your G-WAN web server. But could you show us the benchmarks that G-WAN “is much faster than nginx”? BTW, it would be nice if G-WAN is going to be open source.
eric said,
December 15, 2010 @ 11:12 pm
@Joshua,
Per your request, benchmarks that show that G-WAN “is much faster than nginx”:
- on Windows:
http://gwan.ch/en_windows.html
- on Linux:
http://gwan.ch/en_linux.html
…which points to:
http://gwan.ch/imgs/gwan-lighttpd-nginx-cherokee.png
Being faster that nginx with STATIC contents, G-WAN is
also faster for DYNAMIC contents.
And this is true, even with an nginx pre-compiled module
(while G-WAN uses C scripts that are executed on-the-fly).
The open-source question has been debated in length
on the forum:
http://forum.trustleap.com/web/g-wanforum.nsf/viewTopic.xsp?topicID=1hkwsfnttsbuo
Joshua said,
December 16, 2010 @ 11:27 am
@eric,
Quite impressive! But I’m wondering is it possible that you give us more details of the benchmarks? e.g. hardware, OS, and configuration of the web servers. AFAIK, nginx is not optimized by default.
Zhao Haifeng said,
February 28, 2011 @ 7:05 pm
Hi, I’m Zhao Haifeng, an university student. I plan to write a web server like nginx as the Graduation Project. Of course, I know that it’s impossible for me to write such a greate one in such a short time. But I want to learn more about Linux, Web Server and programming from this graduation project. That’s why I ask my mentor to give me this topic. I want to read nginx source code first, but it’s really a hard job. I wonder if you can tell me something about how I can understand it. Or, could you please tell me what I should learn before doing my graduation project? Now, I just have basic knowlege of Linux, computer network (include HTTP) and programming.
Zhao Haifeng said,
February 28, 2011 @ 7:06 pm
Many thanks and waiting for your response.
Joshua said,
February 28, 2011 @ 10:03 pm
@Zhao Haifeng,
Wanna learn how a web server works? This may be a good start:
http://code.google.com/p/mongoose/
Check it out and have fun!
Zhao Haifeng said,
March 1, 2011 @ 3:55 pm
OK, thank you! I will check it this evening. If I have some problems, maybe I will ask you! Thank you!
Kris said,
March 28, 2011 @ 12:02 am
@Joshua,
G-WAN vs Nginx, Varnish, Apache Traffic Server (a cache server, like Varnish), Lighttpd have been benchmarked here:
http://nbonvin.wordpress.com/2011/03/24/serving-small-static-files-which-server-to-use/
Not only you have all the configurations published there, but there is also a comparison of the CPU and memory usage.
G-WAN beats all others (head and shoulders) despite the low-end hardware (a laptop Intel Core i3 – 370M @ 2.4 Ghz, Hard drive 5400 rpm, Memory: 4GB DDR3 1066MHz).
This is just to reply to your question about the server tuning issues (Nginx is tested with 2 and 4 workers).
Grigory said,
June 19, 2011 @ 5:06 am
@Kris,
In tests by your link, there is a very old nginx - 0.7.67. Why test authors didn’t get nginx-0.0.1 version to make a benchmark. They wrote the article at march 2011 and the question is: did they now that currently nignx was finally released at 1.0 version? (at the moment, when I’m writing this comment, nginx current version is 1.0.4). Very funny benchmark using “zombies” for tests
Grigory said,
June 19, 2011 @ 5:10 am
Oh my… they added update for 1.0 version. Sorry my bad
Magda said,
August 16, 2011 @ 12:34 am
IMHO you’ve got the right anwesr!
bjrikyiwvcz said,
August 18, 2011 @ 8:23 pm
WUcHIY fcoppjmrlgdj
cheap air max 360 said,
November 10, 2011 @ 9:33 am
nike air max
nike air max 90
nike air max 90 shoes
air max 90
air max 90 shoes
cheap nike air max
cheap nike air max 90
nike air max 2011
air max 2011
air max 2012
nike air max 2012
nike shoes
cheap nike shoes
cheap mens nike shoes
cheap womens nike shoes
air max shoes
cheap nike air max shoes
cheap air max shoes
air max 95
nike air max 95
nike shoes australia
nike run shoes
nike air max australia
nike air max 2010
air max 2010
womens nike shoes
womens nike air max shoes
cheap womens nike shoes
cheap mens nike shoes
womens air max shoes
mens air max shoes
mens nike air max shoes
mens nike shoes
cheap nike tn shoes
nike tn shoes
nike air max bw
air max bw
nike air max bw shoes
cheap nike air max bw
air max bw shoes
nike air max tn
cheap air max
cheap air max 90
cheap air max 95
cheap air max tn
cheap air max ltd
cheap air max 24 7
cheap air max 180
cheap air max 360