blob: a2e2dbc07f36c14a3ae5fe2a94f9ed2089bba72d [file] [log] [blame]
Igor Sysoevc83f6832004-06-24 07:53:37 +00001
Igor Sysoevd90282d2004-09-28 08:34:51 +00002/*
Igor Sysoevff8da912004-09-29 16:00:49 +00003 * Copyright (C) Igor Sysoev
Igor Sysoevd90282d2004-09-28 08:34:51 +00004 */
5
6
Igor Sysoevc83f6832004-06-24 07:53:37 +00007#include <ngx_config.h>
8#include <ngx_core.h>
9#include <ngx_http.h>
10
11
Igor Sysoevb1af9bb2004-06-25 14:42:03 +000012typedef 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
21static ngx_int_t ngx_http_status(ngx_http_status_ctx_t *ctx);
22static char *ngx_http_set_status(ngx_conf_t *cf, ngx_command_t *cmd,
23 void *conf);
Igor Sysoevc83f6832004-06-24 07:53:37 +000024
25static ngx_command_t ngx_http_status_commands[] = {
26
27 { ngx_string("status"),
28 NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
Igor Sysoevb1af9bb2004-06-25 14:42:03 +000029 ngx_http_set_status,
Igor Sysoevc83f6832004-06-24 07:53:37 +000030 0,
31 0,
32 NULL },
33
34 ngx_null_command
35};
36
37
38
Igor Sysoev8f125582006-07-28 15:16:17 +000039static ngx_http_module_t ngx_http_status_module_ctx = {
Igor Sysoevc83f6832004-06-24 07:53:37 +000040 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
53ngx_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
63static ngx_int_t ngx_http_status_handler(ngx_http_request_t *r)
64{
Igor Sysoevb1af9bb2004-06-25 14:42:03 +000065 ngx_int_t rc;
66 ngx_http_status_ctx_t ctx;
Igor Sysoevc83f6832004-06-24 07:53:37 +000067
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
Igor Sysoevaab4d8c2004-09-06 18:45:00 +000078 r->headers_out.content_type = ngx_list_push(&r->headers_out.headers);
79 if (r->headers_out.content_type == NULL) {
Igor Sysoevc83f6832004-06-24 07:53:37 +000080 return NGX_HTTP_INTERNAL_SERVER_ERROR;
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +000081 }
Igor Sysoevc83f6832004-06-24 07:53:37 +000082
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
Igor Sysoevb1af9bb2004-06-25 14:42:03 +000098 ctx.request = r;
99 ctx.pool = r->pool;
100 ctx.head = NULL;
101 ctx.size = 0;
Igor Sysoevc83f6832004-06-24 07:53:37 +0000102
Igor Sysoevb1af9bb2004-06-25 14:42:03 +0000103 if (ngx_http_status(&ctx) != NGX_OK) {
Igor Sysoevc83f6832004-06-24 07:53:37 +0000104 return NGX_HTTP_INTERNAL_SERVER_ERROR;
105 }
106
Igor Sysoevb1af9bb2004-06-25 14:42:03 +0000107 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
124static 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
Igor Sysoevc83f6832004-06-24 07:53:37 +0000142 dash = 0;
143
Igor Sysoevb1af9bb2004-06-25 14:42:03 +0000144 /* TODO: old connections */
145
146 c = ngx_cycle->connections;
Igor Sysoevc83f6832004-06-24 07:53:37 +0000147 for (i = 0; i < ngx_cycle->connection_n; i++) {
Igor Sysoevb1af9bb2004-06-25 14:42:03 +0000148
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
Igor Sysoevc0edbcc2004-10-21 15:34:38 +0000162 /* BUG: cmcf->max_server_name_len and "*.domain.tld" */
163
164
Igor Sysoevb1af9bb2004-06-25 14:42:03 +0000165 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 }
Igor Sysoevc83f6832004-06-24 07:53:37 +0000173
Igor Sysoev1b735832004-11-11 14:07:14 +0000174 b->last = ngx_sprintf(b->last, "%P %5ui", ngx_pid, i);
Igor Sysoev59f3aa32004-06-24 16:07:04 +0000175
Igor Sysoevb1af9bb2004-06-25 14:42:03 +0000176 switch (r->http_state) {
Igor Sysoevc83f6832004-06-24 07:53:37 +0000177 case NGX_HTTP_INITING_REQUEST_STATE:
Igor Sysoev59f3aa32004-06-24 16:07:04 +0000178 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;
Igor Sysoevc83f6832004-06-24 07:53:37 +0000192
193 case NGX_HTTP_KEEPALIVE_STATE:
Igor Sysoev59f3aa32004-06-24 16:07:04 +0000194 ch = 'K';
195 break;
196
197 default:
198 ch = '?';
Igor Sysoevc83f6832004-06-24 07:53:37 +0000199 }
Igor Sysoev59f3aa32004-06-24 16:07:04 +0000200
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);
Igor Sysoevb1af9bb2004-06-25 14:42:03 +0000207 for (n = c[i].addr_text.len; n < INET_ADDRSTRLEN; n++) {
208 *(b->last++) = ' ';
209 }
Igor Sysoev59f3aa32004-06-24 16:07:04 +0000210
211 *(b->last++) = ' ';
Igor Sysoevb1af9bb2004-06-25 14:42:03 +0000212 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 }
Igor Sysoevc83f6832004-06-24 07:53:37 +0000221
Igor Sysoevb1af9bb2004-06-25 14:42:03 +0000222 } else {
223 *(b->last++) = '?';
224 }
225
226 if (r->request_line.len) {
Igor Sysoevc83f6832004-06-24 07:53:37 +0000227 *(b->last++) = ' ';
Igor Sysoevc83f6832004-06-24 07:53:37 +0000228 *(b->last++) = '"';
229 b->last = ngx_cpymem(b->last, r->request_line.data,
230 r->request_line.len);
231 *(b->last++) = '"';
232
Igor Sysoevc83f6832004-06-24 07:53:37 +0000233 }
234
Igor Sysoev59f3aa32004-06-24 16:07:04 +0000235 *(b->last++) = CR; *(b->last++) = LF;
236
237 dash = 0;
238
Igor Sysoevb1af9bb2004-06-25 14:42:03 +0000239 } 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
Igor Sysoev1b735832004-11-11 14:07:14 +0000250 b->last = ngx_sprintf(b->last, "%P %5ui", ngx_pid, i);
Igor Sysoevb1af9bb2004-06-25 14:42:03 +0000251
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 {
Igor Sysoevc83f6832004-06-24 07:53:37 +0000272 continue;
273 }
274
Igor Sysoevb1af9bb2004-06-25 14:42:03 +0000275 /* TODO: unlock mutex */
276
277 if (!(cl = ngx_alloc_chain_link(ctx->pool))) {
278 return NGX_ERROR;
Igor Sysoevc83f6832004-06-24 07:53:37 +0000279 }
Igor Sysoevb1af9bb2004-06-25 14:42:03 +0000280
281 if (ctx->head) {
282 *ll = cl;
283
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +0000284 } else {
Igor Sysoevb1af9bb2004-06-25 14:42:03 +0000285 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;
Igor Sysoevc83f6832004-06-24 07:53:37 +0000293 }
294
Igor Sysoevb1af9bb2004-06-25 14:42:03 +0000295 ctx->last = b;
Igor Sysoevc83f6832004-06-24 07:53:37 +0000296
Igor Sysoevb1af9bb2004-06-25 14:42:03 +0000297 return NGX_OK;
Igor Sysoevc83f6832004-06-24 07:53:37 +0000298}
299
300
Igor Sysoevb1af9bb2004-06-25 14:42:03 +0000301static char *ngx_http_set_status(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
Igor Sysoevc83f6832004-06-24 07:53:37 +0000302{
Igor Sysoevc83f6832004-06-24 07:53:37 +0000303 ngx_http_core_loc_conf_t *clcf;
304
Igor Sysoev74a5ddb2004-07-18 19:11:20 +0000305 clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
Igor Sysoevc83f6832004-06-24 07:53:37 +0000306 clcf->handler = ngx_http_status_handler;
307
308 return NGX_CONF_OK;
309}