[PATCH] SSI: Implement #fsize SSI command

Matwey V. Kornilov matwey.kornilov at gmail.com
Sat Jan 28 11:08:29 UTC 2017


# HG changeset patch
# User Matwey V. Kornilov <matwey.kornilov at gmail.com>
# Date 1485600652 -10800
#      Sat Jan 28 13:50:52 2017 +0300
# Branch fsize
# Node ID f3bb0258beb24b975b94966a94d45e9a9f5c3c39
# Parent  640f035293959b2d4b0ba5939d954bc517f57f77
SSI: Implement #fsize SSI command

diff -r 640f03529395 -r f3bb0258beb2 src/http/modules/ngx_http_ssi_filter_module.c
--- a/src/http/modules/ngx_http_ssi_filter_module.c	Fri Jan 27 19:06:35 2017 +0300
+++ b/src/http/modules/ngx_http_ssi_filter_module.c	Sat Jan 28 13:50:52 2017 +0300
@@ -89,6 +89,10 @@
     ngx_int_t rc);
 static ngx_int_t ngx_http_ssi_set_variable(ngx_http_request_t *r, void *data,
     ngx_int_t rc);
+static ngx_int_t ngx_http_ssi_fsize(ngx_http_request_t *r,
+    ngx_http_ssi_ctx_t *ctx, ngx_str_t **params);
+static ngx_int_t ngx_http_ssi_fsize_output(ngx_http_request_t *r, void *data,
+    ngx_int_t rc);
 static ngx_int_t ngx_http_ssi_echo(ngx_http_request_t *r,
     ngx_http_ssi_ctx_t *ctx, ngx_str_t **params);
 static ngx_int_t ngx_http_ssi_config(ngx_http_request_t *r,
@@ -211,6 +215,7 @@
 
 
 static u_char ngx_http_ssi_string[] = "<!--";
+static u_char ngx_http_ssi_si_prefix[] = " kMGTPEZY";
 
 static ngx_str_t ngx_http_ssi_none = ngx_string("(none)");
 static ngx_str_t ngx_http_ssi_timefmt = ngx_string("%A, %d-%b-%Y %H:%M:%S %Z");
@@ -223,12 +228,16 @@
 #define  NGX_HTTP_SSI_INCLUDE_SET      3
 #define  NGX_HTTP_SSI_INCLUDE_STUB     4
 
+#define  NGX_HTTP_SSI_FSIZE_VIRTUAL    0
+#define  NGX_HTTP_SSI_FSIZE_FILE       1
+
 #define  NGX_HTTP_SSI_ECHO_VAR         0
 #define  NGX_HTTP_SSI_ECHO_DEFAULT     1
 #define  NGX_HTTP_SSI_ECHO_ENCODING    2
 
 #define  NGX_HTTP_SSI_CONFIG_ERRMSG    0
 #define  NGX_HTTP_SSI_CONFIG_TIMEFMT   1
+#define  NGX_HTTP_SSI_CONFIG_SIZEFMT   2
 
 #define  NGX_HTTP_SSI_SET_VAR          0
 #define  NGX_HTTP_SSI_SET_VALUE        1
@@ -248,6 +257,13 @@
 };
 
 
