# HG changeset patch # User Vladimir Homutov # Date 1563898075 -10800 # Node ID 392e11db3260d54428887a73d18179755c1d4ab5 # Parent 3bc28d88f34e6426c76ef2b1341fb3b0ff27659b Development guide: added the "Common Pitfalls" section. diff -r 3bc28d88f34e -r 392e11db3260 xml/en/docs/dev/development_guide.xml --- a/xml/en/docs/dev/development_guide.xml Tue Jul 23 15:16:41 2019 +0300 +++ b/xml/en/docs/dev/development_guide.xml Tue Jul 23 19:07:55 2019 +0300 @@ -9,7 +9,7 @@
+ rev="8">
@@ -258,7 +258,7 @@
-
+
For C strings, nginx uses the unsigned character type pointer @@ -7264,6 +7264,183 @@
+
+ +
+ +
+ + +The most common pitfall is an attempt to write a full-fledged C module. +In most cases your task can be accomplished by creating a proper configuration. +If writing a module is inevitable, try to make it +as small and simple as possible. +For example, a module can only export some +variables. + + + +Before starting a module, consider the following questions: + + + + +Is it possible to implement a desired feature using already +available modules? + + + +Is it possible to solve an issue using built-in scripting languages, +such as Perl +or njs? + + + + + + +
+ +
+ + +The most used string type in nginx, +ngx_str_t is not a C-Style +zero-terminated string. +You cannot pass the data to standard C library functions +such as strlen or strstr. +Instead, nginx counterparts +should be used that accept either ngx_str_t +or pointer to data and a length. +However, there is a case when ngx_str_t holds +a pointer to a zero-terminated string: strings that come as a result of +configuration file parsing are zero-terminated. + + +
+ +
+ + +Avoid using global variables in your modules. +Most likely this is an error to have a global variable. +Any global data should be tied to a configuration cycle +and be allocated from the corresponding memory pool. +This allows nginx to perform graceful configuration reloads. +An attempt to use global variables will likely break this feature, +because it will be impossible to have two configurations at +the same time and abandon of them. +Sometimes global variables are required. +In this case, special attention is needed to manage reconfiguration +properly. +Also, check if libraries used by your code have implicit +global state that may be broken on reload. + + +
+ +
+ + +Instead of dealing with malloc/free approach which is error prone, +learn how to use nginx pools. +A pool is created and tied to some object - +configuration, +cycle, +connection, +or HTTP request. +When an object is destroyed, the associated pool is destroyed too. +So when working with an object, it is possible to allocate as much as +needed from the corresponding pool and don't care about freeing memory, +even in case of errors. + + +
+ +
+ + +It is recommended to avoid using threads in nginx because it will +definitely break things: most nginx functions are not thread-safe. +It is expected that a thread will be executing only system calls and +thread-safe library functions. +If you need to run some code that is not related to client request processing, +the proper way is to schedule a timer in the init_process +module handler and perform required actions in timer handler. +Internally nginx makes use of threads to +boost IO-related operations, but this is a special case with a lot +of limitations. + + +
+ +
+ + +A common mistake is to use libraries that are blocking internally. +Most libraries out there are synchronous and blocking by nature. +In other words, they perform one operation at a time and waste +time waiting response from other peer. +As a result, when a request is processed with such library, whole +nginx worker is blocked, thus destroying performance. +Use only libraries that provide asynchronous interface and don't +block whole process. + + +
+ + +
+ + +Often modules need to perform an HTTP call to some external service. +A common mistake is to use some external library, such as libcurl, +to perform HTTP request. +It is absolutely unnecessary to bring a huge amount of external +(probably blocking!) code +for the task which can be accomplished by nginx itself. + + + +There are two basic usage scenarios when an external request is needed: + + + + +in the context of processing a client request (for example, in content handler) + + + +in the context of a worker process (for example, timer handler) + + + + + + + +In the first case, the best is to use +subrequests API. +Instead of directly accessing external service, you declare a location +in nginx configuration and direct your subrequest to this location. +This location is not limited to +proxying +requests, but may contain other nginx directives. +An example of such approach is the + +directive implemented in +ngx_http_auth_request module. + + + +For the second case, it is possible to use basic HTTP client functionality +available in nginx. +For example, +OCSP module +implements simple HTTP client. + + +