[njs] http internalRedirect() method.

Dmitry Volyntsev xeioex at nginx.com
Wed Jun 13 12:30:23 UTC 2018


details:   http://hg.nginx.org/njs/rev/c939541c37bc
branches:  
changeset: 535:c939541c37bc
user:      Dmitry Volyntsev <xeioex at nginx.com>
date:      Wed Jun 13 14:15:43 2018 +0300
description:
http internalRedirect() method.

Performs internal redirect to the specified uri.

req.internalRedirect(<uri>):
    uri - string. If uri starts with '@' it is considered as a
        named location.

diffstat:

 nginx/ngx_http_js_module.c |  92 +++++++++++++++++++++++++++++++++++++++++-----
 1 files changed, 82 insertions(+), 10 deletions(-)

diffs (158 lines):

diff -r bf3d32cc6716 -r c939541c37bc nginx/ngx_http_js_module.c
--- a/nginx/ngx_http_js_module.c	Wed Jun 13 14:11:58 2018 +0300
+++ b/nginx/ngx_http_js_module.c	Wed Jun 13 14:15:43 2018 +0300
@@ -31,6 +31,7 @@ typedef struct {
     ngx_uint_t           done;
     ngx_int_t            status;
     njs_opaque_value_t   request_body;
+    ngx_str_t            redirect_uri;
 } ngx_http_js_ctx_t;
 
 
@@ -51,6 +52,8 @@ typedef struct {
 static ngx_int_t ngx_http_js_content_handler(ngx_http_request_t *r);
 static void ngx_http_js_content_event_handler(ngx_http_request_t *r);
 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_variable(ngx_http_request_t *r,
     ngx_http_variable_value_t *v, uintptr_t data);
 static ngx_int_t ngx_http_js_init_vm(ngx_http_request_t *r);
@@ -89,6 +92,8 @@ static njs_ret_t ngx_http_js_ext_finish(
     nxt_uint_t nargs, njs_index_t unused);
 static njs_ret_t ngx_http_js_ext_return(njs_vm_t *vm, njs_value_t *args,
     nxt_uint_t nargs, njs_index_t unused);
+static njs_ret_t ngx_http_js_ext_internal_redirect(njs_vm_t *vm,
+    njs_value_t *args, nxt_uint_t nargs, njs_index_t unused);
 
 static njs_ret_t ngx_http_js_ext_log(njs_vm_t *vm, njs_value_t *args,
     nxt_uint_t nargs, njs_index_t unused);
@@ -589,6 +594,18 @@ static njs_external_t  ngx_http_js_ext_r
       NULL,
       ngx_http_js_ext_return,
       0 },
+
+    { nxt_string("internalRedirect"),
+      NJS_EXTERN_METHOD,
+      NULL,
+      0,
+      NULL,
+      NULL,
+      NULL,
+      NULL,
+      NULL,
+      ngx_http_js_ext_internal_redirect,
+      0 },
 };
 
 
@@ -683,8 +700,9 @@ ngx_http_js_content_event_handler(ngx_ht
     }
 
     /*
-     * status is expected to be overriden by finish() or return() methods,
-     * otherwise the content handler is considered invalid.
+     * status is expected to be overriden by finish(), return() or
+     * internalRedirect() methods, otherwise the content handler is
+     * considered invalid.
      */
 
     ctx->status = NGX_HTTP_INTERNAL_SERVER_ERROR;
@@ -704,10 +722,7 @@ ngx_http_js_content_event_handler(ngx_ht
         return;
     }
 
-    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
-                   "http js content rc: %i", ctx->status);
-
-    ngx_http_finalize_request(r, ctx->status);
+    ngx_http_js_content_finalize(r, ctx);
 }
 
 
@@ -725,10 +740,7 @@ ngx_http_js_content_write_event_handler(
     ctx = ngx_http_get_module_ctx(r, ngx_http_js_module);
 
     if (!njs_vm_pending(ctx->vm)) {
-        ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
-                       "http js content rc: %i", ctx->status);
-
-        ngx_http_finalize_request(r, ctx->status);
+        ngx_http_js_content_finalize(r, ctx);
         return;
     }
 
@@ -764,6 +776,28 @@ ngx_http_js_content_write_event_handler(
 }
 
 
+static void
+ngx_http_js_content_finalize(ngx_http_request_t *r, ngx_http_js_ctx_t *ctx)
+{
+    ngx_str_t  args;
+
+    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);
+
+        } else {
+            ngx_http_split_args(r, &ctx->redirect_uri, &args);
+            ngx_http_internal_redirect(r, &ctx->redirect_uri, &args);
+        }
+    }
+
+    ngx_http_finalize_request(r, ctx->status);
+}
+
+
 static ngx_int_t
 ngx_http_js_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v,
     uintptr_t data)
@@ -1391,6 +1425,44 @@ ngx_http_js_ext_return(njs_vm_t *vm, njs
 
 
 static njs_ret_t
+ngx_http_js_ext_internal_redirect(njs_vm_t *vm, njs_value_t *args,
+    nxt_uint_t nargs, njs_index_t unused)
+{
+    nxt_str_t            uri;
+    ngx_http_js_ctx_t   *ctx;
+    ngx_http_request_t  *r;
+
+    if (nargs < 2) {
+        njs_vm_error(vm, "too few arguments");
+        return NJS_ERROR;
+    }
+
+    r = njs_value_data(njs_argument(args, 0));
+
+    ctx = ngx_http_get_module_ctx(r, ngx_http_js_module);
+
+    if (njs_vm_value_to_ext_string(vm, &uri, njs_argument(args, 1), 0)
+        == NJS_ERROR)
+    {
+        njs_vm_error(vm, "failed to convert uri arg");
+        return NJS_ERROR;
+    }
+
+    if (uri.length == 0) {
+        njs_vm_error(vm, "uri is empty");
+        return NJS_ERROR;
+    }
+
+    ctx->redirect_uri.data = uri.start;
+    ctx->redirect_uri.len = uri.length;
+
+    ctx->status = NGX_DONE;
+
+    return NJS_OK;
+}
+
+
+static njs_ret_t
 ngx_http_js_ext_log(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
     njs_index_t unused)
 {


More information about the nginx-devel mailing list