+static ngx_http_ssi_param_t  ngx_http_ssi_fsize_params[] = {
+    { ngx_string("virtual"), NGX_HTTP_SSI_FSIZE_VIRTUAL, 0, 0 },
+    { ngx_string("file"), NGX_HTTP_SSI_FSIZE_FILE, 0, 0 },
+    { ngx_null_string, 0, 0, 0 }
+};
+
+
 static ngx_http_ssi_param_t  ngx_http_ssi_echo_params[] = {
     { ngx_string("var"), NGX_HTTP_SSI_ECHO_VAR, 1, 0 },
     { ngx_string("default"), NGX_HTTP_SSI_ECHO_DEFAULT, 0, 0 },
@@ -259,6 +275,7 @@
 static ngx_http_ssi_param_t  ngx_http_ssi_config_params[] = {
     { ngx_string("errmsg"), NGX_HTTP_SSI_CONFIG_ERRMSG, 0, 0 },
     { ngx_string("timefmt"), NGX_HTTP_SSI_CONFIG_TIMEFMT, 0, 0 },
+    { ngx_string("sizefmt"), NGX_HTTP_SSI_CONFIG_SIZEFMT, 0, 0 },
     { ngx_null_string, 0, 0, 0 }
 };
 
@@ -290,6 +307,8 @@
 static ngx_http_ssi_command_t  ngx_http_ssi_commands[] = {
     { ngx_string("include"), ngx_http_ssi_include,
                        ngx_http_ssi_include_params, 0, 0, 1 },
+    { ngx_string("fsize"), ngx_http_ssi_fsize,
+                       ngx_http_ssi_fsize_params, 0, 0, 1 },
     { ngx_string("echo"), ngx_http_ssi_echo,
                        ngx_http_ssi_echo_params, 0, 0, 0 },
     { ngx_string("config"), ngx_http_ssi_config,
@@ -2239,6 +2258,116 @@
     return rc;
 }
 
+static ngx_int_t ngx_http_ssi_fsize(ngx_http_request_t *r,
+    ngx_http_ssi_ctx_t *ctx, ngx_str_t **params)
+{
+    ngx_int_t                    rc;
+    ngx_str_t                   *uri, *file, args;
+    ngx_uint_t                   flags;
+    ngx_http_request_t          *sr;
+    ngx_http_post_subrequest_t  *psr;
+
+    uri = params[NGX_HTTP_SSI_FSIZE_VIRTUAL];
+    file = params[NGX_HTTP_SSI_FSIZE_FILE];
+
+    if (uri && file) {
+        ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
+                      "fsize may be either virtual=\"%V\" or file=\"%V\"",
+                      uri, file);
+        return NGX_HTTP_SSI_ERROR;
+    }
+
+    if (uri == NULL && file == NULL) {
+        ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
+                      "no parameter in \"fsize\" SSI command");
+        return NGX_HTTP_SSI_ERROR;
+    }
+
+    if (uri == NULL) {
+        uri = file;
+    }
+
+    rc = ngx_http_ssi_evaluate_string(r, ctx, uri, NGX_HTTP_SSI_ADD_PREFIX);
+
+    if (rc != NGX_OK) {
+        return rc;
+    }
+
+    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+                   "ssi fsize: \"%V\"", uri);
+
+    ngx_str_null(&args);
+    flags = NGX_HTTP_LOG_UNSAFE;
+
+    if (ngx_http_parse_unsafe_uri(r, uri, &args, &flags) != NGX_OK) {
+        return NGX_HTTP_SSI_ERROR;
+    }
+
+    psr = ngx_palloc(r->pool, sizeof(ngx_http_post_subrequest_t));
+    if (psr == NULL) {
+        return NGX_ERROR;
+    }
+
+    psr->handler = ngx_http_ssi_fsize_output;
+    psr->data = ctx;
+
+    if (ngx_http_subrequest(r, uri, &args, &sr, psr, flags) != NGX_OK) {
+        return NGX_HTTP_SSI_ERROR;
+    }
+    sr->header_only = 1;
+
+    return NGX_OK;
+}
+
+
+static ngx_int_t ngx_http_ssi_fsize_output(ngx_http_request_t *r, void *data,
+    ngx_int_t rc)
+{
+    ngx_chain_t        *out;
+    ngx_buf_t          *b;
+    u_char             *p;
+    size_t              len, i;
+    ngx_http_ssi_ctx_t *ctx;
+    unsigned            sizefmt_bytes;
+
+    ctx = data;
+    sizefmt_bytes = (ctx ? ctx->sizefmt_bytes : 0);
+
+    p = ngx_pnalloc(r->pool, NGX_OFF_T_LEN + 1);
+    if (p == NULL) {
+        return NGX_ERROR;
+    }
+
+    len = ngx_sprintf(p, "%O", r->headers_out.content_length_n) -  p;
+
+    if (!sizefmt_bytes) {
+        i = len / 3;
+        len = len % 3;
+
+        p[len] = ngx_http_ssi_si_prefix[i];
+        len++;
+    }
+
+    b = ngx_calloc_buf(r->pool);
+    if (b == NULL) {
+        return NGX_ERROR;
+    }
+
+    b->memory = 1;
+    b->pos = p;
+    b->last = p + len;
+
+    out= ngx_alloc_chain_link(r->pool);
+    if (out == NULL) {
+        return NGX_ERROR;
+    }
+
+    out->buf = b;
+    out->next = NULL;
+
+    return ngx_http_output_filter(r, out);
+}
+
 
 static ngx_int_t
 ngx_http_ssi_echo(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx,
@@ -2400,6 +2529,22 @@
         ctx->errmsg = *value;
     }
 
+    value = params[NGX_HTTP_SSI_CONFIG_SIZEFMT];
+
+    if (value) {
+       if (value->len == 5
+           && ngx_strncasecmp(value->data, (u_char*)"bytes", 5) == 0) {
+           ctx->sizefmt_bytes = 1;
+       } else if (value->len == 6
+                  && ngx_strncasecmp(value->data, (u_char*)"abbrev", 6) == 0) {
+           ctx->sizefmt_bytes = 0;
+       } else {
+           ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
+                      "#config sizefmt may be either \"bytes\" or \"abbrev\"");
+           return NGX_HTTP_SSI_ERROR;
+       }
+    }
+
     return NGX_OK;
 }
 
diff -r 640f03529395 -r f3bb0258beb2 src/http/modules/ngx_http_ssi_filter_module.h
--- a/src/http/modules/ngx_http_ssi_filter_module.h	Fri Jan 27 19:06:35 2017 +0300
+++ b/src/http/modules/ngx_http_ssi_filter_module.h	Sat Jan 28 13:50:52 2017 +0300
@@ -76,6 +76,7 @@
     unsigned                  block:1;
     unsigned                  output:1;
     unsigned                  output_chosen:1;
+    unsigned                  sizefmt_bytes:1;
 
     ngx_http_request_t       *wait;
     void                     *value_buf;


More information about the nginx-devel mailing list