[PATCH] SSI: Implement #fsize SSI command

Maxim Dounin mdounin at mdounin.ru
Mon Jan 30 14:26:45 UTC 2017


Hello!

On Sat, Jan 28, 2017 at 02:08:29PM +0300, Matwey V. Kornilov wrote:

> # HG changeset patch
> # User Matwey V. Kornilov <matwey.kornilov at gmail.com>
> # Date 1485600652 -10800
> #      Sat Jan 28 13:50:52 2017 +0300
> # Branch fsize
> # Node ID f3bb0258beb24b975b94966a94d45e9a9f5c3c39
> # Parent  640f035293959b2d4b0ba5939d954bc517f57f77
> SSI: Implement #fsize SSI command

Thanks, looks interesting, though certainly it needs more work.  
Some comments below.

[...]

> +static ngx_int_t ngx_http_ssi_fsize(ngx_http_request_t *r,
> +    ngx_http_ssi_ctx_t *ctx, ngx_str_t **params)

Style:
The function type should be on a line by itself preceding the 
function.  That is, function name should start on its own line:

static ngx_int_t
ngx_http_ssi_fsize(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx,
    ngx_str_t **params)

[...]

> +    psr->handler = ngx_http_ssi_fsize_output;
> +    psr->data = ctx;
> +
> +    if (ngx_http_subrequest(r, uri, &args, &sr, psr, flags) != NGX_OK) {
> +        return NGX_HTTP_SSI_ERROR;
> +    }
> +    sr->header_only = 1;
> +
> +    return NGX_OK;
> +}
> +
> +
> +static ngx_int_t ngx_http_ssi_fsize_output(ngx_http_request_t *r, void *data,
> +    ngx_int_t rc)
> +{
> +    ngx_chain_t        *out;
> +    ngx_buf_t          *b;
> +    u_char             *p;
> +    size_t              len, i;
> +    ngx_http_ssi_ctx_t *ctx;
> +    unsigned            sizefmt_bytes;
> +
> +    ctx = data;
> +    sizefmt_bytes = (ctx ? ctx->sizefmt_bytes : 0);

Just a side note:
It is not clear how ctx can be NULL here.

> +
> +    p = ngx_pnalloc(r->pool, NGX_OFF_T_LEN + 1);
> +    if (p == NULL) {
> +        return NGX_ERROR;
> +    }
> +
> +    len = ngx_sprintf(p, "%O", r->headers_out.content_length_n) -  p;

Note that r->headers_out.content_length_n may be -1 here.  Either 
because it is not known at all (this can happen for proxied 
requests), or because it was cleared/modified by a filter 
expecting to change the response.  In either case "-1" is probably 
not a correct value to print here.

It might also be a good idea to find out how to prevent filters 
from clearing the length and/or how to save it earlier.

> +
> +    if (!sizefmt_bytes) {
> +        i = len / 3;
> +        len = len % 3;
> +
> +        p[len] = ngx_http_ssi_si_prefix[i];
> +        len++;
> +    }
> +
> +    b = ngx_calloc_buf(r->pool);
> +    if (b == NULL) {
> +        return NGX_ERROR;
> +    }
> +
> +    b->memory = 1;
> +    b->pos = p;
> +    b->last = p + len;

Just a side note:
Using ngx_create_temp_buf() might be more appropriate here.

> +
> +    out= ngx_alloc_chain_link(r->pool);
> +    if (out == NULL) {
> +        return NGX_ERROR;
> +    }
> +
> +    out->buf = b;
> +    out->next = NULL;
> +
> +    return ngx_http_output_filter(r, out);

Not sure if it's ok to declare a subrequest as a header_only one, 
and then output a body for it.  I suspect it may break in 
unexpected places.

Alternative approach would be to wait for the subrequest and then 
output the result in the main request context, much like it is 
done for "include set".

> @@ -2400,6 +2529,22 @@
>          ctx->errmsg = *value;
>      }
>  
> +    value = params[NGX_HTTP_SSI_CONFIG_SIZEFMT];
> +
> +    if (value) {
> +       if (value->len == 5
> +           && ngx_strncasecmp(value->data, (u_char*)"bytes", 5) == 0) {
> +           ctx->sizefmt_bytes = 1;

Style:
The "{" should be on its own line.  And the cast needs more 
spaces,

       if (value->len == 5
           && ngx_strncasecmp(value->data, (u_char *) "bytes", 5) == 0)
       {
           ctx->sizefmt_bytes = 1;

-- 
Maxim Dounin
http://nginx.org/


More information about the nginx-devel mailing list