static ngx_int_t ngx_http_internal_redirect_handler(ngx_http_request_t *r) { u_char *p; ngx_uint_t i; ngx_str_t uri, args; ngx_http_script_code_pt code; ngx_http_script_engine_t e; ngx_http_variable_value_t stack[10]; ngx_http_internal_redirect_entry_t *redirects; ngx_http_internal_redirect_main_conf_t *imcf; ngx_http_internal_redirect_loc_conf_t *ilcf; ngx_http_core_main_conf_t *cmcf; ngx_http_phase_handler_t *ph, *cur_ph, *last_ph, tmp; imcf = ngx_http_get_module_main_conf(r, ngx_http_internal_redirect_module); if (!imcf->postponed) { imcf->postponed = 1; cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module); ph = cmcf->phase_engine.handlers; cur_ph = &ph[r->phase_handler]; last_ph = &ph[cur_ph->next - 1]; if (cur_ph < last_ph) { tmp = *cur_ph; ngx_memmove(cur_ph, cur_ph + 1, (last_ph - cur_ph) * sizeof(ngx_http_phase_handler_t)); *last_ph = tmp; r->phase_handler--; /* redo the current ph */ return NGX_DECLINED; } } ilcf = ngx_http_get_module_loc_conf(r, ngx_http_internal_redirect_module); if (ilcf->redirects == NULL) { return NGX_DECLINED; } redirects = ilcf->redirects->elts; for (i = 0; i < ilcf->redirects->nelts; i++) { ngx_memzero(&e, sizeof(ngx_http_script_engine_t)); ngx_memzero(&stack, sizeof(stack)); e.sp = stack; e.ip = redirects[i].codes->elts; e.request = r; e.quote = 1; e.log = 1; e.status = NGX_DECLINED; while (*(uintptr_t *) e.ip) { code = *(ngx_http_script_code_pt *) e.ip; code(&e); } e.sp--; if (e.sp->len && (e.sp->len != 1 || e.sp->data[0] != '0')) { break; } } if (i == ilcf->redirects->nelts) { return NGX_DECLINED; } if (redirects[i].code) { return redirects[i].code; } if (redirects[i].lengths) { if (ngx_http_script_run(r, &uri, redirects[i].lengths->elts, 0, redirects->values->elts) == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } } else { uri = redirects[i].name; } if (uri.data[0] == '@') { (void) ngx_http_named_location(r, &uri); } else { if (uri.data[0] != '/') { p = ngx_pcalloc(r->pool, uri.len + 1); if (p == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } uri.len++; *p = '/'; ngx_memcpy(p + 1, uri.data, uri.len); uri.data = p; } ngx_http_split_args(r, &uri, &args); (void) ngx_http_internal_redirect(r, &uri, &args); } ngx_http_finalize_request(r, NGX_DONE); return NGX_DONE; }
static ngx_int_t ngx_http_send_error_page(ngx_http_request_t *r, ngx_http_err_page_t *err_page) { ngx_int_t overwrite; ngx_str_t uri, args; ngx_table_elt_t *location; ngx_http_core_loc_conf_t *clcf; overwrite = err_page->overwrite; if (overwrite && overwrite != NGX_HTTP_OK) { r->expect_tested = 1; } if (overwrite >= 0) { r->err_status = overwrite; } if (ngx_http_complex_value(r, &err_page->value, &uri) != NGX_OK) { return NGX_ERROR; } if (uri.len && uri.data[0] == '/') { if (err_page->value.lengths) { ngx_http_split_args(r, &uri, &args); } else { args = err_page->args; } if (r->method != NGX_HTTP_HEAD) { r->method = NGX_HTTP_GET; r->method_name = ngx_http_get_name; } return ngx_http_internal_redirect(r, &uri, &args); } if (uri.len && uri.data[0] == '@') { return ngx_http_named_location(r, &uri); } location = ngx_list_push(&r->headers_out.headers); if (location == NULL) { return NGX_ERROR; } if (overwrite != NGX_HTTP_MOVED_PERMANENTLY && overwrite != NGX_HTTP_MOVED_TEMPORARILY && overwrite != NGX_HTTP_SEE_OTHER && overwrite != NGX_HTTP_TEMPORARY_REDIRECT) { r->err_status = NGX_HTTP_MOVED_TEMPORARILY; } location->hash = 1; ngx_str_set(&location->key, "Location"); location->value = uri; ngx_http_clear_location(r); r->headers_out.location = location; clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); if (clcf->msie_refresh && r->headers_in.msie) { return ngx_http_send_refresh(r); } return ngx_http_send_special_response(r, clcf, r->err_status - NGX_HTTP_MOVED_PERMANENTLY + NGX_HTTP_OFF_3XX); }
static ngx_int_t ngx_http_send_error_page(ngx_http_request_t *r, ngx_http_err_page_t *err_page) { ngx_int_t overwrite; ngx_str_t uri, args; ngx_table_elt_t *location; ngx_http_core_loc_conf_t *clcf; overwrite = err_page->overwrite; if (overwrite && overwrite != NGX_HTTP_OK) { r->expect_tested = 1; } r->err_status = overwrite; r->zero_in_uri = 0; if (ngx_http_complex_value(r, &err_page->value, &uri) != NGX_OK) { return NGX_ERROR; } if (uri.data[0] == '/') { if (err_page->value.lengths) { ngx_http_split_args(r, &uri, &args); } else { args = err_page->args; } if (r->method != NGX_HTTP_HEAD) { r->method = NGX_HTTP_GET; r->method_name = ngx_http_get_name; } return ngx_http_internal_redirect(r, &uri, &args); } if (uri.data[0] == '@') { return ngx_http_named_location(r, &uri); } location = ngx_list_push(&r->headers_out.headers); if (location == NULL) { return NGX_ERROR; } r->err_status = NGX_HTTP_MOVED_TEMPORARILY; location->hash = 1; location->key.len = sizeof("Location") - 1; location->key.data = (u_char *) "Location"; location->value = uri; r->headers_out.location = location; clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); if (clcf->msie_refresh && r->headers_in.msie) { return ngx_http_send_refresh(r); } return ngx_http_send_special_response(r, clcf, NGX_HTTP_MOVED_TEMPORARILY - NGX_HTTP_MOVED_PERMANENTLY + NGX_HTTP_LEVEL_200); }