Forum: NGINX Add size of empty gif

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Kirill A. Korinskiy (Guest)
on 2009-03-17 21:28
(Received via mailing list)
From: Kirill A. Korinskiy <removed_email_address@domain.invalid>

`ngx_http_empty_gif_module' is a simplpe module for send 1x1
transparent gif. Since the gif can contain any number of garbages data
after the header, I added a directive `empty_gif_size' that sets the
size of "size" for gif 1x1 transparent gif.
---
 src/http/modules/ngx_http_empty_gif_module.c |  162
++++++++++++++++++++++----
 1 files changed, 137 insertions(+), 25 deletions(-)

diff --git a/src/http/modules/ngx_http_empty_gif_module.c
b/src/http/modules/ngx_http_empty_gif_module.c
index
20e4413c086bc9cce0c54b591edc3b5324cf591b..2abbc19ceb9991be85ebd2236d106c4800ae6508
100644
--- a/src/http/modules/ngx_http_empty_gif_module.c
+++ b/src/http/modules/ngx_http_empty_gif_module.c
@@ -8,9 +8,22 @@
 #include <ngx_http.h>


+typedef struct {
+    ngx_str_t fake;
+} ngx_http_empty_gif_loc_conf_t;
+
+
 static char *ngx_http_empty_gif(ngx_conf_t *cf, ngx_command_t *cmd,
     void *conf);

