Skip to content

Commit

Permalink
vmod_std: New partial arg for std.cache_req_body()
Browse files Browse the repository at this point in the history
This parameter defaults to false to avoid breaking existing code.
  • Loading branch information
dridi committed Apr 12, 2022
1 parent 4f90788 commit e5d75ad
Show file tree
Hide file tree
Showing 3 changed files with 119 additions and 4 deletions.
111 changes: 111 additions & 0 deletions bin/varnishtest/tests/s00013.vtc
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
varnishtest "partial std.cache_req_body()"

barrier b1 sock 2
barrier b2 sock 2

server s1 {
# chunked with retry
close

accept
rxreq
expect req.http.transfer-encoding == chunked
expect req.bodylen == 150
txresp
expect_close

# straight with retry
accept
close

accept
rxreq
expect req.http.content-length == 19
expect req.bodylen == 19
expect req.body == "hello partial world"
txresp
expect_close

# chunked pipe
accept
rxreq
expect req.http.transfer-encoding == chunked
expect req.bodylen == 150
txresp
close

# straight pipe
accept
rxreq
expect req.http.content-length == 19
expect req.bodylen == 19
expect req.body == "hello partial world"
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(10b, partial=true);
}

sub vcl_backend_fetch {
if (bereq.retries == 1) {
vtc.barrier_sync(bereq.http.barrier);
}
set bereq.http.connection = "close";
}

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" \
-hdr "barrier: ${b1_sock}"
chunkedlen 100
barrier b1 sync
chunkedlen 50
chunkedlen 0
rxresp
expect resp.status == 200
expect resp.http.x-varnish == 1001

txreq -method POST -nolen -hdr "content-length: 19" \
-hdr "barrier: ${b2_sock}"
send "hello partial "
barrier b2 sync
send "world"
rxresp
expect resp.status == 200
expect resp.http.x-varnish == 1004

txreq -method PIPE -nolen -hdr "transfer-encoding: chunked"
chunkedlen 100
chunkedlen 50
chunkedlen 0
rxresp
expect resp.status == 200
expect resp.http.x-varnish == <undef>
expect_close
} -run

client c2 {
txreq -method PIPE -nolen -hdr "content-length: 19"
send "hello partial world"
rxresp
expect resp.status == 200
expect resp.http.x-varnish == <undef>
} -run

logexpect l1 -wait
server s1 -wait
4 changes: 2 additions & 2 deletions vmod/vmod_std.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down
8 changes: 6 additions & 2 deletions vmod/vmod_std.vcc
Original file line number Diff line number Diff line change
Expand Up @@ -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::

Expand Down

0 comments on commit e5d75ad

Please sign in to comment.