Add size of empty gif

From: Kirill A. Korinskiy [email protected]

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;
    +}

From: Kirill A. Korinskiy [email protected]

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;
    }

From: Kirill A. Korinskiy [email protected]


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),