Nginx-ru mailing list archive (nginx-ru@sysoev.ru)
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Fwd: nginx FR: fcgi error handling
- To: nginx-ru@xxxxxxxxx
- Subject: Fwd: nginx FR: fcgi error handling
- From: "Nick S. Grechukh" <gns@xxxxxxxxxxx>
- Date: Fri, 13 Apr 2007 15:08:50 +0200
- Dkim-signature: a=rsa-sha1; c=relaxed/relaxed; d=gmail.com; s=beta; h=domainkey-signature:received:received:message-id:date:from:sender:to:subject:in-reply-to:mime-version:content-type:references:x-google-sender-auth; b=h/MBbMWwz19coQfZJhLz/NVc3iz2qB0GbZOxYKn8JxNfUVeTx4FLcCBu7qFRz2STjcFKZLWbGOKe+zDI6YIKuw41VLwh23t7DHu8Edb+VRQp9AF0LYJieQX2RY/+iivdSdnJUQ0TUvz0iFv7B3gzXn1s+5U3/AagE5OZa/B+o2U=
- Domainkey-signature: a=rsa-sha1; c=nofws; d=gmail.com; s=beta; h=received:message-id:date:from:sender:to:subject:in-reply-to:mime-version:content-type:references:x-google-sender-auth; b=XGMiYWcSrNR06u27Hrp9Ls8VVB1nxNo9utKkh7Z9+wfHirU1sboIolzxaCSjcAJtJZActIIvzhHpC0cx8+Pf+xCQF/nu4OWS2eQB5/7/CMxTXz2rhzQqr8GYimvi/NkZb75g3Vlm8KK0/sQmvA9kB3ZQc1Wq9dmOYE65M2U9Hmg=
- In-reply-to: <a4ab440f0704121024t7b81febg96a46926163981f5@xxxxxxxxxxxxxx>
- References: <a4ab440f0704121024t7b81febg96a46926163981f5@xxxxxxxxxxxxxx>
---------- Forwarded message ----------
From: "Nick S. Grechukh" <gns@>
Date: Thu, 12 Apr 2007 20:24:14 +0300
Subject: nginx FR: fcgi error handling
To: mithraen@
предлагаю патчик для fastcgi модуля nginx, решающий следующую проблему:
Перехватить и обработать php fatal error средствами PHP в случае
фатальной ошибки невозможно - php уже умер, успев выдать сообщение в
stderr. в результате пользователь получает пустую страницу (или при
display_errors=on - сообщение от php), однако с кодом 200.
Во многих случаях это неприемлемо; под апачем mod_php выдает 500
Internal server error, что гораздо лучше. Насколько мне известно,
штатными средствами добиться от fastcgi+anywebserver поведения,
аналогичного модулю апача невозможно (intercept_errors здесь совсем ни
при чем).
Предлагается отлавливать эти ситуации анализируя stderr от fastcgi;
для этого введена директива fastcgi_catch_stderr, в которой можно
указать, какие строки в stderr следует обрабатывать как internal
server error. Мы используем fastcgi_catch_stderr "PHP Fatal error:",
но в принципе я постарался сделать не-пхп-специфичное решение.
Проблему я вижу только одну - если контент формируется постепенно и
часть ответа уже попала клиенту, выставить код ошибки невозможно. Но
это понятно, с этим в любом случае ничего не сделаешь кроме полного
кэширования ответов fcgi (эксперименты показали, что в буфере nginx
помещается кусок до 4килобайт). А во-вторых, часто ответ кэшируется на
стороне php и в самом конце работы скрипта выдается целиком.
с уважением,
Nick S. Grechukh
diff -Naur nginx-0.5.14/src/http/modules/ngx_http_fastcgi_module.c
nginx-0.5.14.gns/src/http/modules/ngx_http_fastcgi_module.c
--- nginx-0.5.14/src/http/modules/ngx_http_fastcgi_module.c 2007-03-18
13:13:33 +0200
+++ nginx-0.5.14.gns/src/http/modules/ngx_http_fastcgi_module.c 2007-04-12
17:03:25 +0300
@@ -19,6 +19,7 @@
ngx_array_t *params_len;
ngx_array_t *params;
ngx_array_t *params_source;
+ ngx_array_t *catch_stderr;
} ngx_http_fastcgi_loc_conf_t;
@@ -345,6 +346,13 @@
offsetof(ngx_http_fastcgi_loc_conf_t, upstream.hide_headers),
NULL },
+ { ngx_string("fastcgi_catch_stderr"),
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
+ ngx_conf_set_str_array_slot,
+ NGX_HTTP_LOC_CONF_OFFSET,
+ offsetof(ngx_http_fastcgi_loc_conf_t, catch_stderr),
+ NULL },
+
ngx_null_command
};
@@ -835,16 +843,18 @@
u_char *start, *last;
ngx_str_t *status_line, line;
ngx_int_t rc, status;
- ngx_uint_t i;
+ ngx_uint_t i,j;
ngx_table_elt_t *h;
ngx_http_upstream_t *u;
ngx_http_fastcgi_ctx_t *f;
ngx_http_upstream_header_t *hh;
ngx_http_upstream_main_conf_t *umcf;
+ ngx_http_fastcgi_loc_conf_t *flcf;
f = ngx_http_get_module_ctx(r, ngx_http_fastcgi_module);
umcf = ngx_http_get_module_main_conf(r, ngx_http_upstream_module);
+ flcf = ngx_http_get_module_loc_conf(r, ngx_http_fastcgi_module);
if (f == NULL) {
f = ngx_pcalloc(r->pool, sizeof(ngx_http_fastcgi_ctx_t));
@@ -948,6 +958,13 @@
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
"FastCGI sent in stderr: \"%V\"", &line);
+ ngx_str_t* catch_them = flcf->catch_stderr->elts;
+ for (j = 0; j < flcf->catch_stderr->nelts; j++) {
+ if (ngx_strstr(line.data,catch_them[j].data)) {
+ return NGX_HTTP_INTERNAL_SERVER_ERROR;
+ }
+ }
+
if (u->buffer.pos == u->buffer.last) {
if (!f->fastcgi_stdout) {
|