3 * Copyright (C) Igor Sysoev
4 * Copyright (C) Nginx, Inc.
8 #include <ngx_config.h>
15 } ngx_http_copy_filter_conf_t
;
18 #if (NGX_HAVE_FILE_AIO)
19 static void ngx_http_copy_aio_handler(ngx_output_chain_ctx_t
*ctx
,
21 static void ngx_http_copy_aio_event_handler(ngx_event_t
*ev
);
22 #if (NGX_HAVE_AIO_SENDFILE)
23 static void ngx_http_copy_aio_sendfile_event_handler(ngx_event_t
*ev
);
27 static void *ngx_http_copy_filter_create_conf(ngx_conf_t
*cf
);
28 static char *ngx_http_copy_filter_merge_conf(ngx_conf_t
*cf
,
29 void *parent
, void *child
);
30 static ngx_int_t
ngx_http_copy_filter_init(ngx_conf_t
*cf
);
33 static ngx_command_t ngx_http_copy_filter_commands
[] = {
35 { ngx_string("output_buffers"),
36 NGX_HTTP_MAIN_CONF
|NGX_HTTP_SRV_CONF
|NGX_HTTP_LOC_CONF
|NGX_CONF_TAKE2
,
37 ngx_conf_set_bufs_slot
,
38 NGX_HTTP_LOC_CONF_OFFSET
,
39 offsetof(ngx_http_copy_filter_conf_t
, bufs
),
46 static ngx_http_module_t ngx_http_copy_filter_module_ctx
= {
47 NULL
, /* preconfiguration */
48 ngx_http_copy_filter_init
, /* postconfiguration */
50 NULL
, /* create main configuration */
51 NULL
, /* init main configuration */
53 NULL
, /* create server configuration */
54 NULL
, /* merge server configuration */
56 ngx_http_copy_filter_create_conf
, /* create location configuration */
57 ngx_http_copy_filter_merge_conf
/* merge location configuration */
61 ngx_module_t ngx_http_copy_filter_module
= {
63 &ngx_http_copy_filter_module_ctx
, /* module context */
64 ngx_http_copy_filter_commands
, /* module directives */
65 NGX_HTTP_MODULE
, /* module type */
66 NULL
, /* init master */
67 NULL
, /* init module */
68 NULL
, /* init process */
69 NULL
, /* init thread */
70 NULL
, /* exit thread */
71 NULL
, /* exit process */
72 NULL
, /* exit master */
77 static ngx_http_output_body_filter_pt ngx_http_next_body_filter
;
81 ngx_http_copy_filter(ngx_http_request_t
*r
, ngx_chain_t
*in
)
85 ngx_output_chain_ctx_t
*ctx
;
86 ngx_http_core_loc_conf_t
*clcf
;
87 ngx_http_copy_filter_conf_t
*conf
;
91 ngx_log_debug2(NGX_LOG_DEBUG_HTTP
, c
->log
, 0,
92 "http copy filter: \"%V?%V\"", &r
->uri
, &r
->args
);
94 ctx
= ngx_http_get_module_ctx(r
, ngx_http_copy_filter_module
);
97 ctx
= ngx_pcalloc(r
->pool
, sizeof(ngx_output_chain_ctx_t
));
102 ngx_http_set_ctx(r
, ctx
, ngx_http_copy_filter_module
);
104 conf
= ngx_http_get_module_loc_conf(r
, ngx_http_copy_filter_module
);
105 clcf
= ngx_http_get_module_loc_conf(r
, ngx_http_core_module
);
107 ctx
->sendfile
= c
->sendfile
;
108 ctx
->need_in_memory
= r
->main_filter_need_in_memory
109 || r
->filter_need_in_memory
;
110 ctx
->need_in_temp
= r
->filter_need_temporary
;
112 ctx
->alignment
= clcf
->directio_alignment
;
115 ctx
->bufs
= conf
->bufs
;
116 ctx
->tag
= (ngx_buf_tag_t
) &ngx_http_copy_filter_module
;
118 ctx
->output_filter
= (ngx_output_chain_filter_pt
)
119 ngx_http_next_body_filter
;
122 #if (NGX_HAVE_FILE_AIO)
125 ctx
->aio_handler
= ngx_http_copy_aio_handler
;
127 #if (NGX_HAVE_AIO_SENDFILE)
128 c
->aio_sendfile
= (clcf
->aio
== NGX_HTTP_AIO_SENDFILE
);
133 if (in
&& in
->buf
&& ngx_buf_size(in
->buf
)) {
134 r
->request_output
= 1;
138 #if (NGX_HAVE_FILE_AIO)
143 rc
= ngx_output_chain(ctx
, in
);
145 if (ctx
->in
== NULL
) {
146 r
->buffered
&= ~NGX_HTTP_COPY_BUFFERED
;
149 r
->buffered
|= NGX_HTTP_COPY_BUFFERED
;
152 ngx_log_debug3(NGX_LOG_DEBUG_HTTP
, c
->log
, 0,
153 "http copy filter: %i \"%V?%V\"", rc
, &r
->uri
, &r
->args
);
155 #if (NGX_HAVE_FILE_AIO && NGX_HAVE_AIO_SENDFILE)
157 if (c
->busy_sendfile
) {
161 ngx_http_ephemeral_t
*e
;
164 c
->busy_sendfile
= NULL
;
168 file
= c
->busy_sendfile
->file
;
169 offset
= c
->busy_sendfile
->file_pos
;
172 c
->aio_sendfile
= (offset
!= file
->aio
->last_offset
);
173 file
->aio
->last_offset
= offset
;
175 if (c
->aio_sendfile
== 0) {
176 ngx_log_error(NGX_LOG_ALERT
, c
->log
, 0,
177 "sendfile(%V) returned busy again",
182 c
->busy_sendfile
= NULL
;
183 e
= (ngx_http_ephemeral_t
*) &r
->uri_start
;
185 n
= ngx_file_aio_read(file
, &e
->aio_preload
, 1, offset
, r
->pool
);
194 if (rc
== NGX_AGAIN
) {
196 file
->aio
->handler
= ngx_http_copy_aio_sendfile_event_handler
;
209 #if (NGX_HAVE_FILE_AIO)
212 ngx_http_copy_aio_handler(ngx_output_chain_ctx_t
*ctx
, ngx_file_t
*file
)
214 ngx_http_request_t
*r
;
219 file
->aio
->handler
= ngx_http_copy_aio_event_handler
;
228 ngx_http_copy_aio_event_handler(ngx_event_t
*ev
)
230 ngx_event_aio_t
*aio
;
231 ngx_http_request_t
*r
;
239 r
->connection
->write
->handler(r
->connection
->write
);
243 #if (NGX_HAVE_AIO_SENDFILE)
246 ngx_http_copy_aio_sendfile_event_handler(ngx_event_t
*ev
)
248 ngx_event_aio_t
*aio
;
249 ngx_http_request_t
*r
;
258 r
->connection
->write
->handler(r
->connection
->write
);
266 ngx_http_copy_filter_create_conf(ngx_conf_t
*cf
)
268 ngx_http_copy_filter_conf_t
*conf
;
270 conf
= ngx_palloc(cf
->pool
, sizeof(ngx_http_copy_filter_conf_t
));
282 ngx_http_copy_filter_merge_conf(ngx_conf_t
*cf
, void *parent
, void *child
)
284 ngx_http_copy_filter_conf_t
*prev
= parent
;
285 ngx_http_copy_filter_conf_t
*conf
= child
;
287 ngx_conf_merge_bufs_value(conf
->bufs
, prev
->bufs
, 1, 32768);
294 ngx_http_copy_filter_init(ngx_conf_t
*cf
)
296 ngx_http_next_body_filter
= ngx_http_top_body_filter
;
297 ngx_http_top_body_filter
= ngx_http_copy_filter
;