comparison src/http/modules/ngx_http_status_module.c @ 501:d4ea69372b94 release-0.1.25

nginx-0.1.25-RELEASE import *) Bugfix: nginx did run on Linux parisc. *) Feature: nginx now does not start under FreeBSD if the sysctl kern.ipc.somaxconn value is too big. *) Bugfix: if a request was internally redirected by the ngx_http_index_module module to the ngx_http_proxy_module or ngx_http_fastcgi_module modules, then the index file was not closed after request completion. *) Feature: the "proxy_pass" can be used in location with regular expression. *) Feature: the ngx_http_rewrite_filter_module module supports the condition like "if ($HTTP_USER_AGENT ~ MSIE)". *) Bugfix: nginx started too slow if the large number of addresses and text values were used in the "geo" directive. *) Change: a variable name must be declared as "$name" in the "geo" directive. The previous variant without "$" is still supported, but will be removed soon. *) Feature: the "%{VARIABLE}v" logging parameter. *) Feature: the "set $name value" directive. *) Bugfix: gcc 4.0 compatibility. *) Feature: the --with-openssl-opt=OPTIONS autoconfiguration directive.
author Igor Sysoev <igor@sysoev.ru>
date Sat, 19 Mar 2005 12:38:37 +0000
parents src/http/modules/ngx_http_status_handler.c@a88a3e4e158f
children 4d9ea73a627a
comparison
equal deleted inserted replaced
500:9a0f304470f5 501:d4ea69372b94
1
2 /*
3 * Copyright (C) Igor Sysoev
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_http_request_t *request;
14 ngx_pool_t *pool;
15 ngx_chain_t *head;
16 ngx_buf_t *last;
17 size_t size;
18 } ngx_http_status_ctx_t;
19
20
21 static ngx_int_t ngx_http_status(ngx_http_status_ctx_t *ctx);
22 static char *ngx_http_set_status(ngx_conf_t *cf, ngx_command_t *cmd,
23 void *conf);
24
25 static ngx_command_t ngx_http_status_commands[] = {
26
27 { ngx_string("status"),
28 NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
29 ngx_http_set_status,
30 0,
31 0,
32 NULL },
33
34 ngx_null_command
35 };
36
37
38
39 ngx_http_module_t ngx_http_status_module_ctx = {
40 NULL, /* pre conf */
41
42 NULL, /* create main configuration */
43 NULL, /* init main configuration */
44
45 NULL, /* create server configuration */
46 NULL, /* merge server configuration */
47
48 NULL, /* create location configuration */
49 NULL /* merge location configuration */
50 };
51
52
53 ngx_module_t ngx_http_status_module = {
54 NGX_MODULE,
55 &ngx_http_status_module_ctx, /* module context */
56 ngx_http_status_commands, /* module directives */
57 NGX_HTTP_MODULE, /* module type */
58 NULL, /* init module */
59 NULL /* init process */
60 };
61
62
63 static ngx_int_t ngx_http_status_handler(ngx_http_request_t *r)
64 {
65 ngx_int_t rc;
66 ngx_http_status_ctx_t ctx;
67
68 if (r->method != NGX_HTTP_GET && r->method != NGX_HTTP_HEAD) {
69 return NGX_HTTP_NOT_ALLOWED;
70 }
71
72 rc = ngx_http_discard_body(r);
73
74 if (rc != NGX_OK && rc != NGX_AGAIN) {
75 return rc;
76 }
77
78 r->headers_out.content_type = ngx_list_push(&r->headers_out.headers);
79 if (r->headers_out.content_type == NULL) {
80 return NGX_HTTP_INTERNAL_SERVER_ERROR;
81 }
82
83 r->headers_out.content_type->key.len = 0;
84 r->headers_out.content_type->key.data = NULL;
85 r->headers_out.content_type->value.len = sizeof("text/plain") - 1;
86 r->headers_out.content_type->value.data = (u_char *) "text/plain";
87
88 if (r->method == NGX_HTTP_HEAD) {
89 r->headers_out.status = NGX_HTTP_OK;
90
91 rc = ngx_http_send_header(r);
92
93 if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) {
94 return rc;
95 }
96 }
97
98 ctx.request = r;
99 ctx.pool = r->pool;
100 ctx.head = NULL;
101 ctx.size = 0;
102
103 if (ngx_http_status(&ctx) != NGX_OK) {
104 return NGX_HTTP_INTERNAL_SERVER_ERROR;
105 }
106
107 r->headers_out.status = NGX_HTTP_OK;
108 r->headers_out.content_length_n = ctx.size;
109
110 rc = ngx_http_send_header(r);
111
112 if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) {
113 return rc;
114 }
115
116 if (!r->main) {
117 ctx.last->last_buf = 1;
118 }
119
120 return ngx_http_output_filter(r, ctx.head);
121 }
122
123
124 static ngx_int_t ngx_http_status(ngx_http_status_ctx_t *ctx)
125 {
126 u_char ch;
127 size_t len, n;
128 ngx_uint_t i, dash;
129 ngx_buf_t *b;
130 ngx_chain_t *cl, **ll;
131 ngx_connection_t *c;
132 ngx_http_request_t *r;
133 ngx_http_core_main_conf_t *cmcf;
134
135 cmcf = ngx_http_get_module_main_conf(ctx->request, ngx_http_core_module);
136
137 #if (NGX_SUPPRESS_WARN)
138 b = NULL;
139 ll = NULL;
140 #endif
141
142 dash = 0;
143
144 /* TODO: old connections */
145
146 c = ngx_cycle->connections;
147 for (i = 0; i < ngx_cycle->connection_n; i++) {
148
149 /* TODO: trylock connection mutex */
150
151 r = c[i].data;
152 if (r && r->signature == NGX_HTTP_MODULE) {
153
154 /* STUB: should be NGX_PID_T_LEN */
155 len = NGX_INT64_LEN /* pid */
156 + 1 + NGX_INT32_LEN /* connection */
157 + 1 + 1 /* state */
158 + 1 + INET_ADDRSTRLEN
159 + 1 + (r->server_name ? cmcf->max_server_name_len : 1)
160 + 2; /* "\r\n" */
161
162 /* BUG: cmcf->max_server_name_len and "*.domain.tld" */
163
164
165 if (r->request_line.len) {
166 len += 1 + 1 + r->request_line.len + 1;
167 }
168
169 if (!(b = ngx_create_temp_buf(ctx->pool, len))) {
170 /* TODO: unlock mutex */
171 return NGX_ERROR;
172 }
173
174 b->last = ngx_sprintf(b->last, "%P %5ui", ngx_pid, i);
175
176 switch (r->http_state) {
177 case NGX_HTTP_INITING_REQUEST_STATE:
178 ch = 'I';
179 break;
180
181 case NGX_HTTP_READING_REQUEST_STATE:
182 ch = 'R';
183 break;
184
185 case NGX_HTTP_PROCESS_REQUEST_STATE:
186 ch = 'P';
187 break;
188
189 case NGX_HTTP_WRITING_REQUEST_STATE:
190 ch = 'W';
191 break;
192
193 case NGX_HTTP_KEEPALIVE_STATE:
194 ch = 'K';
195 break;
196
197 default:
198 ch = '?';
199 }
200
201 *(b->last++) = ' ';
202 *(b->last++) = ch;
203
204 *(b->last++) = ' ';
205 b->last = ngx_cpymem(b->last, c[i].addr_text.data,
206 c[i].addr_text.len);
207 for (n = c[i].addr_text.len; n < INET_ADDRSTRLEN; n++) {
208 *(b->last++) = ' ';
209 }
210
211 *(b->last++) = ' ';
212 if (r->server_name) {
213 b->last = ngx_cpymem(b->last, r->server_name->data,
214 r->server_name->len);
215 for (n = r->server_name->len;
216 n < cmcf->max_server_name_len;
217 n++)
218 {
219 *(b->last++) = ' ';
220 }
221
222 } else {
223 *(b->last++) = '?';
224 }
225
226 if (r->request_line.len) {
227 *(b->last++) = ' ';
228 *(b->last++) = '"';
229 b->last = ngx_cpymem(b->last, r->request_line.data,
230 r->request_line.len);
231 *(b->last++) = '"';
232
233 }
234
235 *(b->last++) = CR; *(b->last++) = LF;
236
237 dash = 0;
238
239 } else if (c[i].fd != -1) {
240 len = NGX_INT64_LEN /* pid */
241 + 1 + NGX_INT32_LEN /* connection */
242 + 1 + 1 /* state */
243 + 2; /* "\r\n" */
244
245 if (!(b = ngx_create_temp_buf(ctx->pool, len))) {
246 /* TODO: unlock mutex */
247 return NGX_ERROR;
248 }
249
250 b->last = ngx_sprintf(b->last, "%P %5ui", ngx_pid, i);
251
252 *(b->last++) = ' ';
253 *(b->last++) = 's';
254
255 *(b->last++) = CR; *(b->last++) = LF;
256
257 dash = 0;
258
259 } else if (!dash) {
260 len = 3;
261
262 if (!(b = ngx_create_temp_buf(ctx->pool, len))) {
263 /* TODO: unlock mutex */
264 return NGX_ERROR;
265 }
266
267 *(b->last++) = '-'; *(b->last++) = CR; *(b->last++) = LF;
268
269 dash = 1;
270
271 } else {
272 continue;
273 }
274
275 /* TODO: unlock mutex */
276
277 if (!(cl = ngx_alloc_chain_link(ctx->pool))) {
278 return NGX_ERROR;
279 }
280
281 if (ctx->head) {
282 *ll = cl;
283
284 } else {
285 ctx->head = cl;
286 }
287
288 cl->buf = b;
289 cl->next = NULL;
290 ll = &cl->next;
291
292 ctx->size += b->last - b->pos;
293 }
294
295 ctx->last = b;
296
297 return NGX_OK;
298 }
299
300
301 static char *ngx_http_set_status(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
302 {
303 ngx_http_core_loc_conf_t *clcf;
304
305 clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
306 clcf->handler = ngx_http_status_handler;
307
308 return NGX_CONF_OK;
309 }