[PATCH] Log: Added "json" parameter which escapes backslashes in logs

Khramov Anton anton at endocode.com
Thu May 26 08:38:38 UTC 2016


# HG changeset patch
# User Khramov Anton <anton at endocode.com>
# Date 1464194463 -7200
#      Wed May 25 18:41:03 2016 +0200
# Node ID 2e8a8398f0e2e928bdc4088e5999b1ebf481fd7c
# Parent  bc6fd7afeed6f7433c60634d9b0867ea3241b217
Log: Added "json" parameter which escapes backslashes in logs

This patch makes JSON log format not being broken when nginx
escapes special characters, i.e.  "/?var=\x22hello, world\x22"
log entry with json parameter will look like:
"/?var=\\x22hello, world\\x22",

diff -r bc6fd7afeed6 -r 2e8a8398f0e2 src/http/modules/ngx_http_log_module.c
--- a/src/http/modules/ngx_http_log_module.c	Tue May 24 21:54:32 2016 +0300
+++ b/src/http/modules/ngx_http_log_module.c	Wed May 25 18:41:03 2016 +0200
@@ -20,13 +20,14 @@
     ngx_http_log_op_t *op);
 
 typedef size_t (*ngx_http_log_op_getlen_pt) (ngx_http_request_t *r,
-    uintptr_t data);
+    uintptr_t data, ngx_uint_t json);
 
 
 struct ngx_http_log_op_s {
     size_t                      len;
     ngx_http_log_op_getlen_pt   getlen;
     ngx_http_log_op_run_pt      run;
+    ngx_uint_t                  json;
     uintptr_t                   data;
 };
 
@@ -69,6 +70,7 @@
     ngx_syslog_peer_t          *syslog_peer;
     ngx_http_log_fmt_t         *format;
     ngx_http_complex_value_t   *filter;
+    ngx_uint_t                  json;
 } ngx_http_log_t;
 
 
@@ -128,10 +130,10 @@
 static ngx_int_t ngx_http_log_variable_compile(ngx_conf_t *cf,
     ngx_http_log_op_t *op, ngx_str_t *value);
 static size_t ngx_http_log_variable_getlen(ngx_http_request_t *r,
-    uintptr_t data);
+    uintptr_t data, ngx_uint_t json);
 static u_char *ngx_http_log_variable(ngx_http_request_t *r, u_char *buf,
     ngx_http_log_op_t *op);
-static uintptr_t ngx_http_log_escape(u_char *dst, u_char *src, size_t size);
+static uintptr_t ngx_http_log_escape(u_char *dst, u_char *src, size_t size, ngx_uint_t json);
 
 
 static void *ngx_http_log_create_main_conf(ngx_conf_t *cf);
@@ -288,8 +290,9 @@
         len = 0;
         op = log[l].format->ops->elts;
         for (i = 0; i < log[l].format->ops->nelts; i++) {
+            op[i].json = log[l].json;
             if (op[i].len == 0) {
-                len += op[i].getlen(r, op[i].data);
+                len += op[i].getlen(r, op[i].data, log[l].json);
 
             } else {
                 len += op[i].len;
@@ -928,7 +931,7 @@
 
 
 static size_t
-ngx_http_log_variable_getlen(ngx_http_request_t *r, uintptr_t data)
+ngx_http_log_variable_getlen(ngx_http_request_t *r, uintptr_t data, ngx_uint_t json)
 {
     uintptr_t                   len;
     ngx_http_variable_value_t  *value;
@@ -939,10 +942,14 @@
         return 1;
     }
 
-    len = ngx_http_log_escape(NULL, value->data, value->len);
+    len = ngx_http_log_escape(NULL, value->data, value->len, json);
 
     value->escape = len ? 1 : 0;
 
+    if (json) {
+        return value->len + len * 4;
+    }
+
     return value->len + len * 3;
 }
 
@@ -963,13 +970,13 @@
         return ngx_cpymem(buf, value->data, value->len);
 
     } else {
-        return (u_char *) ngx_http_log_escape(buf, value->data, value->len);
+        return (u_char *) ngx_http_log_escape(buf, value->data, value->len, op->json);
     }
 }
 
 
 static uintptr_t
-ngx_http_log_escape(u_char *dst, u_char *src, size_t size)
+ngx_http_log_escape(u_char *dst, u_char *src, size_t size, ngx_uint_t json)
 {
     ngx_uint_t      n;
     static u_char   hex[] = "0123456789ABCDEF";
@@ -1012,6 +1019,9 @@
 
     while (size) {
         if (escape[*src >> 5] & (1 << (*src & 0x1f))) {
+            if (json) {
+                *dst++ = '\\';
+            }
             *dst++ = '\\';
             *dst++ = 'x';
             *dst++ = hex[*src >> 4];
@@ -1129,6 +1139,8 @@
         return NGX_CONF_ERROR;
     }
 
+    log->json = 0;
+
     lmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_log_module);
     fmt = lmcf->formats.elts;
 
@@ -1147,6 +1159,7 @@
 
     ssize_t                            size;
     ngx_int_t                          gzip;
+    ngx_int_t                          json;
     ngx_uint_t                         i, n;
     ngx_msec_t                         flush;
     ngx_str_t                         *value, name, s;
@@ -1270,6 +1283,7 @@
     size = 0;
     flush = 0;
     gzip = 0;
+    json = 0;
 
     for (i = 3; i < cf->args->nelts; i++) {
 
@@ -1359,6 +1373,12 @@
             continue;
         }
 
+        if (ngx_strncmp(value[i].data, "json", 4) == 0)
+        {
+            json = 1;
+            continue;
+        }
+
         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                            "invalid parameter \"%V\"", &value[i]);
         return NGX_CONF_ERROR;
@@ -1371,6 +1391,10 @@
         return NGX_CONF_ERROR;
     }
 
+    if (json) {
+        log->json = 1;
+    }
+
     if (size) {
 
         if (log->script) {



More information about the nginx-devel mailing list