diff options
| author | Igor Sysoev <igor@sysoev.ru> | 2002-08-15 17:20:26 +0000 |
|---|---|---|
| committer | Igor Sysoev <igor@sysoev.ru> | 2002-08-15 17:20:26 +0000 |
| commit | 0c331d9f666b4f9be91009b7caea457e58a80779 (patch) | |
| tree | d48221581b361ee5b0ccad46e4df49caa41b1bba /src/http | |
| parent | 6de5c2cb63f8aee4bcbec3c363a72fd8e4a4e64d (diff) | |
| download | nginx-0c331d9f666b4f9be91009b7caea457e58a80779.tar.gz nginx-0c331d9f666b4f9be91009b7caea457e58a80779.tar.bz2 | |
nginx-0.0.1-2002-08-15-21:20:26 import
Diffstat (limited to 'src/http')
| -rw-r--r-- | src/http/modules/ngx_http_header_filter.c | 55 | ||||
| -rw-r--r-- | src/http/modules/ngx_http_index_handler.c | 11 | ||||
| -rw-r--r-- | src/http/modules/ngx_http_static_handler.c | 101 | ||||
| -rw-r--r-- | src/http/ngx_http.h | 7 | ||||
| -rw-r--r-- | src/http/ngx_http_event.c | 56 | ||||
| -rw-r--r-- | src/http/ngx_http_filter.h | 10 | ||||
| -rw-r--r-- | src/http/ngx_http_parse.c | 475 | ||||
| -rw-r--r-- | src/http/ngx_http_write_filter.c | 82 | ||||
| -rw-r--r-- | src/http/ngx_http_write_filter.h | 11 |
9 files changed, 767 insertions, 41 deletions
diff --git a/src/http/modules/ngx_http_header_filter.c b/src/http/modules/ngx_http_header_filter.c new file mode 100644 index 000000000..1742b8bfc --- /dev/null +++ b/src/http/modules/ngx_http_header_filter.c @@ -0,0 +1,55 @@ + + +typedef struct { + int len; + char *line; +} line; + + +static line http_codes[] = { + { 6, "200 OK" } +}; + + + + +int ngx_http_header_filter(ngx_http_request_t *r) +{ + int status; + ngx_hunk_t *h; + + ngx_test_null(h, ngx_get_hunk(r->pool, 1024, 0, 64), NGX_HTTP_FILTER_ERROR); + + status = r->headers_out->status - GX_HTTP_OK; + + ngx_memcpy(h->pos.mem, "HTTP/1.0 ", 9); + h->pos.mem += 9; + ngx_memcpy(h->pos.mem, http_codes[status].line, http_codes[status].len); + h->pos.mem += http_codes[status].len; + *(h->pos.mem++) = CR; *(h->pos.mem++) = LF; + + memcpy(h->pos.mem, "Date: ", 6); + h->pos.mem += 6; + h->pos.mem += ngx_http_get_time(h->pos.mem, time()); + *(h->pos.mem++) = CR; *(h->pos.mem++) = LF; + + /* 2^64 is 20 characters */ + if (r->headers_out->content_length) + h->pos.mem += ngx_snprintf(h->pos.mem, 49, "Content-Length: %d" CRLF, + r->headers_out->content_length); + + /* check */ + + memcpy(h->pos.mem, "Server: ", 8); + h->pos.mem += 8; + if (r->headers_out->server) { + h->pos.mem = ngx_cpystrn(h->pos.mem, r->headers_out->server, + h->last.mem - h->pos.mem); + check space + } else { + ngx_memcpy(h->pos.mem, NGINX_VER, sizeof(NGINX_VER)); + h->pos.mem += sizeof(NGINX_VER); + } + *(h->pos.mem++) = CR; *(h->pos.mem++) = LF; + +} diff --git a/src/http/modules/ngx_http_index_handler.c b/src/http/modules/ngx_http_index_handler.c index 498dda664..2d3f3663d 100644 --- a/src/http/modules/ngx_http_index_handler.c +++ b/src/http/modules/ngx_http_index_handler.c @@ -20,10 +20,11 @@ int ngx_http_index_handler(ngx_http_request_t *r) ngx_get_module_loc_conf(r, &ngx_http_index_handler_module); index_len = (*(r->uri_end - 1) == '/') ? cf->max_index_len : 0; - name = ngx_palloc(r->pool, r->uri_end - r->uri_start + index_len - + r->server->doc_root_len); - if (name == NULL) - return NGX_ERROR; + + ngx_test_null(name, + ngx_palloc(r->pool, r->uri_end - r->uri_start + index_len + + r->server->doc_root_len), + NGX_HTTP_INTERNAL_SERVER_ERROR); loc = ngx_cpystrn(name, r->server->doc_root, r->server->doc_root_len); file = ngx_cpystrn(loc, r->uri_start, r->uri_end - r->uri_start + 1); @@ -39,7 +40,7 @@ int ngx_http_index_handler(ngx_http_request_t *r) if (err == NGX_ENOENT) return NGX_HTTP_NOT_FOUND; else - return NGX_ERROR; + return NGX_HTTP_INTERNAL_SERVER_ERROR; } if (ngx_is_dir(r->stat)) { diff --git a/src/http/modules/ngx_http_static_handler.c b/src/http/modules/ngx_http_static_handler.c new file mode 100644 index 000000000..f2053c443 --- /dev/null +++ b/src/http/modules/ngx_http_static_handler.c @@ -0,0 +1,101 @@ + +#include <ngx_config.h> + +#include <ngx_strings.h> +#include <ngx_open.h> +#include <ngx_stat.h> + +#include <ngx_http.h> + +int ngx_http_static_handler(ngx_http_request_t *r) +{ + int index_len, err, i; + char *name, *loc, *file + ngx_file_t fd; + + ngx_http_header_out_t out; + ngx_http_event_static_handler_loc_conf_t *cf; + + cf = (ngx_http_event_static_handler_loc_conf_t *) + ngx_get_module_loc_conf(r, &ngx_http_event_static_handler_module); + + ngx_assert(r->fd, return NGX_HTTP_INTERNAL_SERVER_ERROR, + r->connection->log, "ngx_http_static_handler: no file"); + + out.status = NGX_HTTP_OK; + out.content_length = r->stat.sb_size; + out.last_modified = r->stat.sb_mtime; + + /* */ + out.content_type = "text/html"; + + rc = ngx_send_http_header(&out); + if (r->header_only) + return rc; + + /* NGX_HTTP_INTERNAL_SERVER_ERROR is too late */ + + ngx_test_null(h, ngx_create_hunk(r->pool), NGX_HTTP_INTERNAL_SERVER_ERROR); + h->type = NGX_HUNK_FILE | NGX_HUNK_LAST; + h->fd = r->fd; + h->pos.file = 0; + h->end.file = r->stat.sb_size; + + ngx_test_null(ch, ngx_create_chain(r->pool), + NGX_HTTP_INTERNAL_SERVER_ERROR); + ch->hunk = h; + ch->next = NULL; + + return ngx_http_filter(ch); +} + +/* + +static void *ngx_create_index_config() +{ + ngx_http_index_handler_loc_conf_t *cf; + + ngx_check_null(cf, ngx_alloc(p, sizeof(ngx_http_index_handler_loc_conf)), + NULL); + + cf->indices = ngx_create_array(p, sizeof(ngx_http_index_t), 5); + if (cf->indices == NULL) + return NULL; + + cf->max_index_len = 0; + + return cf; +} + +static void *ngx_merge_index_config() +{ + if (p->indices->nelts > 0) { + + copy and check dups + + if (c->max_index_len < c->max_index_len) + c->max_index_len < c->max_index_len); + } +} + +static void *ngx_set_index() +{ + if (*conf == NULL) { + cf = ngx_create_index_conf(); + if (cf == NULL) + return "can not create config"; + } + + while (args) { + index = ngx_push_array(cf->indices); + index->name = arg; + index->len = ngx_strlen(arg) + 1; + + if (cf->max_index_len < index->len) + cf->max_index_len = index->len; + } + + *conf = cf; +} + +*/ diff --git a/src/http/ngx_http.h b/src/http/ngx_http.h index 62e10f750..6fa0f7829 100644 --- a/src/http/ngx_http.h +++ b/src/http/ngx_http.h @@ -23,6 +23,13 @@ typedef struct { + void *ctx; /* STUB */ +} ngx_http_module_t; + +/* STUB */ +#define ngx_get_module_ctx(r, module) (module)->ctx + +typedef struct { char *buff; char *pos; char *last; diff --git a/src/http/ngx_http_event.c b/src/http/ngx_http_event.c index 8c3ada844..24cbb5663 100644 --- a/src/http/ngx_http_event.c +++ b/src/http/ngx_http_event.c @@ -38,10 +38,7 @@ int ngx_http_init_connection(ngx_connection_t *c) ngx_event_t *ev; ev = c->read; -/* ev->event_handler = ngx_http_init_request; -*/ - ev->event_handler = NULL; ev->log->action = "reading client request line"; ngx_log_debug(ev->log, "ngx_http_init_connection: entered"); @@ -62,8 +59,6 @@ int ngx_http_init_connection(ngx_connection_t *c) #endif } -#if 0 - int ngx_http_init_request(ngx_event_t *ev) { ngx_connection_t *c = (ngx_connection_t *) ev->data; @@ -71,11 +66,13 @@ int ngx_http_init_request(ngx_event_t *ev) ngx_log_debug(ev->log, "ngx_http_init_request: entered"); + ngx_test_null(c->pool, ngx_create_pool(16384, ev->log), -1); ngx_test_null(r, ngx_pcalloc(c->pool, sizeof(ngx_http_request_t)), -1); c->data = r; r->connection = c; + ngx_test_null(r->pool, ngx_create_pool(16384, ev->log), -1); ngx_test_null(r->buff, ngx_palloc(r->pool, sizeof(ngx_buff_t)), -1); ngx_test_null(r->buff->buff, ngx_pcalloc(r->pool, sizeof(c->server->buff_size)), -1); @@ -99,33 +96,15 @@ int ngx_http_process_request(ngx_event_t *ev) ngx_log_debug(ev->log, "http process request"); - ngx_log_debug(ev->log, "http: eof:%d, avail:%d", ev->eof, ev->available); - - if (ev->eof && ev->available == 0) { - if (ev->err_no) - ngx_log_error(NGX_LOG_ERR, ev->log, ev->err_no, - "ngx_http_process_request: " - "read failed while %s", ev->action); - - return -1; - } - - if ((n = read(c->fd, r->buff->last, r->buff->end - r->buff->last)) == -1) { + n = ngx_event_recv(ev, r->buff->last, r->buff->end - r->buff->last); - if (errno == NGX_EWOULDBLOCK) { - ngx_log_error(NGX_LOG_INFO, ev->log, errno, - "ngx_http_process_request: " - "EAGAIN while %s", ev->action); - return 0; - } + if (n == -2) + return 0; - ngx_log_error(NGX_LOG_ERR, ev->log, errno, - "ngx_http_process_request: " - "read failed while %s", ev->action); + if (n == -1) return -1; - } - ngx_log_debug(ev->log, "http read %d", n); + ngx_log_debug(ev->log, "http read %d" _ n); if (n == 0) { if (ev->unexpected_eof) { @@ -138,8 +117,6 @@ int ngx_http_process_request(ngx_event_t *ev) return ngx_http_close_request(ev); } - n == r->buff->end - r->buff->last; - if (!ev->read_discarded) { r->buff->last += n; @@ -168,8 +145,8 @@ static int ngx_process_http_request_line(ngx_http_request_t *r) if ((n = ngx_read_http_request_line(r)) == 1) { *r->uri_end = '\0'; - ngx_log_debug(r->connection->log, "HTTP: %d, %d, %s", - r->method, r->http_version, r->uri_start); + ngx_log_debug(r->connection->log, "HTTP: %d, %d, %s" _ + r->method _ r->http_version _ r->uri_start); r->state_handler = ngx_process_http_request_header; r->connection->read->action = "reading client request headers"; } @@ -184,8 +161,8 @@ static int ngx_process_http_request_header(ngx_http_request_t *r) while ((n = ngx_read_http_header_line(r)) == 1) { *r->header_name_end = '\0'; *r->header_end = '\0'; - ngx_log_debug(r->connection->log, "HTTP header: '%s: %s'", - r->header_name_start, r->header_start); + ngx_log_debug(r->connection->log, "HTTP header: '%s: %s'" _ + r->header_name_start _ r->header_start); } if (n != 2) @@ -203,6 +180,13 @@ static int ngx_process_http_request_header(ngx_http_request_t *r) static int ngx_process_http_request(ngx_http_request_t *r) { + return -1; +} + +#if 0 + +static int ngx_process_http_request(ngx_http_request_t *r) +{ int fd; struct stat sb; ngx_http_header_out_t *header_out; @@ -258,6 +242,8 @@ static int ngx_process_http_request(ngx_http_request_t *r) return 0; } +#endif + static int ngx_http_close_request(ngx_event_t *ev) { ngx_connection_t *c = (ngx_connection_t *) ev->data; @@ -269,5 +255,3 @@ static int ngx_http_close_request(ngx_event_t *ev) return ngx_event_close(ev); } - -#endif diff --git a/src/http/ngx_http_filter.h b/src/http/ngx_http_filter.h new file mode 100644 index 000000000..9d0a53ba3 --- /dev/null +++ b/src/http/ngx_http_filter.h @@ -0,0 +1,10 @@ +#ifndef _NGX_HTTP_FILTER_H_INCLUDED_ +#define _NGX_HTTP_FILTER_H_INCLUDED_ + + +#define NGX_HTTP_FILTER_ERROR -1 +#define NGX_HTTP_FILTER_AGAIN 0 +#define NGX_HTTP_FILTER_DONE 1 + + +#endif /* _NGX_HTTP_FILTER_H_INCLUDED_ */ diff --git a/src/http/ngx_http_parse.c b/src/http/ngx_http_parse.c new file mode 100644 index 000000000..6bfab9bfb --- /dev/null +++ b/src/http/ngx_http_parse.c @@ -0,0 +1,475 @@ + +#include <ngx_config.h> +#include <ngx_http.h> + +int ngx_read_http_request_line(ngx_http_request_t *r) +{ + char ch; + char *buff = r->buff->buff; + char *p = r->buff->pos; + enum { + rl_start = 0, + rl_space_after_method, + rl_spaces_before_uri, + rl_after_slash_in_uri, + rl_check_uri, + rl_uri, + rl_http_09, + rl_http_version, + rl_first_major_digit, + rl_major_digit, + rl_first_minor_digit, + rl_minor_digit, + rl_almost_done, + rl_done + } state = r->state; + + while (p < r->buff->last && state < rl_done) { + ch = *p++; + +/* +printf("\nstate: %d, pos: %x, end: %x, char: '%c' buf: %s", + state, p, r->buff->last, ch, p); +*/ + + /* GCC complie it as jump table */ + + switch (state) { + + /* HTTP methods: GET, HEAD, POST */ + case rl_start: + switch (ch) { + case 'G': + if (p + 1 >= r->buff->last) + return 0; + + if (*p != 'E' || *(p + 1) != 'T') + return NGX_HTTP_INVALID_METHOD; + + r->method = NGX_HTTP_GET; + p += 2; + break; + + case 'H': + if (p + 2 >= r->buff->last) + return 0; + + if (*p != 'E' || *(p + 1) != 'A' || *(p + 2) != 'D') + return NGX_HTTP_INVALID_METHOD; + + r->method = NGX_HTTP_HEAD; + p += 3; + break; + + case 'P': + if (p + 2 >= r->buff->last) + return 0; + + if (*p != 'O' || *(p + 1) != 'S' || *(p + 2) != 'T') + return NGX_HTTP_INVALID_METHOD; + + r->method = NGX_HTTP_POST; + p += 3; + break; + + default: + return NGX_HTTP_INVALID_METHOD; + } + + state = rl_space_after_method; + break; + + /* single space after method */ + case rl_space_after_method: + switch (ch) { + case ' ': + state = rl_spaces_before_uri; + break; + default: + return NGX_HTTP_INVALID_METHOD; + } + break; + + /* space* before URI */ + case rl_spaces_before_uri: + switch (ch) { + case '/': + r->uri_start = p - 1; + state = rl_after_slash_in_uri; + break; + case ' ': + break; + default: + r->unusual_uri = 1; + r->uri_start = p - 1; + state = rl_uri; + break; + } + break; + + /* check dot after slash */ + case rl_after_slash_in_uri: + switch (ch) { + case CR: + r->uri_end = p - 1; + r->http_minor = 9; + state = rl_almost_done; + break; + case LF: + r->uri_end = p - 1; + r->http_minor = 9; + state = rl_done; + break; + case ' ': + r->uri_end = p - 1; + state = rl_http_09; + break; + case '.': + r->complex_uri = 1; + state = rl_uri; + break; + case '/': + r->complex_uri = 1; + state = rl_uri; + break; + case '?': + r->args_start = p; + state = rl_uri; + break; + default: + state = rl_check_uri; + break; + } + break; + + /* check slash in URI */ + case rl_check_uri: + switch (ch) { + case CR: + r->uri_end = p - 1; + r->http_minor = 9; + state = rl_almost_done; + break; + case LF: + r->uri_end = p - 1; + r->http_minor = 9; + state = rl_done; + break; + case ' ': + r->uri_end = p - 1; + state = rl_http_09; + break; + case '.': + r->uri_ext = p; + break; + case '/': + r->uri_ext = NULL; + state = rl_after_slash_in_uri; + break; + case '?': + r->args_start = p; + state = rl_uri; + break; + } + break; + + /* URI */ + case rl_uri: + switch (ch) { + case CR: + r->uri_end = p - 1; + r->http_minor = 9; + state = rl_almost_done; + break; + case LF: + r->uri_end = p - 1; + r->http_minor = 9; + state = rl_done; + break; + case ' ': + r->uri_end = p - 1; + state = rl_http_09; + break; + } + break; + + /* space+ after URI */ + case rl_http_09: + switch (ch) { + case ' ': + break; + case CR: + r->http_minor = 9; + state = rl_almost_done; + break; + case LF: + r->http_minor = 9; + state = rl_done; + break; + case 'H': + state = rl_http_version; + break; + default: + return NGX_HTTP_INVALID_REQUEST; + } + break; + + /* TTP/ */ + case rl_http_version: + if (p + 2 >= r->buff->last) { + r->state = rl_http_version; + r->buff->pos = p - 1; + return 0; + } + + if (ch != 'T' || *p != 'T' || *(p + 1) != 'P' || *(p + 2) != '/') + return NGX_HTTP_INVALID_REQUEST; + + p += 3; + state = rl_first_major_digit; + break; + + /* first digit of major HTTP version */ + case rl_first_major_digit: + if (ch < '1' || ch > '9') + return NGX_HTTP_INVALID_REQUEST; + + r->http_major = ch - '0'; + state = rl_major_digit; + break; + + /* major HTTP version or dot */ + case rl_major_digit: + if (ch == '.') { + state = rl_first_minor_digit; + break; + } + + if (ch < '0' || ch > '9') + return NGX_HTTP_INVALID_REQUEST; + + r->http_major = r->http_major * 10 + ch - '0'; + break; + + /* first digit of minor HTTP version */ + case rl_first_minor_digit: + if (ch < '0' || ch > '9') + return NGX_HTTP_INVALID_REQUEST; + + r->http_minor = ch - '0'; + + state = rl_minor_digit; + break; + + /* minor HTTP version or end of request line */ + case rl_minor_digit: + if (ch == CR) { + state = rl_almost_done; + break; + } + + if (ch == LF) { + state = rl_done; + break; + } + + if (ch < '0' || ch > '9') + return NGX_HTTP_INVALID_REQUEST; + + r->http_minor = r->http_minor * 10 + ch - '0'; + break; + + /* end of request line */ + case rl_almost_done: + switch (ch) { + case LF: + state = rl_done; + break; + default: + return NGX_HTTP_INVALID_METHOD; + } + break; + } + } + + r->buff->pos = p; + + if (state == rl_done) { + r->http_version = r->http_major * 1000 + r->http_minor; + r->state = rl_start; + return 1; + } else { + r->state = state; + return 0; + } +} + +int ngx_read_http_header_line(ngx_http_request_t *r) +{ + char c, ch; + char *buff = r->buff->buff; + char *p = r->buff->pos; + enum { + hl_start = 0, + hl_name, + hl_space_before_value, + hl_value, + hl_space_after_value, + hl_almost_done, + header_almost_done, + hl_done, + header_done + } state = r->state; + + while (p < r->buff->last && state < hl_done) { + ch = *p++; + +/* +printf("\nstate: %d, pos: %x, end: %x, char: '%c' buf: %s", + state, p, r->buff->last, ch, p); +*/ + + switch (state) { + + /* first char */ + case hl_start: + switch (ch) { + case CR: + r->header_end = p - 1; + state = header_almost_done; + break; + case LF: + r->header_end = p - 1; + state = header_done; + break; + default: + state = hl_name; + r->header_name_start = p - 1; + + c = ch | 0x20; + if (c >= 'a' && c <= 'z') + break; + + if (ch == '-') + break; + + if (ch >= '0' && ch <= '9') + break; + + return NGX_HTTP_INVALID_HEADER; + + } + break; + + /* header name */ + case hl_name: + c = ch | 0x20; + if (c >= 'a' && c <= 'z') + break; + + if (ch == ':') { + r->header_name_end = p - 1; + state = hl_space_before_value; + break; + } + + if (ch == '-') + break; + + if (ch >= '0' && ch <= '9') + break; + + return NGX_HTTP_INVALID_HEADER; + + /* space* before header value */ + case hl_space_before_value: + switch (ch) { + case ' ': + break; + case CR: + r->header_start = r->header_end = p - 1; + state = hl_almost_done; + break; + case LF: + r->header_start = r->header_end = p - 1; + state = hl_done; + break; + default: + r->header_start = p - 1; + state = hl_value; + break; + } + break; + + /* header value */ + case hl_value: + switch (ch) { + case ' ': + r->header_end = p - 1; + state = hl_space_after_value; + break; + case CR: + r->header_end = p - 1; + state = hl_almost_done; + break; + case LF: + r->header_end = p - 1; + state = hl_done; + break; + } + break; + + /* space* before end of header line */ + case hl_space_after_value: + switch (ch) { + case ' ': + break; + case CR: + state = hl_almost_done; + break; + case LF: + state = hl_done; + break; + default: + state = hl_value; + break; + } + break; + + /* end of header line */ + case hl_almost_done: + switch (ch) { + case LF: + state = hl_done; + break; + default: + return NGX_HTTP_INVALID_HEADER; + } + break; + + /* end of header */ + case header_almost_done: + switch (ch) { + case LF: + state = header_done; + break; + default: + return NGX_HTTP_INVALID_HEADER; + } + break; + } + } + + r->buff->pos = p; + + if (state == hl_done) { + r->state = hl_start; + return 1; + } else if (state == header_done) { + r->state = hl_start; + return 2; + } else { + r->state = state; + return 0; + } +} diff --git a/src/http/ngx_http_write_filter.c b/src/http/ngx_http_write_filter.c new file mode 100644 index 000000000..5e4eaa612 --- /dev/null +++ b/src/http/ngx_http_write_filter.c @@ -0,0 +1,82 @@ + +#include <ngx_config.h> + +#include <ngx_hunk.h> +#include <ngx_http.h> +#include <ngx_http_filter.h> +#include <ngx_event_write.h> + +#include <ngx_http_write_filter.h> + + +ngx_http_module_t ngx_http_write_filter_module; + + +/* STUB */ +static ngx_http_write_filter_ctx_t module_ctx; + +void ngx_http_write_filter_init() +{ + module_ctx.buffer_output = 10240; + module_ctx.out = NULL; + + ngx_http_write_filter_module.ctx = &module_ctx; +} +/* */ + + +int ngx_http_write_filter(ngx_http_request_t *r, ngx_chain_t *in) +{ + int last; + off_t size, flush; + ngx_chain_t *ch, **prev, *chain; + ngx_http_write_filter_ctx_t *ctx; + + ctx = (ngx_http_write_filter_ctx_t *) + ngx_get_module_ctx(r->main ? r->main : r, + &ngx_http_write_filter_module); + size = flush = 0; + last = 0; + prev = &ctx->out; + + /* find size, flush point and last link of saved chain */ + for (ch = ctx->out; ch; ch = ch->next) { + prev = &ch->next; + size += ch->hunk->last.file - ch->hunk->pos.file; + + if (ch->hunk->type & NGX_HUNK_FLUSH) + flush = size; + + if (ch->hunk->type & NGX_HUNK_LAST) + last = 1; + } + + /* add new chain to existent one */ + for (/* void */; in; in = in->next) { + ngx_test_null(ch, ngx_palloc(r->pool, sizeof(ngx_chain_t)), + NGX_HTTP_FILTER_ERROR); + + ch->hunk = in->hunk; + ch->next = NULL; + *prev = ch; + prev = &ch->next; + size += ch->hunk->last.file - ch->hunk->pos.file; + + if (ch->hunk->type & NGX_HUNK_FLUSH) + flush = size; + + if (ch->hunk->type & NGX_HUNK_LAST) + last = 1; + } + + if (flush == 0 && size < ctx->buffer_output) + return NGX_HTTP_FILTER_DONE; + + chain = ngx_event_write(r->connection, ctx->out, flush); + if (chain == (ngx_chain_t *) -1) + return NGX_HTTP_FILTER_ERROR; + + ctx->out = chain; + + return (chain ? NGX_HTTP_FILTER_AGAIN : NGX_HTTP_FILTER_DONE); +} diff --git a/src/http/ngx_http_write_filter.h b/src/http/ngx_http_write_filter.h new file mode 100644 index 000000000..6a2c6f24d --- /dev/null +++ b/src/http/ngx_http_write_filter.h @@ -0,0 +1,11 @@ +#ifndef _NGX_HTTP_WRITE_FILTER_H_INCLUDED_ +#define _NGX_HTTP_WRITE_FILTER_H_INCLUDED_ + + +typedef struct { + ngx_chain_t *out; + size_t buffer_output; +} ngx_http_write_filter_ctx_t; + + +#endif /* _NGX_HTTP_WRITE_FILTER_H_INCLUDED_ */ |
