From 80e5d59897c4b2e9bac8b4ad4d9ed55ae90607f3 Mon Sep 17 00:00:00 2001 From: Dridi Boukelmoune Date: Fri, 8 Apr 2022 20:03:47 +0200 Subject: [PATCH] vmod_std: New partial arg for std.cache_req_body() This parameter defaults to false to avoid breaking existing code. --- bin/varnishtest/tests/s00013.vtc | 50 ++++++++++++++++++++++++++++++++ vmod/vmod_std.c | 4 +-- vmod/vmod_std.vcc | 8 +++-- 3 files changed, 58 insertions(+), 4 deletions(-) create mode 100644 bin/varnishtest/tests/s00013.vtc diff --git a/bin/varnishtest/tests/s00013.vtc b/bin/varnishtest/tests/s00013.vtc new file mode 100644 index 00000000000..bc3991fdca7 --- /dev/null +++ b/bin/varnishtest/tests/s00013.vtc @@ -0,0 +1,50 @@ +varnishtest "partial std.cache_req_body()" + +barrier b1 sock 2 + +server s1 { + close + + accept + rxreq + expect req.bodylen == 150 + txresp +} -start + +varnish v1 -cliok "param.set debug +syncvsl,+flush_head,+slow_bereq" +varnish v1 -vcl+backend { + import std; + import vtc; + + sub vcl_recv { + std.cache_req_body(100b, partial=true); + } + + sub vcl_backend_fetch { + if (bereq.retries == 1) { + vtc.barrier_sync("${b1_sock}"); + } + } + + sub vcl_backend_error { + return (retry); + } +} -start + +logexpect l1 -v v1 -i FetchError -g raw { + expect 0 1002 FetchError "Failed to send a partial req.body" + expect 0 1002 FetchError "backend write error" +} -start + +client c1 { + txreq -method POST -nolen -hdr "transfer-encoding: chunked" + chunkedlen 100 + barrier b1 sync + chunkedlen 50 + chunkedlen 0 + rxresp + expect resp.status == 200 +} -run + +logexpect l1 -wait +server s1 -wait diff --git a/vmod/vmod_std.c b/vmod/vmod_std.c index fe20c202530..a21cb5b6756 100644 --- a/vmod/vmod_std.c +++ b/vmod/vmod_std.c @@ -239,11 +239,11 @@ vmod_timestamp(VRT_CTX, VCL_STRING label) } VCL_BOOL v_matchproto_(td_std_cache_req_body) -vmod_cache_req_body(VRT_CTX, VCL_BYTES size) +vmod_cache_req_body(VRT_CTX, VCL_BYTES size, VCL_BOOL partial) { CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC); size = vmax_t(VCL_BYTES, size, 0); - if (VRT_CacheReqBody(ctx, (size_t)size, 0) < 0) + if (VRT_CacheReqBody(ctx, (size_t)size, partial) < 0) return (0); return (1); } diff --git a/vmod/vmod_std.vcc b/vmod/vmod_std.vcc index acd273c884e..4be0e789c09 100644 --- a/vmod/vmod_std.vcc +++ b/vmod/vmod_std.vcc @@ -505,14 +505,18 @@ Example:: set req.http.My-Env = std.getenv("MY_ENV"); -$Function BOOL cache_req_body(BYTES size) +$Function BOOL cache_req_body(BYTES size, BOOL partial = 0) Caches the request body if it is smaller than *size*. Returns ``true`` if the body was cached, ``false`` otherwise. Normally the request body can only be sent once. Caching it enables retrying backend requests with a request body, as usually the case -with ``POST`` and ``PUT``. +with ``POST`` and ``PUT``. When the ``partial`` argument is ``true``, +the request body may be larger than ``size`` and only up to ``size`` +bytes may be cached. This also enables retrying backend requests with +a request body, unless request body bytes were consumed beyond the +partial cached payload. Example::