Re: расширение return
Igor Sysoev
igor на sysoev.ru
Пт Июн 18 14:05:17 MSD 2010
On Thu, Jun 17, 2010 at 02:20:52PM +0400, Igor Sysoev wrote:
> On Thu, Jun 17, 2010 at 02:15:22PM +0400, Igor Sysoev wrote:
>
> > On Thu, Jun 17, 2010 at 11:07:12AM +0100, Valery Kholodkov wrote:
> >
> > > О, можно будет сделать более универсальный eval:
> > >
> > > eval $a {
> > > return 200 "blah";
> > > }
> >
> > А какая семантика ?
> >
> > Вообще-то я не хочу ничего добавлять в этот мерзкий rewrite модуль,
> > но return мне нравится. Да и понадобилось по работе.
>
> Я бы ещё сделал
>
> location /old/ {
> location ~ ^/old(.+)$ {
> return http://site.com$1;
> }
>
> или
>
> location /old/ {
> location ~ ^/old(.+)$ {
> return 301 http://site.com$1;
> }
>
> Вот такую личную неприязнь я испытываю к rewrite, что кушать не могу!
Итак, патч. Варианты использования:
# старые
return 204;
return 404;
return 500;
# новые
return 200;
return 200 "OK\n";
return 404 "not found\n"; # не перехватывается error_page
return 301 http://site.ru$request_uri;
return 302 http://site.ru$request_uri;
return 303 http://site.ru$request_uri;
return http://site.ru$request_uri; # по умолчанию 302
return https://site.ru$request_uri; # по умолчанию 302
return $scheme://site.ru$request_uri; # по умолчанию 302
--
Игорь Сысоев
http://sysoev.ru
-------------- next part --------------
Index: src/http/ngx_http_core_module.c
===================================================================
--- src/http/ngx_http_core_module.c (revision 2950)
+++ src/http/ngx_http_core_module.c (working copy)
@@ -865,7 +865,7 @@
/*
* generic phase checker,
- * used by the post read, server rewrite, rewrite, and pre-access phases
+ * used by the post read and pre-access phases
*/
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
@@ -896,6 +896,29 @@
ngx_int_t
+ngx_http_core_rewrite_phase(ngx_http_request_t *r, ngx_http_phase_handler_t *ph)
+{
+ ngx_int_t rc;
+
+ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+ "rewrite phase: %ui", r->phase_handler);
+
+ rc = ph->handler(r);
+
+ if (rc == NGX_DECLINED) {
+ r->phase_handler++;
+ return NGX_AGAIN;
+ }
+
+ /* rc == NGX_OK || rc == NGX_ERROR || rc == NGX_HTTP_... */
+
+ ngx_http_finalize_request(r, rc);
+
+ return NGX_OK;
+}
+
+
+ngx_int_t
ngx_http_core_find_config_phase(ngx_http_request_t *r,
ngx_http_phase_handler_t *ph)
{
@@ -1709,6 +1732,79 @@
ngx_int_t
+ngx_http_send_response(ngx_http_request_t *r, ngx_uint_t status,
+ ngx_str_t *ct, ngx_http_complex_value_t *cv)
+{
+ ngx_int_t rc;
+ ngx_str_t val;
+ ngx_buf_t *b;
+ ngx_chain_t out;
+
+ r->headers_out.status = status;
+
+ if (status == NGX_HTTP_NO_CONTENT) {
+ return ngx_http_send_header(r);
+ }
+
+ if (ngx_http_complex_value(r, cv, &val) != NGX_OK) {
+ return NGX_HTTP_INTERNAL_SERVER_ERROR;
+ }
+
+ if (status >= NGX_HTTP_MOVED_PERMANENTLY && status <= NGX_HTTP_SEE_OTHER) {
+
+ r->headers_out.location = ngx_list_push(&r->headers_out.headers);
+ if (r->headers_out.location == NULL) {
+ return NGX_HTTP_INTERNAL_SERVER_ERROR;
+ }
+
+ r->headers_out.location->hash = 1;
+ ngx_str_set(&r->headers_out.location->key, "Location");
+ r->headers_out.location->value = val;
+
+ return status;
+ }
+
+ r->headers_out.content_length_n = val.len;
+
+ if (ct) {
+ r->headers_out.content_type_len = ct->len;
+ r->headers_out.content_type = *ct;
+
+ } else {
+ if (ngx_http_set_content_type(r) != NGX_OK) {
+ return NGX_HTTP_INTERNAL_SERVER_ERROR;
+ }
+ }
+
+ if (r->method == NGX_HTTP_HEAD) {
+ return ngx_http_send_header(r);
+ }
+
+ b = ngx_pcalloc(r->pool, sizeof(ngx_buf_t));
+ if (b == NULL) {
+ return NGX_HTTP_INTERNAL_SERVER_ERROR;
+ }
+
+ b->pos = val.data;
+ b->last = val.data + val.len;
+ b->memory = val.len ? 1 : 0;
+ b->last_buf = (r == r->main) ? 1: 0;
+ b->last_in_chain = 1;
+
+ out.buf = b;
+ out.next = NULL;
+
+ rc = ngx_http_send_header(r);
+
+ if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) {
+ return rc;
+ }
+
+ return ngx_http_output_filter(r, &out);
+}
+
+
+ngx_int_t
ngx_http_send_header(ngx_http_request_t *r)
{
if (r->err_status) {
Index: src/http/ngx_http_request.h
===================================================================
--- src/http/ngx_http_request.h (revision 2950)
+++ src/http/ngx_http_request.h (working copy)
@@ -72,6 +72,7 @@
#define NGX_HTTP_SPECIAL_RESPONSE 300
#define NGX_HTTP_MOVED_PERMANENTLY 301
#define NGX_HTTP_MOVED_TEMPORARILY 302
+#define NGX_HTTP_SEE_OTHER 303
#define NGX_HTTP_NOT_MODIFIED 304
#define NGX_HTTP_BAD_REQUEST 400
Index: src/http/ngx_http_special_response.c
===================================================================
--- src/http/ngx_http_special_response.c (revision 2950)
+++ src/http/ngx_http_special_response.c (working copy)
@@ -65,6 +65,14 @@
;
+static char ngx_http_error_303_page[] =
+"<html>" CRLF
+"<head><title>303 See Other</title></head>" CRLF
+"<body bgcolor=\"white\">" CRLF
+"<center><h1>303 See Other</h1></center>" CRLF
+;
+
+
static char ngx_http_error_400_page[] =
"<html>" CRLF
"<head><title>400 Bad Request</title></head>" CRLF
@@ -281,7 +289,7 @@
/* ngx_null_string, */ /* 300 */
ngx_string(ngx_http_error_301_page),
ngx_string(ngx_http_error_302_page),
- ngx_null_string, /* 303 */
+ ngx_string(ngx_http_error_303_page),
#define NGX_HTTP_LAST_LEVEL_300 304
#define NGX_HTTP_LEVEL_300 (NGX_HTTP_LAST_LEVEL_300 - 301)
Index: src/http/ngx_http_header_filter_module.c
===================================================================
--- src/http/ngx_http_header_filter_module.c (revision 2950)
+++ src/http/ngx_http_header_filter_module.c (working copy)
@@ -68,7 +68,7 @@
ngx_string("301 Moved Permanently"),
ngx_string("302 Moved Temporarily"),
- ngx_null_string, /* "303 See Other" */
+ ngx_string("303 See Other"),
ngx_string("304 Not Modified"),
/* ngx_null_string, */ /* "305 Use Proxy" */
Index: src/http/ngx_http_core_module.h
===================================================================
--- src/http/ngx_http_core_module.h (revision 2950)
+++ src/http/ngx_http_core_module.h (working copy)
@@ -429,6 +429,8 @@
void ngx_http_core_run_phases(ngx_http_request_t *r);
ngx_int_t ngx_http_core_generic_phase(ngx_http_request_t *r,
ngx_http_phase_handler_t *ph);
+ngx_int_t ngx_http_core_rewrite_phase(ngx_http_request_t *r,
+ ngx_http_phase_handler_t *ph);
ngx_int_t ngx_http_core_find_config_phase(ngx_http_request_t *r,
ngx_http_phase_handler_t *ph);
ngx_int_t ngx_http_core_post_rewrite_phase(ngx_http_request_t *r,
@@ -446,6 +448,8 @@
void *ngx_http_test_content_type(ngx_http_request_t *r, ngx_hash_t *types_hash);
ngx_int_t ngx_http_set_content_type(ngx_http_request_t *r);
void ngx_http_set_exten(ngx_http_request_t *r);
+ngx_int_t ngx_http_send_response(ngx_http_request_t *r, ngx_uint_t status,
+ ngx_str_t *ct, ngx_http_complex_value_t *cv);
u_char *ngx_http_map_uri_to_path(ngx_http_request_t *r, ngx_str_t *name,
size_t *root_length, size_t reserved);
ngx_int_t ngx_http_auth_basic_user(ngx_http_request_t *r);
Index: src/http/ngx_http_script.c
===================================================================
--- src/http/ngx_http_script.c (revision 2950)
+++ src/http/ngx_http_script.c (working copy)
@@ -1254,14 +1254,17 @@
code = (ngx_http_script_return_code_t *) e->ip;
- e->status = code->status;
-
- if (code->status == NGX_HTTP_NO_CONTENT) {
- e->request->header_only = 1;
- e->request->zero_body = 1;
+ if (code->status < NGX_HTTP_BAD_REQUEST
+ || code->text.value.len
+ || code->text.lengths)
+ {
+ e->status = ngx_http_send_response(e->request, code->status, NULL,
+ &code->text);
+ } else {
+ e->status = code->status;
}
- e->ip += sizeof(ngx_http_script_return_code_t) - sizeof(uintptr_t);
+ e->ip = ngx_http_script_exit;
}
Index: src/http/ngx_http_script.h
===================================================================
--- src/http/ngx_http_script.h (revision 2950)
+++ src/http/ngx_http_script.h (working copy)
@@ -159,7 +159,7 @@
typedef struct {
ngx_http_script_code_pt code;
uintptr_t status;
- uintptr_t null;
+ ngx_http_complex_value_t text;
} ngx_http_script_return_code_t;
Index: src/http/modules/ngx_http_rewrite_module.c
===================================================================
--- src/http/modules/ngx_http_rewrite_module.c (revision 2950)
+++ src/http/modules/ngx_http_rewrite_module.c (working copy)
@@ -52,7 +52,7 @@
{ ngx_string("return"),
NGX_HTTP_SRV_CONF|NGX_HTTP_SIF_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF
- |NGX_CONF_TAKE1,
+ |NGX_CONF_TAKE12,
ngx_http_rewrite_return,
NGX_HTTP_LOC_CONF_OFFSET,
0,
@@ -433,8 +433,10 @@
{
ngx_http_rewrite_loc_conf_t *lcf = conf;
- ngx_str_t *value;
- ngx_http_script_return_code_t *ret;
+ u_char *p;
+ ngx_str_t *value, *v;
+ ngx_http_script_return_code_t *ret;
+ ngx_http_compile_complex_value_t ccv;
ret = ngx_http_script_start_code(cf->pool, &lcf->codes,
sizeof(ngx_http_script_return_code_t));
@@ -444,12 +446,46 @@
value = cf->args->elts;
+ ngx_memzero(ret, sizeof(ngx_http_script_return_code_t));
+
ret->code = ngx_http_script_return_code;
- ret->null = (uintptr_t) NULL;
- ret->status = ngx_atoi(value[1].data, value[1].len);
+ p = value[1].data;
+ ret->status = ngx_atoi(p, value[1].len);
+
if (ret->status == (uintptr_t) NGX_ERROR) {
+
+ if (cf->args->nelts == 2
+ && (ngx_strncmp(p, "http://", sizeof("http://") - 1) == 0
+ || ngx_strncmp(p, "https://", sizeof("https://") - 1) == 0
+ || ngx_strncmp(p, "$scheme", sizeof("$scheme") - 1) == 0))
+ {
+ ret->status = NGX_HTTP_MOVED_TEMPORARILY;
+ v = &value[1];
+
+ } else {
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+ "invalid return code \"%V\"", &value[1]);
+ return NGX_CONF_ERROR;
+ }
+
+ } else {
+
+ if (cf->args->nelts == 2) {
+ return NGX_CONF_OK;
+ }
+
+ v = &value[2];
+ }
+
+ ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
+
+ ccv.cf = cf;
+ ccv.value = v;
+ ccv.complex_value = &ret->text;
+
+ if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
return NGX_CONF_ERROR;
}
Index: src/http/ngx_http.c
===================================================================
--- src/http/ngx_http.c (revision 2950)
+++ src/http/ngx_http.c (working copy)
@@ -509,7 +509,7 @@
if (cmcf->phase_engine.server_rewrite_index == (ngx_uint_t) -1) {
cmcf->phase_engine.server_rewrite_index = n;
}
- checker = ngx_http_core_generic_phase;
+ checker = ngx_http_core_rewrite_phase;
break;
@@ -526,7 +526,7 @@
if (cmcf->phase_engine.location_rewrite_index == (ngx_uint_t) -1) {
cmcf->phase_engine.location_rewrite_index = n;
}
- checker = ngx_http_core_generic_phase;
+ checker = ngx_http_core_rewrite_phase;
break;
Подробная информация о списке рассылки nginx-ru