[PATCH] - flastmod SSI command

Rastislav Stanik nginx at rastos.org
Wed Sep 21 18:55:33 UTC 2016


Hi.

I'm new here and I subscribed because recently I wanted to switch
some little personal web server from apache to nginx and found
out that "flastmod" SSI command is not supported by nginx.
This command is supported by Apache
http://httpd.apache.org/docs/current/mod/mod_include.html#element.flastmod
as well as IIS
https://msdn.microsoft.com/en-us/library/ms525105%28v=vs.90%29.aspx

So I tried to implement that. The patch/changeset is in the attachment.
I would appreciate any feedback which would help to get that eventually
included in official nginx code.
--
	bye
		rastos
-------------- next part --------------
# HG changeset patch
# User Rastislav Stanik <nginx at rastos.org>
# Date 1474145684 -7200
#      Sat Sep 17 22:54:44 2016 +0200
# Node ID f12b9f072e00182c8e12f24a4b8fa323c0d28080
# Parent  52367732bcbc87430e8276424356aaec3c2b6a87
add handling of flastmod SSI directive

Add handling of SSI directive 'flastmod'. The directive
takes a single argument 'file' and is replaced with
modification time of the specified file. The filename
is accepted/rejected based on the same rules as for the
SSI directive 'include'.
The time string is constructed based on SSI directive config timefmt.
Failure to obtain the modification time is logged.

diff -r 52367732bcbc -r f12b9f072e00 src/http/modules/ngx_http_ssi_filter_module.c
--- a/src/http/modules/ngx_http_ssi_filter_module.c	Fri Sep 16 15:13:24 2016 +0300
+++ b/src/http/modules/ngx_http_ssi_filter_module.c	Sat Sep 17 22:54:44 2016 +0200
@@ -85,6 +85,8 @@
 
 static ngx_int_t ngx_http_ssi_include(ngx_http_request_t *r,
     ngx_http_ssi_ctx_t *ctx, ngx_str_t **params);
+static ngx_int_t ngx_http_ssi_flastmod(ngx_http_request_t *r,
+    ngx_http_ssi_ctx_t *ctx, ngx_str_t **params);
 static ngx_int_t ngx_http_ssi_stub_output(ngx_http_request_t *r, void *data,
     ngx_int_t rc);
 static ngx_int_t ngx_http_ssi_set_variable(ngx_http_request_t *r, void *data,
@@ -223,6 +225,8 @@
 #define  NGX_HTTP_SSI_INCLUDE_SET      3
 #define  NGX_HTTP_SSI_INCLUDE_STUB     4
 
+#define  NGX_HTTP_SSI_FLASTMOD_FILE    0
+
 #define  NGX_HTTP_SSI_ECHO_VAR         0
 #define  NGX_HTTP_SSI_ECHO_DEFAULT     1
 #define  NGX_HTTP_SSI_ECHO_ENCODING    2
@@ -247,6 +251,10 @@
     { ngx_null_string, 0, 0, 0 }
 };
 
+static ngx_http_ssi_param_t  ngx_http_ssi_flastmod_params[] = {
+    { ngx_string("file"), NGX_HTTP_SSI_FLASTMOD_FILE, 0, 0 }
+};
+
 
 static ngx_http_ssi_param_t  ngx_http_ssi_echo_params[] = {
     { ngx_string("var"), NGX_HTTP_SSI_ECHO_VAR, 1, 0 },
@@ -308,7 +316,8 @@
                        ngx_http_ssi_block_params, 0, 0, 0 },
     { ngx_string("endblock"), ngx_http_ssi_endblock,
                        ngx_http_ssi_no_params, 0, 1, 0 },
-
+    { ngx_string("flastmod"), ngx_http_ssi_flastmod,
+                       ngx_http_ssi_flastmod_params, 0, 0, 0 },
     { ngx_null_string, NULL, NULL, 0, 0, 0 }
 };
 
@@ -2197,6 +2206,97 @@
     return NGX_OK;
 }
 