+static void *ngx_http_empty_gif_create_local_conf(ngx_conf_t *cf);
+static char *ngx_http_empty_gif_merge_local_conf(ngx_conf_t *cf,
+    void *parent, void *child);
+
+static char *ngx_http_empty_gif_size(ngx_conf_t *cf,
+    ngx_command_t *cmd, void *conf);
+
+
 static ngx_command_t  ngx_http_empty_gif_commands[] = {

     { ngx_string("empty_gif"),
@@ -20,6 +33,13 @@ static ngx_command_t  ngx_http_empty_gif_commands[] =
{
       0,
       NULL },

+    { ngx_string("empty_gif_size"),
+      NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+      ngx_http_empty_gif_size,
+      NGX_HTTP_LOC_CONF_OFFSET,
+      offsetof(ngx_http_empty_gif_loc_conf_t, fake),
+      NULL },
+
       ngx_null_command
 };

@@ -75,32 +95,32 @@ static u_char  ngx_empty_gif[] = {


 static ngx_http_module_t  ngx_http_empty_gif_module_ctx = {
-    NULL,                          /* preconfiguration */
-    NULL,                          /* postconfiguration */
+    NULL,                                  /* preconfiguration */
+    NULL,                                  /* postconfiguration */

-    NULL,                          /* create main configuration */
-    NULL,                          /* init main configuration */
+    NULL,                                  /* create main configuration
*/
+    NULL,                                  /* init main configuration
*/

-    NULL,                          /* create server configuration */
-    NULL,                          /* merge server configuration */
+    NULL,                                  /* create server
configuration */
+    NULL,                                  /* merge server
configuration */

-    NULL,                          /* create location configuration */
-    NULL                           /* merge location configuration */
+    ngx_http_empty_gif_create_local_conf,  /* create location
configuration */
+    ngx_http_empty_gif_merge_local_conf    /* merge location
configuration */
 };


 ngx_module_t  ngx_http_empty_gif_module = {
     NGX_MODULE_V1,
-    &ngx_http_empty_gif_module_ctx, /* module context */
-    ngx_http_empty_gif_commands,   /* module directives */
-    NGX_HTTP_MODULE,               /* module type */
-    NULL,                          /* init master */
-    NULL,                          /* init module */
-    NULL,                          /* init process */
-    NULL,                          /* init thread */
-    NULL,                          /* exit thread */
-    NULL,                          /* exit process */
-    NULL,                          /* exit master */
+    &ngx_http_empty_gif_module_ctx,   /* module context */
+    ngx_http_empty_gif_commands,      /* module directives */
+    NGX_HTTP_MODULE,                  /* module type */
+    NULL,                             /* init master */
+    NULL,                             /* init module */
+    NULL,                             /* init process */
+    NULL,                             /* init thread */
+    NULL,                             /* exit thread */
+    NULL,                             /* exit process */
+    NULL,                             /* exit master */
     NGX_MODULE_V1_PADDING
 };

@@ -108,9 +128,12 @@ ngx_module_t  ngx_http_empty_gif_module = {
 static ngx_int_t
 ngx_http_empty_gif_handler(ngx_http_request_t *r)
 {
-    ngx_int_t     rc;
-    ngx_buf_t    *b;
-    ngx_chain_t   out;
+    ngx_int_t                       rc;
+    ngx_buf_t                      *b;
+    ngx_chain_t                     out[2];
+    ngx_http_empty_gif_loc_conf_t  *conf;
+
+    conf = ngx_http_get_module_loc_conf(r, ngx_http_empty_gif_module);

     if (!(r->method & (NGX_HTTP_GET|NGX_HTTP_HEAD))) {
         return NGX_HTTP_NOT_ALLOWED;
@@ -129,6 +152,9 @@ ngx_http_empty_gif_handler(ngx_http_request_t *r)
     if (r->method == NGX_HTTP_HEAD) {
         r->headers_out.status = NGX_HTTP_OK;
         r->headers_out.content_length_n = sizeof(ngx_empty_gif);
+        if (conf->fake.len) {
+            r->headers_out.content_length_n += conf->fake.len;
+        }
         r->headers_out.last_modified_time = 23349600;

         r->headers_out.etag_size = 40;
@@ -144,18 +170,36 @@ ngx_http_empty_gif_handler(ngx_http_request_t *r)
         return NGX_HTTP_INTERNAL_SERVER_ERROR;
     }

-    out.buf = b;
-    out.next = NULL;
+    out[0].buf = b;
+    out[0].next = NULL;

     b->pos = ngx_empty_gif;
     b->last = ngx_empty_gif + sizeof(ngx_empty_gif);
     b->memory = 1;
-    b->last_buf = 1;

     r->headers_out.status = NGX_HTTP_OK;
     r->headers_out.content_length_n = sizeof(ngx_empty_gif);
     r->headers_out.last_modified_time = 23349600;

+    if (conf->fake.len) {
+        out[0].next = &out[1];
+        r->headers_out.content_length_n += conf->fake.len;
+
+        b = ngx_pcalloc(r->pool, sizeof(ngx_buf_t));
+        if (b == NULL) {
+            return NGX_HTTP_INTERNAL_SERVER_ERROR;
+        }
+
+        out[1].next = NULL;
+        out[1].buf = b;
+
+        b->pos = conf->fake.data;
+        b->last = conf->fake.data + conf->fake.len;
+        b->memory = 1;
+    }
+
+    b->last_buf = 1;
+
     r->headers_out.etag_size = 40;
     r->headers_out.etag_time = 5;
     r->headers_out.etag_uniq = 6535;
@@ -166,7 +210,7 @@ ngx_http_empty_gif_handler(ngx_http_request_t *r)
         return rc;
     }

-    return ngx_http_output_filter(r, &out);
+    return ngx_http_output_filter(r, &out[0]);
 }


@@ -180,3 +224,71 @@ ngx_http_empty_gif(ngx_conf_t *cf, ngx_command_t
*cmd, void *conf)

     return NGX_CONF_OK;
 }
+
+
+static void *
+ngx_http_empty_gif_create_local_conf(ngx_conf_t *cf)
+{
+    ngx_http_empty_gif_loc_conf_t  *conf;
+
+    conf = ngx_pcalloc(cf->pool,
sizeof(ngx_http_empty_gif_loc_conf_t));
+    if (conf == NULL) {
+        return NGX_CONF_ERROR;
+    }
+
+    return conf;
+}
+
+static char *
+ngx_http_empty_gif_merge_local_conf(ngx_conf_t *cf, void *parent, void
*child)
+{
+    ngx_http_empty_gif_loc_conf_t  *prev = parent;
+    ngx_http_empty_gif_loc_conf_t  *conf = child;
+
+    if (prev->fake.len) {
+        conf->fake = prev->fake;
+    }
+
+    return NGX_CONF_OK;
+}
+
+static char *
+ngx_http_empty_gif_size(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
+{
+    char  *p = conf;
+
+    ngx_str_t                 *field, *value;
+    ngx_conf_post_t           *post;
+
+    field = (ngx_str_t *) (p + cmd->offset);
+
+    if (field->data) {
+        return "is duplicate";
+    }
+
+    value = cf->args->elts;
+
+    field->len = ngx_parse_size(&value[1]);
+
+    if (field->len == (size_t) NGX_ERROR) {
+        return "invalid value";
+    }
+
+    if (field->len < sizeof(ngx_empty_gif)) {
+        return "is shortly";
+    }
+
+    field->len -= sizeof(ngx_empty_gif);
+
+    field->data = ngx_pcalloc(cf->pool, field->len);
+    if (field->data == NULL) {
+        return NGX_CONF_ERROR;
+    }
+
+    if (cmd->post) {
+        post = cmd->post;
+        return post->post_handler(cf, post, field);
+    }
+
+    return NGX_CONF_OK;
+}
Kirill A. Korinskiy (Guest)
on 2009-03-18 01:49
(Received via mailing list)
From: Kirill A. Korinskiy <removed_email_address@domain.invalid>

Now for send of very large empty gif did not allocated a lot of
memory, because I allocated buffer and used it multiple times. Size of
buffer is a first optional argument of `empty_gif_size' directive.
---
 src/http/modules/ngx_http_empty_gif_module.c |  109
+++++++++++++++++---------
 1 files changed, 71 insertions(+), 38 deletions(-)

diff --git a/src/http/modules/ngx_http_empty_gif_module.c
b/src/http/modules/ngx_http_empty_gif_module.c
index
2abbc19ceb9991be85ebd2236d106c4800ae6508..17b46ac0efb06673232e808ca1d0b44d5994a1a2
100644
--- a/src/http/modules/ngx_http_empty_gif_module.c
+++ b/src/http/modules/ngx_http_empty_gif_module.c
@@ -9,7 +9,12 @@


 typedef struct {
-    ngx_str_t fake;
+    size_t     size;
+    ngx_str_t  str;
+} ngx_http_empty_gif_fake_t;
+
+typedef struct {
+    ngx_http_empty_gif_fake_t fake;
 } ngx_http_empty_gif_loc_conf_t;


@@ -34,7 +39,7 @@ static ngx_command_t  ngx_http_empty_gif_commands[] =
{
       NULL },

     { ngx_string("empty_gif_size"),
-      NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+      NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1|NGX_CONF_TAKE2,
       ngx_http_empty_gif_size,
       NGX_HTTP_LOC_CONF_OFFSET,
       offsetof(ngx_http_empty_gif_loc_conf_t, fake),
@@ -129,8 +134,9 @@ static ngx_int_t
 ngx_http_empty_gif_handler(ngx_http_request_t *r)
 {
     ngx_int_t                       rc;
-    ngx_buf_t                      *b;
-    ngx_chain_t                     out[2];
+    ngx_buf_t                      *b = NULL;
+    ngx_uint_t                      i, out_count;
+    ngx_chain_t                    *out;
     ngx_http_empty_gif_loc_conf_t  *conf;

     conf = ngx_http_get_module_loc_conf(r, ngx_http_empty_gif_module);
@@ -152,8 +158,8 @@ ngx_http_empty_gif_handler(ngx_http_request_t *r)
     if (r->method == NGX_HTTP_HEAD) {
         r->headers_out.status = NGX_HTTP_OK;
         r->headers_out.content_length_n = sizeof(ngx_empty_gif);
-        if (conf->fake.len) {
-            r->headers_out.content_length_n += conf->fake.len;
+        if (conf->fake.size) {
+            r->headers_out.content_length_n += conf->fake.size;
         }
         r->headers_out.last_modified_time = 23349600;

@@ -165,39 +171,50 @@ ngx_http_empty_gif_handler(ngx_http_request_t *r)
         return ngx_http_send_header(r);
     }

-    b = ngx_pcalloc(r->pool, sizeof(ngx_buf_t));
-    if (b == NULL) {
-        return NGX_HTTP_INTERNAL_SERVER_ERROR;
+    out_count = 1;
+    if (conf->fake.size) {
+        out_count += conf->fake.size / conf->fake.str.len;
+        if (conf->fake.size % conf->fake.str.len) {
+            out_count++;
+        }
     }

-    out[0].buf = b;
-    out[0].next = NULL;
-
-    b->pos = ngx_empty_gif;
-    b->last = ngx_empty_gif + sizeof(ngx_empty_gif);
-    b->memory = 1;
-
-    r->headers_out.status = NGX_HTTP_OK;
-    r->headers_out.content_length_n = sizeof(ngx_empty_gif);
-    r->headers_out.last_modified_time = 23349600;
-
-    if (conf->fake.len) {
-        out[0].next = &out[1];
-        r->headers_out.content_length_n += conf->fake.len;
+    out = ngx_palloc(r->pool, sizeof(ngx_chain_t) * out_count);
+    if (out == NULL) {
+        return NGX_HTTP_INTERNAL_SERVER_ERROR;
+    }

+    for (i = 0; i < out_count; i++) {
         b = ngx_pcalloc(r->pool, sizeof(ngx_buf_t));
         if (b == NULL) {
             return NGX_HTTP_INTERNAL_SERVER_ERROR;
         }

-        out[1].next = NULL;
-        out[1].buf = b;
+        out[i].buf = b;
+
+        if (0 == i) {
+            out[i].next = NULL;
+            b->pos = b->start = ngx_empty_gif;
+            b->last = b->end = ngx_empty_gif + sizeof(ngx_empty_gif);
+        } else if ((conf->fake.size / conf->fake.str.len) + 1 == i) {
+            out[i-1].next = &out[i];
+            out[i].next = NULL;
+            b->pos = b->start = conf->fake.str.data;
+            b->last = b->end = conf->fake.str.data + conf->fake.size %
conf->fake.str.len;
+        } else {
+            out[i-1].next = &out[i];
+            out[i].next = NULL;
+            b->pos = b->start = conf->fake.str.data;
+            b->last = b->end = conf->fake.str.data +
conf->fake.str.len;
+        }

-        b->pos = conf->fake.data;
-        b->last = conf->fake.data + conf->fake.len;
         b->memory = 1;
     }

+    r->headers_out.status = NGX_HTTP_OK;
+    r->headers_out.content_length_n = sizeof(ngx_empty_gif) +
conf->fake.size;
+    r->headers_out.last_modified_time = 23349600;
+
     b->last_buf = 1;

     r->headers_out.etag_size = 40;
@@ -210,7 +227,7 @@ ngx_http_empty_gif_handler(ngx_http_request_t *r)
         return rc;
     }

-    return ngx_http_output_filter(r, &out[0]);
+    return ngx_http_output_filter(r, out);
 }


@@ -245,7 +262,7 @@ ngx_http_empty_gif_merge_local_conf(ngx_conf_t *cf,
void *parent, void *child)
     ngx_http_empty_gif_loc_conf_t  *prev = parent;
     ngx_http_empty_gif_loc_conf_t  *conf = child;

-    if (prev->fake.len) {
+    if (prev->fake.size) {
         conf->fake = prev->fake;
     }

@@ -257,31 +274,47 @@ ngx_http_empty_gif_size(ngx_conf_t *cf,
ngx_command_t *cmd, void *conf)
 {
     char  *p = conf;

-    ngx_str_t                 *field, *value;
+    ngx_str_t                 *value;
+    ngx_int_t                  i = 1;
     ngx_conf_post_t           *post;
+    ngx_http_empty_gif_fake_t *field;

-    field = (ngx_str_t *) (p + cmd->offset);
+    field = (ngx_http_empty_gif_fake_t *) (p + cmd->offset);

-    if (field->data) {
+    if (field->str.data) {
         return "is duplicate";
     }

     value = cf->args->elts;

-    field->len = ngx_parse_size(&value[1]);
+    if (cf->args->nelts == 3) {
+        field->str.len = ngx_parse_size(&value[i]);
+        if (field->str.len == (size_t) NGX_ERROR) {
+            return "invalid value";
+        }
+        i++;
+    } else {
+        field->str.len = 1024;
+    }
+
+    field->size = ngx_parse_size(&value[i]);

-    if (field->len == (size_t) NGX_ERROR) {
+    if (field->size == (size_t) NGX_ERROR) {
         return "invalid value";
     }

-    if (field->len < sizeof(ngx_empty_gif)) {
+    if (field->size < sizeof(ngx_empty_gif)) {
         return "is shortly";
     }

-    field->len -= sizeof(ngx_empty_gif);
+    field->size -= sizeof(ngx_empty_gif);
+
+    if (field->str.len > field->size) {
+        field->str.len = field->size;
+    }

-    field->data = ngx_pcalloc(cf->pool, field->len);
-    if (field->data == NULL) {
+    field->str.data = ngx_pcalloc(cf->pool, field->str.len);
+    if (field->str.data == NULL) {
         return NGX_CONF_ERROR;
     }
Kirill A. Korinskiy (Guest)
on 2009-03-18 01:49
(Received via mailing list)
From: Kirill A. Korinskiy <removed_email_address@domain.invalid>

---
 src/http/modules/ngx_http_empty_gif_module.c |    3 ++-
 1 files changed, 2 insertions(+), 1 deletions(-)

diff --git a/src/http/modules/ngx_http_empty_gif_module.c
b/src/http/modules/ngx_http_empty_gif_module.c
index
17b46ac0efb06673232e808ca1d0b44d5994a1a2..e1a5749f44369b092913720ab89f565f8deb3130
100644
--- a/src/http/modules/ngx_http_empty_gif_module.c
+++ b/src/http/modules/ngx_http_empty_gif_module.c
@@ -39,7 +39,8 @@ static ngx_command_t  ngx_http_empty_gif_commands[] =
{
       NULL },

     { ngx_string("empty_gif_size"),
-      NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1|NGX_CONF_TAKE2,
+
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF
+                        |NGX_CONF_TAKE12,
       ngx_http_empty_gif_size,
       NGX_HTTP_LOC_CONF_OFFSET,
       offsetof(ngx_http_empty_gif_loc_conf_t, fake),
This topic is locked and can not be replied to.