I will give some code example:
ngx_http_my_filter_header_filter(ngx_http_request_t *r)
{
// (...)
// I clear content length, because it will be modified by my filter
if (r == r->main) {
ngx_http_clear_content_length(r);
ngx_http_clear_last_modified(r);
}
return ngx_http_next_header_filter(r);
}
ngx_http_myfilter_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
{
// process data
// enqueue downloads etc.
//...
return NGX_DONE;
}
The function which is called when downloads are finished:
ngx_http_myfilter_download_finished()
{
// process data etc.
// create and fill new ngx_chain_t
// set in bufs: memory = 1, last_buf = 1 in last buffer
rc = ngx_http_next_body_filter(r, output_chain);
if(rc == NGX_AGAIN)
{
ngx_add_timer(r->connection->write, timeout);
r->write_event_handler = ngx_http_myfilter_fast_handler;
if (ngx_handle_write_event(r->connection->write, 0) == NGX_ERROR)
{
// error handling
}
}
else {
ngx_http_myfilter_fast_handler(r);
}
}
and fast_handler:
ngx_http_xxslt_fast_handler(ngx_http_request_t *r)
{
ngx_int_t rc;
rc = ngx_http_send_special(r, NGX_HTTP_LAST);
ngx_http_finalize_request(r, rc);
}
When ngx_http_next_body_filter returns NGX_OK everything is fine, no problem.
My filter behaves strange, when ngx_http_next_body_filter returns NGX_AGAIN (for large output chains).
When I refresh website, first request is handled properly, I can see the result in the web browser.
Second request is broken. After receiving rc = NGX_AGAIN my fast_handler is not called and response isn't transferred to the client.
There are two messages in logs from nginx:
2009/09/18 11:40:25 [info] 30067#0: *52 client closed prematurely connection (104: Connection reset by peer) while sending response to client, client: 10.166...
2009/09/18 11:40:54 [info] 30067#0: *1 client timed out (110: Connection timed out) while sending response to client, client: 10.166...
When I use telnet it looks like this:
GET /sth HTTP/1.1
Host: host
[result]
0
0
// this is ok, because of Transfer-Encoding: chunked there are two zeros at the end
GET /sth HTTP/1.1
Host: host
[result]
0
// where is second 0?
GET /sth HTTP/1.1
Host: host
[no result, no reaction]
GET /sth HTTP/1.1
Host: host
[no result, no reaction again]
etc.
These request which are not handled just call my body_filter with in = NULL (it's visible in logs).
Any ideas what am I doing wrong?
Any help will be greatly appreciated ;)