static void ngx_http_js_content_write_event_handler(ngx_http_request_t *r);
static void ngx_http_js_content_finalize(ngx_http_request_t *r,
ngx_http_js_ctx_t *ctx);
+static ngx_int_t ngx_http_js_internal_redirect(ngx_http_request_t *r,
+ ngx_http_js_ctx_t *ctx);
static ngx_int_t ngx_http_js_header_filter(ngx_http_request_t *r);
static ngx_int_t ngx_http_js_variable_set(ngx_http_request_t *r,
ngx_http_variable_value_t *v, uintptr_t data);
static ngx_int_t
ngx_http_js_access_finalize(ngx_http_request_t *r, ngx_http_js_ctx_t *ctx)
{
+ ngx_int_t rc;
+
+ if (ctx->redirect_uri.len) {
+ rc = ngx_http_js_internal_redirect(r, ctx);
+ ngx_http_finalize_request(r, rc);
+ return NGX_DONE;
+ }
+
if (r->header_sent) {
ngx_http_finalize_request(r, NGX_OK);
return NGX_DONE;
static void
ngx_http_js_content_finalize(ngx_http_request_t *r, ngx_http_js_ctx_t *ctx)
{
- ngx_str_t args;
- ngx_int_t rc;
- ngx_uint_t flags;
+ ngx_int_t rc;
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"http js content rc: %i", ctx->status);
if (ctx->redirect_uri.len) {
- if (ctx->redirect_uri.data[0] == '@') {
- ngx_http_named_location(r, &ctx->redirect_uri);
+ rc = ngx_http_js_internal_redirect(r, ctx);
+ ngx_http_finalize_request(r, rc);
+ return;
+ }
- } else {
- ngx_str_null(&args);
- flags = NGX_HTTP_LOG_UNSAFE;
+ ngx_http_finalize_request(r, ctx->status);
+}
- rc = ngx_http_parse_unsafe_uri(r, &ctx->redirect_uri, &args,
- &flags);
- if (rc != NGX_OK) {
- ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
- return;
- }
- ngx_http_internal_redirect(r, &ctx->redirect_uri, &args);
- }
+static ngx_int_t
+ngx_http_js_internal_redirect(ngx_http_request_t *r, ngx_http_js_ctx_t *ctx)
+{
+ ngx_str_t args;
+ ngx_int_t rc;
+ ngx_uint_t flags;
+
+ if (r->header_sent) {
+ ngx_log_error(NGX_LOG_WARN, r->connection->log, 0,
+ "ignored internalRedirect() because headers were "
+ "already sent");
+ return NGX_OK;
}
- ngx_http_finalize_request(r, ctx->status);
+ if (ctx->redirect_uri.data[0] == '@') {
+ return ngx_http_named_location(r, &ctx->redirect_uri);
+ }
+
+ ngx_str_null(&args);
+ flags = NGX_HTTP_LOG_UNSAFE;
+
+ rc = ngx_http_parse_unsafe_uri(r, &ctx->redirect_uri, &args, &flags);
+ if (rc != NGX_OK) {
+ return NGX_HTTP_INTERNAL_SERVER_ERROR;
+ }
+
+ return ngx_http_internal_redirect(r, &ctx->redirect_uri, &args);
}
js_content test.content;
}
+ location /access_internal_redirect {
+ js_access test.access_internal_redirect;
+ js_content test.content;
+ }
+
+ location /access_internal_redirect_async {
+ js_access test.access_internal_redirect_async;
+ js_content test.content;
+ }
+
+ location /access_internal_redirect_named {
+ js_access test.access_internal_redirect_named;
+ js_content test.content;
+ }
+
+ location /internal_redirect_dest {
+ return 200 "internal_redirect";
+ }
+
+ location @internal_redirect_named {
+ return 200 "internal_redirect_named";
+ }
+
location /callback {
js_content test.content;
}
r.return(302, 'http://127.0.0.1:$p0/callback');
}
+ function access_internal_redirect(r) {
+ r.internalRedirect('/internal_redirect_dest');
+ }
+
+ async function access_internal_redirect_async(r) {
+ await new Promise(resolve => setTimeout(resolve, 5));
+ r.internalRedirect('/internal_redirect_dest');
+ }
+
+ function access_internal_redirect_named(r) {
+ r.internalRedirect('\@internal_redirect_named');
+ }
+
export default { content, deny, deny_body, exception, noop, override,
decline, content_only, async_timeout, async_deny,
async_deny_body, access_return_200,
async_exception, sr_skip, sr, fetch, route,
- auth_check, redirect, redirect_async };
+ auth_check, redirect, redirect_async,
+ access_internal_redirect,
+ access_internal_redirect_async,
+ access_internal_redirect_named };
EOF
$t->write_file_expand('no_import.conf', bad_conf(
location => 'js_access test.noop;'));
-$t->try_run('no js_access')->plan(33);
+$t->try_run('no js_access')->plan(36);
###############################################################################
'js_access async redirect');
like(http_get('/redirect_async'), qr!Location: http://127.0.0.1:$p0/callback!,
'js_access async redirect Location header');
+like(http_get('/access_internal_redirect'), qr/internal_redirect/,
+ 'js_access internalRedirect');
+like(http_get('/access_internal_redirect_async'), qr/internal_redirect/,
+ 'async js_access internalRedirect');
+like(http_get('/access_internal_redirect_named'), qr/internal_redirect_named/,
+ 'js_access internalRedirect to named location');
my ($rc, $out) = nginx_test_conf($t, 'duplicate.conf');