Opened 3 years ago

Last modified 20 months ago

#1743 new defect

Can't flush HTTP response header under TLS+HTTP2

Reported by: mrpre@… Owned by:
Priority: minor Milestone:
Component: nginx-module Version: 1.14.x
Keywords: http2 Cc:
uname -a: centos7 CST 2017 x86_64 x86_64 x86_64 GNU/Linux
nginx -V: --with-stream --with-stream_ssl_module --with-http_ssl_module --with-http_v2_module


I want to send HTTP response header first before data is sent to client.
so I do like this:

/*Want to response Header and flush*/
/*ngx_http_send_special doesn't work under HTTP2 but works under HTTP1*/
ngx_http_send_special(r, NGX_HTTP_FLUSH);
/*send Data later*/
ngx_http_output_filter(r, &out);

I had already set postpone_output to 0, and then I found HTTP response header was cached in ssl_buffer( in function ngx_ssl_send_chain ).

Under HTTP 1, function ngx_ssl_send_chain will set c->buffered which c was the real connection and then we call ngx_http_send_special->...->ngx_http_write_filter->ngx_ssl_send_chain, the header was sent on network. That was I want.

Under HTTP 2, function ngx_ssl_send_chain will set c->buffered which c was the real connection but when ngx_http_send_special->...->ngx_http_write_filter was called, ngx_ssl_send_chain wasn't called, because the c in ngx_http_write_filter was the H2 fake connection and c->buffered was not set

    if (size == 0
        && !(c->buffered & NGX_LOWLEVEL_BUFFERED)
        && !(last && c->need_last_buf))
        /*return here*/
        if (last || flush || sync) {
            for (cl = r->out; cl; /* void */) {
                ln = cl;
                cl = cl->next;
                ngx_free_chain(r->pool, ln);

            r->out = NULL;
            c->buffered &= ~NGX_HTTP_WRITE_BUFFERED;

            return NGX_OK;

        ngx_log_error(NGX_LOG_ALERT, c->log, 0,
                      "the http output chain is empty");


        return NGX_ERROR;

What should I do if I want to flush HTTP response header into network before data is sent ?

Change History (2)

comment:1 by mrpre@…, 3 years ago

What I want is that DATA frame is delayed one minute.

/*HEAD frame first*/

/*NGX_HTTP_FLUSH doesn't wrok, HEAD frame still cached in ssl buffer*/
ngx_http_send_special(r, NGX_HTTP_FLUSH);

/*This action will flush HEAD frame which means HEAD frame and DATA frame are sent by one tcp segment*/
ngx_http_output_filter(r, &out);

comment:2 by Maxim Dounin, 20 months ago

Keywords: http2 added
Note: See TracTickets for help on using tickets.