--- name: nginx-c-modules description: nginx C module development guidelines based on the official nginx development guide. This skill should be used when writing, reviewing, or refactoring nginx C modules to ensure correct memory management, request lifecycle handling, and event-driven patterns. Triggers on tasks involving nginx module development, ngx_http_module_t, handler/filter/upstream implementation, pool allocation, or nginx configuration directives. --- # nginx.org C Module Development Best Practices Comprehensive development guide for nginx C modules, derived from the official nginx development documentation and community expertise. Contains 49 rules across 8 categories, prioritized by impact to guide correct module implementation and prevent common crashes, memory leaks, and undefined behavior. ## When to Apply Reference these guidelines when: - Writing new nginx C modules (handlers, filters, upstream, load-balancers) - Implementing configuration directives and merge logic - Managing memory with nginx pools and shared memory zones - Handling the HTTP request lifecycle (body reading, subrequests, finalization) - Working with nginx's event loop, timers, and thread pools ## Rule Categories by Priority | Priority | Category | Impact | Prefix | |----------|----------|--------|--------| | 1 | Memory Management | CRITICAL | `mem-` | | 2 | Request Lifecycle | CRITICAL | `req-` | | 3 | Configuration System | HIGH | `conf-` | | 4 | Handler Development | HIGH | `handler-` | | 5 | Filter Chain | MEDIUM-HIGH | `filter-` | | 6 | Upstream & Proxy | MEDIUM | `upstream-` | | 7 | Event Loop & Concurrency | MEDIUM | `event-` | | 8 | Data Structures & Strings | LOW-MEDIUM | `ds-` | ## Quick Reference ### 1. Memory Management (CRITICAL) - [`mem-pool-allocation`](references/mem-pool-allocation.md) - Use Pool Allocation Instead of Heap malloc - [`mem-check-allocation`](references/mem-check-allocation.md) - Check Every Allocation Return for NULL - [`mem-pcalloc-structs`](references/mem-pcalloc-structs.md) - Use ngx_pcalloc for Struct Initialization - [`mem-cleanup-handlers`](references/mem-cleanup-handlers.md) - Register Pool Cleanup Handlers for External Resources - [`mem-pnalloc-strings`](references/mem-pnalloc-strings.md) - Use ngx_pnalloc for String Data Allocation - [`mem-pfree-limitations`](references/mem-pfree-limitations.md) - Avoid Relying on ngx_pfree for Pool Allocations - [`mem-shared-slab`](references/mem-shared-slab.md) - Use Slab Allocator for Shared Memory Zones ### 2. Request Lifecycle (CRITICAL) - [`req-finalize-once`](references/req-finalize-once.md) - Finalize Requests Exactly Once - [`req-no-access-after-finalize`](references/req-no-access-after-finalize.md) - Never Access Request After Finalization - [`req-body-async`](references/req-body-async.md) - Handle Request Body Reading Asynchronously - [`req-discard-body`](references/req-discard-body.md) - Discard Request Body When Not Reading It - [`req-subrequest-completion`](references/req-subrequest-completion.md) - Use Post-Subrequest Handlers for Completion - [`req-count-reference`](references/req-count-reference.md) - Increment Request Count Before Async Operations - [`req-internal-redirect`](references/req-internal-redirect.md) - Return After Internal Redirect ### 3. Configuration System (HIGH) - [`conf-unset-init`](references/conf-unset-init.md) - Initialize Config Fields with UNSET Constants - [`conf-merge-all-fields`](references/conf-merge-all-fields.md) - Merge All Config Fields in merge_loc_conf - [`conf-context-flags`](references/conf-context-flags.md) - Use Correct Context Flags for Directives - [`conf-null-command`](references/conf-null-command.md) - Terminate Commands Array with ngx_null_command - [`conf-custom-handler`](references/conf-custom-handler.md) - Use Custom Handlers for Complex Directive Parsing - [`conf-module-ctx-null`](references/conf-module-ctx-null.md) - Set Unused Module Context Callbacks to NULL - [`conf-build-config`](references/conf-build-config.md) - Write Correct config Build Script for Module Compilation ### 4. Handler Development (HIGH) - [`handler-send-header-first`](references/handler-send-header-first.md) - Send Header Before Body Output - [`handler-last-buf`](references/handler-last-buf.md) - Set last_buf Flag on Final Buffer - [`handler-phase-registration`](references/handler-phase-registration.md) - Register Phase Handlers in postconfiguration - [`handler-content-handler`](references/handler-content-handler.md) - Use content_handler for Location-Specific Response Generation - [`handler-error-page`](references/handler-error-page.md) - Return HTTP Status Codes for Error Responses - [`handler-empty-response`](references/handler-empty-response.md) - Use header_only for Empty Body Responses - [`handler-module-ctx`](references/handler-module-ctx.md) - Use Module Context for Per-Request State - [`handler-add-variable`](references/handler-add-variable.md) - Register Custom Variables in preconfiguration ### 5. Filter Chain (MEDIUM-HIGH) - [`filter-registration-order`](references/filter-registration-order.md) - Save and Replace Top Filter in postconfiguration - [`filter-call-next`](references/filter-call-next.md) - Always Call Next Filter in the Chain - [`filter-check-subrequest`](references/filter-check-subrequest.md) - Distinguish Main Request from Subrequest in Filters - [`filter-buffer-chain-iteration`](references/filter-buffer-chain-iteration.md) - Iterate Buffer Chains Using cl->next Pattern - [`filter-buffering-flag`](references/filter-buffering-flag.md) - Set Buffering Flag When Accumulating Response Data ### 6. Upstream & Proxy (MEDIUM) - [`upstream-create-request`](references/upstream-create-request.md) - Build Complete Request Buffer in create_request - [`upstream-process-header`](references/upstream-process-header.md) - Parse Upstream Response Incrementally in process_header - [`upstream-peer-free`](references/upstream-peer-free.md) - Track Failures in Peer free Callback - [`upstream-finalize`](references/upstream-finalize.md) - Clean Up Resources in finalize_request Callback - [`upstream-connection-reuse`](references/upstream-connection-reuse.md) - Enable Keepalive for Upstream Connections ### 7. Event Loop & Concurrency (MEDIUM) - [`event-no-blocking`](references/event-no-blocking.md) - Never Use Blocking Calls in Event Handlers - [`event-timer-management`](references/event-timer-management.md) - Delete Timers Before Freeing Associated Data - [`event-handle-read-write`](references/event-handle-read-write.md) - Call ngx_handle_read/write_event After I/O Operations - [`event-thread-pool`](references/event-thread-pool.md) - Offload Blocking Operations to Thread Pool - [`event-posted-events`](references/event-posted-events.md) - Use Posted Events for Deferred Processing ### 8. Data Structures & Strings (LOW-MEDIUM) - [`ds-ngx-str-not-null-terminated`](references/ds-ngx-str-not-null-terminated.md) - Never Assume ngx_str_t Is Null-Terminated - [`ds-ngx-str-set-literals`](references/ds-ngx-str-set-literals.md) - Use ngx_string Macro Only with String Literals - [`ds-cpymem-pattern`](references/ds-cpymem-pattern.md) - Use ngx_cpymem for Sequential Buffer Writes - [`ds-list-iteration`](references/ds-list-iteration.md) - Iterate ngx_list_t Using Part-Based Pattern - [`ds-hash-readonly`](references/ds-hash-readonly.md) - Build Hash Tables During Configuration Only ## How to Use Read individual reference files for detailed explanations and code examples: - [Section definitions](references/_sections.md) - Category structure and impact levels - [Rule template](assets/templates/_template.md) - Template for adding new rules ## Reference Files | File | Description | |------|-------------| | [references/_sections.md](references/_sections.md) | Category definitions and ordering | | [assets/templates/_template.md](assets/templates/_template.md) | Template for new rules | | [metadata.json](metadata.json) | Version and reference information |