From: Kirill A. Korinskiy <catap@catap.ru>
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;
}
--
1.6.2