comparison ngx_http_delay_module.c @ 0:9777bf89da35

Delay module.
author Maxim Dounin <mdounin@mdounin.ru>
date Tue, 29 Jun 2010 22:08:53 +0400
parents
children aee676aa6c1f
comparison
equal deleted inserted replaced
-1:000000000000 0:9777bf89da35
1
2 /*
3 * Copyright (C) Maxim Dounin
4 */
5
6
7 #include <ngx_config.h>
8 #include <ngx_core.h>
9 #include <ngx_http.h>
10
11
12 typedef struct {
13 ngx_msec_t delay;
14 } ngx_http_delay_conf_t;
15
16
17 static void ngx_http_delay_event_handler(ngx_http_request_t *r);
18
19
20 static void *ngx_http_delay_create_conf(ngx_conf_t *cf);
21 static char *ngx_http_delay_merge_conf(ngx_conf_t *cf, void *parent,
22 void *child);
23 static ngx_int_t ngx_http_delay_init(ngx_conf_t *cf);
24
25
26 static ngx_command_t ngx_http_delay_commands[] = {
27
28 { ngx_string("delay"),
29 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
30 ngx_conf_set_msec_slot,
31 NGX_HTTP_LOC_CONF_OFFSET,
32 offsetof(ngx_http_delay_conf_t, delay),
33 NULL },
34
35 ngx_null_command
36 };
37
38
39 static ngx_http_module_t ngx_http_delay_module_ctx = {
40 NULL, /* preconfiguration */
41 ngx_http_delay_init, /* postconfiguration */
42
43 NULL, /* create main configuration */
44 NULL, /* init main configuration */
45
46 NULL, /* create server configuration */
47 NULL, /* merge server configuration */
48
49 ngx_http_delay_create_conf, /* create location configration */
50 ngx_http_delay_merge_conf /* merge location configration */
51 };
52
53
54 ngx_module_t ngx_http_delay_module = {
55 NGX_MODULE_V1,
56 &ngx_http_delay_module_ctx, /* module context */
57 ngx_http_delay_commands, /* module directives */
58 NGX_HTTP_MODULE, /* module type */
59 NULL, /* init master */
60 NULL, /* init module */
61 NULL, /* init process */
62 NULL, /* init thread */
63 NULL, /* exit thread */
64 NULL, /* exit process */
65 NULL, /* exit master */
66 NGX_MODULE_V1_PADDING
67 };
68
69
70 static ngx_int_t
71 ngx_http_delay_handler(ngx_http_request_t *r)
72 {
73 ngx_http_delay_conf_t *dcf;
74
75 if (ngx_http_get_module_ctx(r, ngx_http_delay_module) != NULL) {
76 return NGX_DECLINED;
77 }
78
79 dcf = ngx_http_get_module_loc_conf(r, ngx_http_delay_module);
80
81 if (dcf->delay == NGX_CONF_UNSET_MSEC) {
82 return NGX_DECLINED;
83 }
84
85 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
86 "delaying request");
87
88 if (ngx_handle_read_event(r->connection->read, 0) != NGX_OK) {
89 return NGX_HTTP_INTERNAL_SERVER_ERROR;
90 }
91
92 r->read_event_handler = ngx_http_test_reading;
93 r->write_event_handler = ngx_http_delay_event_handler;
94
95 ngx_add_timer(r->connection->write, dcf->delay);
96
97 ngx_http_set_ctx(r, (void *) 1, ngx_http_delay_module);
98
99 return NGX_AGAIN;
100 }
101
102
103 static void
104 ngx_http_delay_event_handler(ngx_http_request_t *r)
105 {
106 ngx_event_t *wev;
107
108 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
109 "delay");
110
111 wev = r->connection->write;
112
113 if (!wev->timedout) {
114
115 if (ngx_handle_write_event(wev, 0) != NGX_OK) {
116 ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
117 }
118
119 return;
120 }
121
122 wev->timedout = 0;
123
124 if (ngx_handle_read_event(r->connection->read, 0) != NGX_OK) {
125 ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
126 return;
127 }
128
129 r->read_event_handler = ngx_http_block_reading;
130 r->write_event_handler = ngx_http_core_run_phases;
131
132 ngx_http_core_run_phases(r);
133 }
134
135
136 static void *
137 ngx_http_delay_create_conf(ngx_conf_t *cf)
138 {
139 ngx_http_delay_conf_t *conf;
140
141 conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_delay_conf_t));
142 if (conf == NULL) {
143 return NULL;
144 }
145
146 /*
147 * set by ngx_pcalloc():
148 *
149 */
150
151 conf->delay = NGX_CONF_UNSET_MSEC;
152
153 return conf;
154 }
155
156
157 static char *
158 ngx_http_delay_merge_conf(ngx_conf_t *cf, void *parent, void *child)
159 {
160 ngx_http_delay_conf_t *prev = parent;
161 ngx_http_delay_conf_t *conf = child;
162
163 ngx_conf_merge_msec_value(conf->delay, prev->delay,
164 NGX_CONF_UNSET_MSEC);
165
166 return NGX_CONF_OK;
167 }
168
169
170 static ngx_int_t
171 ngx_http_delay_init(ngx_conf_t *cf)
172 {
173 ngx_http_handler_pt *h;
174 ngx_http_core_main_conf_t *cmcf;
175
176 cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
177
178 h = ngx_array_push(&cmcf->phases[NGX_HTTP_PREACCESS_PHASE].handlers);
179 if (h == NULL) {
180 return NGX_ERROR;
181 }
182
183 *h = ngx_http_delay_handler;
184
185 return NGX_OK;
186 }