+static ngx_int_t
+ngx_http_ssi_flastmod(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx,
+    ngx_str_t **params)
+{
+    ngx_str_t   *file;
+    ngx_str_t   current_path;
+    ngx_uint_t  flags;
+    ngx_int_t   rc;
+    ngx_str_t   args;
+    size_t      root;
+    struct stat st_buf;
+    u_char *endpos;
+    char *statpath;
+    struct tm mod_time;
+    
+    file = params[NGX_HTTP_SSI_FLASTMOD_FILE];
+
+    if (file == NULL) {
+        ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
+                      "no parameter in \"flastmod\" SSI command");
+        return NGX_HTTP_SSI_ERROR;
+    }
+
+    rc = ngx_http_ssi_evaluate_string(r, ctx, file, 0);
+
+    if (rc != NGX_OK) {
+        return rc;
+    }
+
+    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+                   "ssi flastmod: \"%V\"", file);
+
+    ngx_str_null(&args);
+    flags = NGX_HTTP_LOG_UNSAFE;
+    
+    if (ngx_http_parse_unsafe_uri(r, file, &args, &flags) != NGX_OK) {
+        return NGX_HTTP_SSI_ERROR;
+    }
+    
+    root=0;
+    ngx_http_map_uri_to_path(r, &current_path, &root, 0);
+    // in worst case we will append the flastmod file at the end of the current pathname and add terminating zero
+    statpath=ngx_pcalloc(r->pool,current_path.len+file->len+1);
+    if (!statpath) {
+        return NGX_HTTP_SSI_ERROR;
+    }
+    // write the current pathname to 'statpath'
+    strncpy(statpath,current_path.data,current_path.len);
+    endpos=statpath+current_path.len;
+    // find the last slash
+    for (;endpos>current_path.data && !ngx_path_separator(*endpos);endpos--)
+            ;
+    // append the flastmod file after last slash
+    strncpy(endpos+1,file->data,file->len);
+    *(endpos+1+file->len)='\0'; // zero terminate the string so that we can pass it to stat(2)
+    
+    if (0==stat(statpath,&st_buf)) {
+        if (gmtime_r(&st_buf.st_mtim.tv_sec,&mod_time)) {
+            char *result=NULL;
+            ngx_uint_t len=0;
+            ngx_buf_t *b=NULL;
+            
+            result = ngx_pcalloc(r->pool, NGX_HTTP_SSI_MAX_FLASTMOD);
+            if (result) {
+                // convert the modification time to string:
+                len=strftime(result,NGX_HTTP_SSI_MAX_FLASTMOD,ctx->timefmt.data,&mod_time);
+                b = ngx_calloc_buf(r->pool);
+                if (b) {
+                    ngx_chain_t *cl = ngx_alloc_chain_link(r->pool);
+                    if (cl) {
+                        // insert the time string into the http response:
+                        b->memory = 1;
+                        b->pos = result;
+                        b->last = result + len;
+                        
+                        cl->buf = b;
+                        cl->next = NULL;
+                        *ctx->last_out = cl;
+                        ctx->last_out = &cl->next;
+                        return NGX_OK;
+                    }
+                }
+            }
+        }
+    }
+    else
+       ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
+                     "could not stat() \"%s\" file. err=%d",statpath,ngx_errno);
+
+    return NGX_HTTP_SSI_ERROR;
+}
 
 static ngx_int_t
 ngx_http_ssi_stub_output(ngx_http_request_t *r, void *data, ngx_int_t rc)
diff -r 52367732bcbc -r f12b9f072e00 src/http/modules/ngx_http_ssi_filter_module.h
--- a/src/http/modules/ngx_http_ssi_filter_module.h	Fri Sep 16 15:13:24 2016 +0300
+++ b/src/http/modules/ngx_http_ssi_filter_module.h	Sat Sep 17 22:54:44 2016 +0200
@@ -30,6 +30,9 @@
 #define NGX_HTTP_SSI_ENTITY_ENCODING  2
 
 
+#define  NGX_HTTP_SSI_MAX_FLASTMOD     100
+
+
 typedef struct {
     ngx_hash_t                hash;
     ngx_hash_keys_arrays_t    commands;


More information about the nginx-devel mailing list