@@ -8,7 +8,7 @@ static ngx_int_t ngx_http_redirectionio_header_read(ngx_http_request_t *r, ngx_t
88
99static ngx_int_t ngx_http_redirectionio_header_content_type_read (ngx_http_request_t * r , struct REDIRECTIONIO_HeaderMap * * first );
1010
11- static ngx_int_t ngx_http_redirectionio_buffer_read (ngx_buf_t * buffer , char * * output );
11+ static ngx_int_t ngx_http_redirectionio_buffer_read (ngx_buf_t * buffer , struct REDIRECTIONIO_Buffer * output );
1212
1313ngx_int_t ngx_http_redirectionio_match_on_response_status_header_filter (ngx_http_request_t * r ) {
1414 ngx_http_redirectionio_ctx_t * ctx ;
@@ -203,24 +203,24 @@ static ngx_int_t ngx_http_redirectionio_create_filter_body(ngx_http_request_t *r
203203 return ngx_http_next_header_filter (r );
204204}
205205
206- ngx_int_t ngx_http_redirectionio_body_filter (ngx_http_request_t * r , ngx_chain_t * in ) {
206+ ngx_int_t ngx_http_redirectionio_body_filter (ngx_http_request_t * r , ngx_chain_t * input_chain ) {
207207 ngx_http_redirectionio_ctx_t * ctx ;
208208 ngx_http_redirectionio_conf_t * conf ;
209- ngx_chain_t * out , * cl , * tl , * ll ;
209+ ngx_chain_t * out_chain , * current_chain , * tmp_chain , * last_chain , * previous_chain ;
210210 size_t tsize ;
211211 ngx_int_t rc ;
212212
213213 conf = ngx_http_get_module_loc_conf (r , ngx_http_redirectionio_module );
214214
215215 if (conf -> enable == NGX_HTTP_REDIRECTIONIO_OFF ) {
216- return ngx_http_next_body_filter (r , in );
216+ return ngx_http_next_body_filter (r , input_chain );
217217 }
218218
219219 ctx = ngx_http_get_module_ctx (r , ngx_http_redirectionio_module );
220220
221221 // Skip if no context
222222 if (ctx == NULL ) {
223- return ngx_http_next_body_filter (r , in );
223+ return ngx_http_next_body_filter (r , input_chain );
224224 }
225225
226226 // Discard body if last buffer already sent (avoid double body)
@@ -230,80 +230,96 @@ ngx_int_t ngx_http_redirectionio_body_filter(ngx_http_request_t *r, ngx_chain_t
230230
231231 // Skip if no filter_id
232232 if (ctx -> body_filter == NULL ) {
233- return ngx_http_next_body_filter (r , in );
233+ return ngx_http_next_body_filter (r , input_chain );
234234 }
235235
236- if (in == NULL ) {
237- return ngx_http_next_body_filter (r , in );
236+ if (input_chain == NULL ) {
237+ return ngx_http_next_body_filter (r , input_chain );
238238 }
239239
240- out = NULL ;
241- ll = NULL ;
240+ out_chain = NULL ;
241+ last_chain = NULL ;
242+ previous_chain = NULL ;
242243 tsize = 0 ;
243244
244- for (cl = in ; cl ; cl = cl -> next ) {
245- tl = ngx_http_redirectionio_body_filter_replace (ctx , r -> pool , cl );
245+ for (current_chain = input_chain ; current_chain ; current_chain = current_chain -> next ) {
246+ tmp_chain = ngx_http_redirectionio_body_filter_replace (ctx , r -> pool , current_chain );
246247
247- if (tl == NULL ) {
248+ // Buffered case
249+ if (tmp_chain == NULL ) {
248250 continue ;
249251 }
250252
251- // Last link is not null, set the next of it to the current one
252- if (ll != NULL ) {
253- ll -> next = tl ;
253+ // Error case: receive same thing as sended
254+ if (tmp_chain == current_chain ) {
255+ // Add chain to the one sent, and remove from in (so it's not updated)
256+ if (previous_chain == NULL ) {
257+ input_chain = current_chain -> next ;
258+ } else {
259+ previous_chain -> next = current_chain -> next ;
260+ }
261+ } else {
262+ previous_chain = current_chain ;
263+ tsize += ngx_buf_size (current_chain -> buf );
264+ }
265+
266+ // Last chain is not null, set the next of it to the current one
267+ if (last_chain != NULL ) {
268+ last_chain -> next = tmp_chain ;
254269 } else {
255- out = tl ;
270+ out_chain = tmp_chain ;
256271 }
257272
258- ll = tl ;
259- tsize += ngx_buf_size (cl -> buf );
273+ last_chain = tmp_chain ;
260274
261- if (tl -> buf -> last_buf ) {
275+ if (tmp_chain -> buf -> last_buf ) {
262276 ctx -> last_buffer_sent = 1 ;
263277 }
264278 }
265279
266280 rc = NGX_OK ;
267281
268282 // Everything is buffered
269- if (out != NULL ) {
270- rc = ngx_http_next_body_filter (r , out );
283+ if (out_chain != NULL ) {
284+ rc = ngx_http_next_body_filter (r , out_chain );
271285 }
272286
273- // Fake initial chain as sent
274- in = ngx_chain_update_sent (in , tsize );
287+ // Fake initial chain as sent (only if not null, as we may have used old ones already)
288+ if (input_chain != NULL ) {
289+ input_chain = ngx_chain_update_sent (input_chain , tsize );
290+ }
275291
276292 return rc ;
277293}
278294
279295static ngx_chain_t * ngx_http_redirectionio_body_filter_replace (ngx_http_redirectionio_ctx_t * ctx , ngx_pool_t * pool , ngx_chain_t * cl ) {
280296 ngx_chain_t * out = NULL , * el = NULL ;
281- const char * buf_in , * buf_out ;
297+ struct REDIRECTIONIO_Buffer buf_in , buf_out ;
282298 char * memory_buf ;
283299 size_t mbsize ;
284300
285- if (ngx_http_redirectionio_buffer_read (cl -> buf , ( char * * ) & buf_in ) != NGX_OK ) {
301+ if (ngx_http_redirectionio_buffer_read (cl -> buf , & buf_in ) != NGX_OK ) {
286302 return cl ;
287303 }
288304
289305 buf_out = redirectionio_action_body_filter_filter (ctx -> body_filter , buf_in );
290306
291- if (buf_out != buf_in ) {
292- free ((char * )buf_in );
307+ // Same output as input
308+ if (buf_out .data == buf_in .data ) {
309+ return cl ;
293310 }
294311
295- if (buf_out != NULL && strlen (buf_out ) > 0 ) {
296- mbsize = strlen (buf_out );
297-
312+ if (buf_out .len > 0 ) {
313+ mbsize = buf_out .len ;
298314 out = ngx_palloc (pool , sizeof (ngx_chain_t ));
299315
300316 if (out == NULL ) {
301317 return cl ;
302318 }
303319
304320 memory_buf = ngx_palloc (pool , mbsize );
305- ngx_memcpy (memory_buf , buf_out , mbsize );
306- free (( char * ) buf_out );
321+ ngx_memcpy (memory_buf , buf_out . data , mbsize );
322+ redirectionio_api_buffer_drop ( buf_out );
307323
308324 out -> next = NULL ;
309325 out -> buf = ngx_create_temp_buf (pool , mbsize );
@@ -323,7 +339,7 @@ static ngx_chain_t* ngx_http_redirectionio_body_filter_replace(ngx_http_redirect
323339 buf_out = redirectionio_action_body_filter_close (ctx -> body_filter );
324340 ctx -> body_filter = NULL ;
325341
326- if (buf_out == NULL || strlen ( buf_out ) == 0 ) {
342+ if (buf_out . len == 0 ) {
327343 if (out != NULL ) {
328344 out -> buf -> last_buf = 1 ;
329345
@@ -333,7 +349,7 @@ static ngx_chain_t* ngx_http_redirectionio_body_filter_replace(ngx_http_redirect
333349 return cl ;
334350 }
335351
336- mbsize = strlen ( buf_out ) ;
352+ mbsize = buf_out . len ;
337353 el = ngx_palloc (pool , sizeof (ngx_chain_t ));
338354
339355 if (el == NULL ) {
@@ -347,8 +363,8 @@ static ngx_chain_t* ngx_http_redirectionio_body_filter_replace(ngx_http_redirect
347363 }
348364
349365 memory_buf = ngx_palloc (pool , mbsize );
350- ngx_memcpy (memory_buf , buf_out , mbsize );
351- free (( char * ) buf_out );
366+ ngx_memcpy (memory_buf , buf_out . data , mbsize );
367+ redirectionio_api_buffer_drop ( buf_out );
352368
353369 el -> next = NULL ;
354370 el -> buf = ngx_create_temp_buf (pool , mbsize );
@@ -432,15 +448,14 @@ static ngx_int_t ngx_http_redirectionio_header_content_type_read(ngx_http_reques
432448 return NGX_OK ;
433449}
434450
435- static ngx_int_t ngx_http_redirectionio_buffer_read (ngx_buf_t * buffer , char * * output ) {
451+ static ngx_int_t ngx_http_redirectionio_buffer_read (ngx_buf_t * buffer , struct REDIRECTIONIO_Buffer * output ) {
436452#if (NGX_HAVE_SENDFILE64 )
437453 off_t offset ;
438454#else
439455 int32_t offset ;
440456#endif
441457 size_t bsize , readed = 0 ;
442458 ssize_t n ;
443- char * data ;
444459
445460 bsize = ngx_buf_size (buffer );
446461
@@ -452,21 +467,23 @@ static ngx_int_t ngx_http_redirectionio_buffer_read(ngx_buf_t *buffer, char **ou
452467 return NGX_DONE ;
453468 }
454469
455- data = malloc (bsize + 1 );
470+ output -> data = malloc (bsize );
471+ output -> len = bsize ;
456472
457473 if (ngx_buf_in_memory (buffer )) {
458- ngx_memcpy (data , buffer -> pos , bsize );
474+ ngx_memcpy (output -> data , buffer -> pos , bsize );
459475 } else if (buffer -> in_file ) {
460476#if (NGX_HAVE_SENDFILE64 )
461477 offset = buffer -> file_pos ;
462478#else
463479 offset = (int32_t ) buffer -> file_pos ;
464480#endif
465481 while (readed < bsize ) {
466- n = pread (buffer -> file -> fd , data , bsize - readed , offset + readed );
482+ n = pread (buffer -> file -> fd , output -> data , bsize - readed , offset + readed );
467483
468484 if (n <= 0 ) {
469- free (data );
485+ free (output -> data );
486+ output -> len = 0 ;
470487
471488 return NGX_ERROR ;
472489 }
@@ -475,8 +492,5 @@ static ngx_int_t ngx_http_redirectionio_buffer_read(ngx_buf_t *buffer, char **ou
475492 }
476493 }
477494
478- * (data + bsize ) = '\0' ;
479- * output = data ;
480-
481495 return NGX_OK ;
482496}
0 commit comments