Skip to content

Commit 873bfc7

Browse files
committed
Use byte array instead of string for body filtering
1 parent d510ac8 commit 873bfc7

File tree

2 files changed

+62
-46
lines changed

2 files changed

+62
-46
lines changed

src/ngx_http_redirectionio_module.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -558,6 +558,8 @@ static void ngx_http_redirectionio_log_callback(const char* log_str, const void*
558558
if (level <= 1) {
559559
ngx_log_error(NGX_LOG_ERR, (ngx_log_t *)data, 0, "redirectionio api error: %s", log_str);
560560
}
561+
562+
free((char *)log_str);
561563
}
562564

563565
static void ngx_http_redirectionio_context_cleanup(void *context) {

src/ngx_http_redirectionio_module_filter.c

Lines changed: 60 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ static ngx_int_t ngx_http_redirectionio_header_read(ngx_http_request_t *r, ngx_t
88

99
static 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

1313
ngx_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

279295
static 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

Comments
 (0)