Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
L
libvmod-zipflow
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
uplex-varnish
libvmod-zipflow
Commits
7d378554
Unverified
Commit
7d378554
authored
Jul 25, 2023
by
Nils Goroll
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Make subreq() work
parent
99a7d77f
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
514 additions
and
55 deletions
+514
-55
configure.ac
configure.ac
+10
-0
Makefile.am
src/Makefile.am
+4
-2
flint.lnt
src/flint.lnt
+4
-1
vmod_zipflow.c
src/vmod_zipflow.c
+367
-46
vmod_zipflow.vcc
src/vmod_zipflow.vcc
+14
-6
sub-coalesce.vtc
src/vtc/sub-coalesce.vtc
+64
-0
sub.vtc
src/vtc/sub.vtc
+51
-0
No files found.
configure.ac
View file @
7d378554
...
...
@@ -25,6 +25,16 @@ AC_ARG_WITH([rst2man],
VARNISH_PREREQ([6.0.0])
VARNISH_VMODS([zipflow])
AC_ARG_VAR([VARNISHSRC], [path to Varnish source])
if test "x$VARNISHSRC" = x; then
AC_MSG_FAILURE([Need VARNISHSRC])
fi
VARNISHSRC_CFLAGS="$VARNISHAPI_CFLAGS \
-I$VARNISHSRC/include \
-I$VARNISHSRC/bin/varnishd \
-I$VARNISHSRC/lib/libvsc"
AC_SUBST([VARNISHSRC_CFLAGS])
AC_CONFIG_FILES([
Makefile
src/Makefile
...
...
src/Makefile.am
View file @
7d378554
AM_CFLAGS
=
$(VARNISH
API
_CFLAGS)
$(ZLIB_CFLAGS)
-I
../foreign/zipflow
AM_CFLAGS
=
$(VARNISH
SRC
_CFLAGS)
$(ZLIB_CFLAGS)
-I
../foreign/zipflow
# Modules
...
...
@@ -29,7 +29,9 @@ AM_VTC_LOG_FLAGS = \
TESTS
=
\
vtc/vmod_zipflow.vtc
\
vtc/empty.vtc
\
vtc/coverage.vtc
vtc/coverage.vtc
\
vtc/sub.vtc
\
vtc/sub-coalesce.vtc
# Documentation
...
...
src/flint.lnt
View file @
7d378554
...
...
@@ -3,6 +3,7 @@
-efile(766, vmod_compat.h)
-e717 // do ... while(0)
-e663 // array to pointer
-ecall(835, dlopen)
-e801 // goto
...
...
@@ -19,4 +20,6 @@
// assert constructors not referenced
-esym(528, assert_*)
-emacro(747, WS_TASK_ALLOC_OBJ)
\ No newline at end of file
-emacro(747, WS_TASK_ALLOC_OBJ)
-emacro(527, WRONG)
-emacro(506, VSTAILQ_FOREACH_SAFE)
\ No newline at end of file
src/vmod_zipflow.c
View file @
7d378554
/*-
* Copyright 2022 UPLEX Nils Goroll Systemoptimierung
* Copyright 2022
,2023
UPLEX Nils Goroll Systemoptimierung
* All rights reserved
*
* Author: Nils Goroll <nils.goroll@uplex.de>
...
...
@@ -31,10 +31,12 @@
#include <string.h> // memset() for INIT_OBJ()
#include <stdlib.h> // strtoul()
#include <cache/cache.h>
#include <cache/cache_varnishd.h>
#include <cache/cache_transport.h>
#include <cache/cache_filter.h>
#include <vcl.h>
#include <vtim.h>
#include <VSC_main.h>
#include "vcc_zipflow_if.h"
...
...
@@ -47,16 +49,17 @@ assert_zlib(void)
assert
(
Z_DEFAULT_COMPRESSION
==
-
1
);
//lint !e506 const bool
}
// https://github.com/varnishcache/varnish-cache/pull/3815
#ifndef WS_TASK_ALLOC_OBJ
#define WS_TASK_ALLOC_OBJ(ctx, ptr, magic) do { \
ptr = WS_Alloc((ctx)->ws, sizeof *(ptr)); \
#define WS_TOP_ALLOC_OBJ(ctx, ptr, magic) do { \
AN((ctx)->req); \
AN((ctx)->req->top); \
AN((ctx)->req->top->topreq); \
ptr = WS_Alloc((ctx)->req->top->topreq->ws, \
(int)sizeof *(ptr)); \
if ((ptr) == NULL) \
VRT_fail(ctx, "Out of workspace for " #magic); \
else \
INIT_OBJ(ptr, magic); \
} while(0)
#endif
static
char
default_level
=
Z_DEFAULT_COMPRESSION
;
...
...
@@ -68,13 +71,16 @@ struct zipflow_request {
unsigned
magic
;
#define ZIPFLOW_REQUEST_MAGIC 0xaa175160
unsigned
bundle
:
1
;
unsigned
woken
:
1
;
// reembark
char
level
;
VCL_STRING
url
;
VCL_STRING
host
;
VCL_STRING
uri
;
VCL_STRING
name
;
unsigned
mode
;
VCL_TIME
atime
,
mtime
;
VSTAILQ_ENTRY
(
zipflow_request
)
list
;
struct
zipflow_top
*
top
;
pthread_cond_t
*
cond
;
};
VSTAILQ_HEAD
(
zipflow_head
,
zipflow_request
);
...
...
@@ -84,6 +90,7 @@ struct zipflow_top {
#define ZIPFLOW_TOP_MAGIC 0x5743145e
struct
zipflow_head
head
;
ZIP
*
zip
;
struct
req
*
req
;
};
static
struct
zipflow_top
*
...
...
@@ -103,7 +110,7 @@ get_zipflow_top(VRT_CTX)
return
(
zft
);
}
WS_T
ASK
_ALLOC_OBJ
(
ctx
,
zft
,
ZIPFLOW_TOP_MAGIC
);
WS_T
OP
_ALLOC_OBJ
(
ctx
,
zft
,
ZIPFLOW_TOP_MAGIC
);
if
(
zft
==
NULL
)
return
(
NULL
);
...
...
@@ -125,12 +132,26 @@ static const struct vdp vdp_zipflow[1] = {{
.
priv1
=
NULL
}};
static
int
vdp_zipsub_init
(
VRT_CTX
,
struct
vdp_ctx
*
vdc
,
void
**
priv
,
struct
objcore
*
oc
);
static
int
vdp_zipsub_fini
(
struct
vdp_ctx
*
vdc
,
void
**
priv
);
static
int
vdp_zipsub_bytes
(
struct
vdp_ctx
*
vdc
,
enum
vdp_action
act
,
void
**
priv
,
const
void
*
ptr
,
ssize_t
len
);
static
const
struct
vdp
vdp_zipsub
[
1
]
=
{{
.
name
=
"zipsub"
,
.
init
=
vdp_zipsub_init
,
.
bytes
=
vdp_zipsub_bytes
,
.
fini
=
vdp_zipsub_fini
,
.
priv1
=
NULL
}};
static
struct
zipflow_request
*
new_zipflow_request
(
VRT_CTX
,
struct
zipflow_top
*
zft
)
{
struct
zipflow_request
*
zfr
;
WS_T
ASK
_ALLOC_OBJ
(
ctx
,
zfr
,
ZIPFLOW_REQUEST_MAGIC
);
WS_T
OP
_ALLOC_OBJ
(
ctx
,
zfr
,
ZIPFLOW_REQUEST_MAGIC
);
if
(
zfr
==
NULL
)
return
(
NULL
);
...
...
@@ -182,27 +203,39 @@ get_zipflow_request(VRT_CTX)
*/
VCL_VOID
vmod_subreq
(
VRT_CTX
,
VCL_STRING
ur
l
)
vmod_subreq
(
VRT_CTX
,
VCL_STRING
ur
i
,
VCL_STRING
host
)
{
struct
zipflow_request
*
zfr
;
struct
zipflow_top
*
zft
;
CHECK_OBJ_NOTNULL
(
ctx
,
VRT_CTX_MAGIC
);
AN
(
ctx
->
method
&
(
VCL_MET_TASK_C
)
);
AN
(
ctx
->
method
&
VCL_MET_TASK_C
);
zft
=
get_zipflow_top
(
ctx
);
zfr
=
new_zipflow_request
(
ctx
,
zft
);
if
(
uri
==
NULL
||
*
uri
!=
'/'
)
{
VRT_fail
(
ctx
,
"subreq uri argument needs to start with /"
);
return
;
}
zfr
=
get_zipflow_request
(
ctx
);
if
(
zfr
==
NULL
)
return
;
zfr
->
url
=
url
;
zfr
=
new_zipflow_request
(
ctx
,
zfr
->
top
);
if
(
zfr
==
NULL
)
return
;
zfr
->
host
=
host
;
zfr
->
uri
=
uri
;
}
VCL_BOOL
vmod_is_subreq
(
VRT_CTX
)
{
struct
zipflow_request
*
zfr
;
CHECK_OBJ_NOTNULL
(
ctx
,
VRT_CTX_MAGIC
);
// XXX TODO
return
(
1
);
zfr
=
get_zipflow_request
(
ctx
);
return
(
zfr
!=
NULL
&&
zfr
->
uri
!=
NULL
);
}
VCL_VOID
...
...
@@ -410,23 +443,64 @@ vdp_zipflow_log(void *vsl, char *msg)
}
static
int
vdp_zip
flow
_init
(
VRT_CTX
,
struct
vdp_ctx
*
vdc
,
void
**
priv
,
struct
objcore
*
oc
)
vdp_zip
sub
_init
(
VRT_CTX
,
struct
vdp_ctx
*
vdc
,
void
**
priv
,
struct
objcore
*
oc
)
{
struct
zipflow_request
*
zfr
=
get_zipflow_request
(
ctx
)
;
struct
zipflow_request
*
zfr
;
struct
zipflow_top
*
zft
;
struct
req
*
req
;
(
void
)
oc
;
CHECK_OBJ_NOTNULL
(
ctx
,
VRT_CTX_MAGIC
);
(
void
)
vdc
;
AN
(
vdc
);
AN
(
priv
);
(
void
)
priv
;
CAST_OBJ_NOTNULL
(
zfr
,
*
priv
,
ZIPFLOW_REQUEST_MAGIC
);
(
void
)
oc
;
zft
=
zfr
->
top
;
CHECK_OBJ_NOTNULL
(
zft
,
ZIPFLOW_TOP_MAGIC
);
assert
(
zfr
==
VSTAILQ_FIRST
(
&
zft
->
head
));
VSTAILQ_REMOVE_HEAD
(
&
zft
->
head
,
list
);
AN
(
zft
->
zip
);
if
(
zfr
->
bundle
)
{
fill_meta
(
ctx
,
zfr
);
AZ
(
zip_meta
(
zft
->
zip
,
zfr
->
name
,
3
,
zfr
->
mode
,
(
uint32_t
)
zfr
->
atime
,
(
uint32_t
)
zfr
->
mtime
));
}
req
=
vdc
->
req
;
CHECK_OBJ_NOTNULL
(
req
,
REQ_MAGIC
);
RFC2616_Weaken_Etag
(
req
->
resp
);
if
(
req
->
resp_len
!=
0
)
req
->
resp_len
=
-
1
;
return
(
0
);
}
static
int
vdp_zipflow_init
(
VRT_CTX
,
struct
vdp_ctx
*
vdc
,
void
**
priv
,
struct
objcore
*
oc
)
{
struct
zipflow_request
*
zfr
=
get_zipflow_request
(
ctx
);
struct
zipflow_top
*
zft
;
if
(
zfr
==
NULL
)
return
(
1
);
zft
=
zfr
->
top
;
CHECK_OBJ_NOTNULL
(
zft
,
ZIPFLOW_TOP_MAGIC
);
CHECK_OBJ_NOTNULL
(
vdc
,
VDP_CTX_MAGIC
);
CHECK_OBJ_NOTNULL
(
vdc
->
req
,
REQ_MAGIC
);
assert
(
zfr
==
VSTAILQ_FIRST
(
&
zft
->
head
));
VSTAILQ_REMOVE_HEAD
(
&
zft
->
head
,
list
);
if
(
zft
->
req
)
{
VSLb
(
vdc
->
vsl
,
SLT_Error
,
"zipflow: can't be nested"
);
return
(
1
);
}
AZ
(
zft
->
req
);
zft
->
req
=
vdc
->
req
;
AZ
(
zft
->
zip
);
zft
->
zip
=
zip_pipe
(
vdc
,
vdp_zipflow_put
,
zfr
->
level
);
if
(
zft
->
zip
==
NULL
)
{
...
...
@@ -434,22 +508,28 @@ vdp_zipflow_init(VRT_CTX, struct vdp_ctx *vdc, void **priv, struct objcore *oc)
return
(
1
);
}
AZ
(
zip_log
(
zft
->
zip
,
vdc
->
vsl
,
vdp_zipflow_log
));
if
(
zfr
->
bundle
)
{
fill_meta
(
ctx
,
zfr
);
AZ
(
zip_meta
(
zft
->
zip
,
zfr
->
name
,
3
,
zfr
->
mode
,
(
uint32_t
)
zfr
->
atime
,
(
uint32_t
)
zfr
->
mtime
));
}
AN
(
priv
);
AZ
(
*
priv
);
*
priv
=
zfr
;
req
=
vdc
->
req
;
CHECK_OBJ_NOTNULL
(
req
,
REQ_MAGIC
);
RFC2616_Weaken_Etag
(
req
->
resp
);
if
(
req
->
resp_len
!=
0
)
req
->
resp_len
=
-
1
;
return
(
vdp_zipsub_init
(
ctx
,
vdc
,
priv
,
oc
));
}
static
int
vdp_zipsub_fini
(
struct
vdp_ctx
*
vdc
,
void
**
priv
)
{
struct
zipflow_request
*
zfr
;
(
void
)
vdc
;
AN
(
priv
);
zfr
=
*
priv
;
*
priv
=
NULL
;
if
(
zfr
!=
NULL
)
{
CHECK_OBJ
(
zfr
,
ZIPFLOW_REQUEST_MAGIC
);
memset
(
zfr
,
0
,
sizeof
*
zfr
);
}
return
(
0
);
}
...
...
@@ -460,7 +540,7 @@ vdp_zipflow_fini(struct vdp_ctx *vdc, void **priv)
struct
zipflow_top
*
zft
;
int
r
;
(
void
)
vdc
;
(
void
)
vdc
;
AN
(
priv
);
zfr
=
*
priv
;
*
priv
=
NULL
;
...
...
@@ -477,22 +557,22 @@ vdp_zipflow_fini(struct vdp_ctx *vdc, void **priv)
}
static
int
vdp_zip
flow
_bytes
(
struct
vdp_ctx
*
vdc
,
enum
vdp_action
act
,
void
**
priv
,
vdp_zip
sub
_bytes
(
struct
vdp_ctx
*
vdc
,
enum
vdp_action
act
,
void
**
priv
,
const
void
*
ptr
,
ssize_t
len
)
{
struct
zipflow_request
*
zfr
;
struct
zipflow_top
*
zft
;
int
r
;
(
void
)
vdc
;
(
void
)
vdc
;
(
void
)
priv
;
AN
(
priv
);
CAST_OBJ_NOTNULL
(
zfr
,
*
priv
,
ZIPFLOW_REQUEST_MAGIC
);
zft
=
zfr
->
top
;
CHECK_OBJ_NOTNULL
(
zft
,
ZIPFLOW_TOP_MAGIC
);
if
(
zfr
->
bundle
==
0
)
{
(
void
)
zip_close
(
zft
->
zip
);
return
(
0
);
}
if
(
zfr
->
bundle
==
0
)
return
(
1
);
assert
(
len
>=
0
);
r
=
zip_data
(
zft
->
zip
,
ptr
,
(
size_t
)
len
,
act
==
VDP_END
?
1
:
0
);
if
(
r
)
{
...
...
@@ -500,13 +580,254 @@ vdp_zipflow_bytes(struct vdp_ctx *vdc, enum vdp_action act, void **priv,
return
(
-
1
);
}
if
(
act
!=
VDP_END
)
return
(
0
);
return
(
0
);
}
static
void
zfr_include
(
struct
req
*
preq
,
struct
zipflow_request
*
zfr
);
*
priv
=
NULL
;
r
=
zip_close
(
zft
->
zip
);
if
(
r
)
VSLb
(
vdc
->
vsl
,
SLT_Error
,
"zip_close returned %d"
,
r
);
static
int
vdp_zipflow_bytes
(
struct
vdp_ctx
*
vdc
,
enum
vdp_action
act
,
void
**
priv
,
const
void
*
ptr
,
ssize_t
len
)
{
struct
zipflow_request
*
zfr
;
struct
zipflow_top
*
zft
;
int
r
,
c
;
r
=
vdp_zipsub_bytes
(
vdc
,
act
,
priv
,
ptr
,
len
);
if
(
r
==
0
&&
act
!=
VDP_END
)
return
(
r
);
TAKE_OBJ_NOTNULL
(
zfr
,
priv
,
ZIPFLOW_REQUEST_MAGIC
);
zft
=
zfr
->
top
;
memset
(
zfr
,
0
,
sizeof
*
zfr
);
CHECK_OBJ_NOTNULL
(
zft
,
ZIPFLOW_TOP_MAGIC
);
if
(
r
==
0
)
{
while
((
zfr
=
VSTAILQ_FIRST
(
&
zft
->
head
))
!=
NULL
)
zfr_include
(
zft
->
req
,
zfr
);
}
c
=
zip_close
(
zft
->
zip
);
if
(
c
)
VSLb
(
vdc
->
vsl
,
SLT_Error
,
"zip_close returned %d"
,
r
);
if
(
r
==
0
)
r
=
c
;
return
(
r
);
}
static
void
v_matchproto_
(
vtr_reembark_f
)
zfr_reembark
(
struct
worker
*
wrk
,
struct
req
*
req
)
{
struct
zipflow_request
*
zfr
;
(
void
)
wrk
;
CHECK_OBJ_NOTNULL
(
req
,
REQ_MAGIC
);
CAST_OBJ_NOTNULL
(
zfr
,
req
->
transport_priv
,
ZIPFLOW_REQUEST_MAGIC
);
AN
(
zfr
->
cond
);
AN
(
req
->
sp
);
Lck_Lock
(
&
req
->
sp
->
mtx
);
zfr
->
woken
=
1
;
PTOK
(
pthread_cond_signal
(
zfr
->
cond
));
Lck_Unlock
(
&
req
->
sp
->
mtx
);
}
static
int
v_matchproto_
(
vtr_minimal_response_f
)
zfr_minimal_response
(
struct
req
*
req
,
uint16_t
status
)
{
(
void
)
req
;
(
void
)
status
;
WRONG
(
"zfr_minimal_response should not be called"
);
return
(
0
);
}
static
void
v_matchproto_
(
vtr_deliver_f
)
zfr_deliver
(
struct
req
*
req
,
struct
boc
*
boc
,
int
wantbody
);
//lint -e{785} too few initializers
static
const
struct
transport
ZIPFLOW_transport
=
{
.
magic
=
TRANSPORT_MAGIC
,
.
name
=
"ZIPFLOW"
,
.
deliver
=
zfr_deliver
,
.
reembark
=
zfr_reembark
,
.
minimal_response
=
zfr_minimal_response
};
/*--------------------------------------------------------------------
* basically varnish-cache ESI
*/
static
void
zfr_include
(
struct
req
*
preq
,
struct
zipflow_request
*
zfr
)
{
struct
worker
*
wrk
;
struct
sess
*
sp
;
struct
req
*
req
;
struct
vmod_priv
*
task_priv
;
struct
vrt_ctx
ctx
[
1
];
enum
req_fsm_nxt
s
;
CHECK_OBJ_NOTNULL
(
preq
,
REQ_MAGIC
);
CHECK_OBJ_NOTNULL
(
preq
->
top
,
REQTOP_MAGIC
);
sp
=
preq
->
sp
;
CHECK_OBJ_NOTNULL
(
sp
,
SESS_MAGIC
);
CHECK_OBJ_NOTNULL
(
zfr
,
ZIPFLOW_REQUEST_MAGIC
);
wrk
=
preq
->
wrk
;
if
(
preq
->
esi_level
>=
cache_param
->
max_esi_depth
)
{
VSLb
(
preq
->
vsl
,
SLT_VCL_Error
,
"ESI depth limit reached (param max_esi_depth = %u)"
,
cache_param
->
max_esi_depth
);
return
;
}
req
=
Req_New
(
sp
);
AN
(
req
);
THR_SetRequest
(
req
);
assert
(
IS_NO_VXID
(
req
->
vsl
->
wid
));
req
->
vsl
->
wid
=
VXID_Get
(
wrk
,
VSL_CLIENTMARKER
);
wrk
->
stats
->
esi_req
++
;
req
->
esi_level
=
preq
->
esi_level
+
1
;
VSLb
(
req
->
vsl
,
SLT_Begin
,
"req %ju esi %u"
,
(
uintmax_t
)
VXID
(
preq
->
vsl
->
wid
),
req
->
esi_level
);
VSLb
(
preq
->
vsl
,
SLT_Link
,
"req %ju esi %u"
,
(
uintmax_t
)
VXID
(
req
->
vsl
->
wid
),
req
->
esi_level
);
VSLb_ts_req
(
req
,
"Start"
,
W_TIM_real
(
wrk
));
memset
(
req
->
top
,
0
,
sizeof
*
req
->
top
);
req
->
top
=
preq
->
top
;
HTTP_Setup
(
req
->
http
,
req
->
ws
,
req
->
vsl
,
SLT_ReqMethod
);
HTTP_Dup
(
req
->
http
,
preq
->
http0
);
http_SetH
(
req
->
http
,
HTTP_HDR_URL
,
zfr
->
uri
);
if
(
zfr
->
host
!=
NULL
&&
*
zfr
->
host
!=
'\0'
)
{
http_Unset
(
req
->
http
,
H_Host
);
http_SetHeader
(
req
->
http
,
zfr
->
host
);
}
http_ForceField
(
req
->
http
,
HTTP_HDR_METHOD
,
"GET"
);
http_ForceField
(
req
->
http
,
HTTP_HDR_PROTO
,
"HTTP/1.1"
);
/* Don't allow conditionals, we can't use a 304 */
http_Unset
(
req
->
http
,
H_If_Modified_Since
);
http_Unset
(
req
->
http
,
H_If_None_Match
);
/* Don't allow Range */
http_Unset
(
req
->
http
,
H_Range
);
// XXX handle gzip when zipflow supports it
http_Unset
(
req
->
http
,
H_Accept_Encoding
);
/* Client content already taken care of */
http_Unset
(
req
->
http
,
H_Content_Length
);
http_Unset
(
req
->
http
,
H_Transfer_Encoding
);
req
->
req_body_status
=
BS_NONE
;
AZ
(
req
->
vcl
);
AN
(
req
->
top
);
if
(
req
->
top
->
vcl0
)
req
->
vcl
=
req
->
top
->
vcl0
;
else
req
->
vcl
=
preq
->
vcl
;
VCL_Ref
(
req
->
vcl
);
assert
(
req
->
req_step
==
R_STP_TRANSPORT
);
req
->
t_req
=
preq
->
t_req
;
req
->
transport
=
&
ZIPFLOW_transport
;
req
->
transport_priv
=
zfr
;
CNT_Embark
(
wrk
,
req
);
VCL_TaskEnter
(
req
->
privs
);
INIT_OBJ
(
ctx
,
VRT_CTX_MAGIC
);
VCL_Req2Ctx
(
ctx
,
req
);
task_priv
=
VRT_priv_task
(
ctx
,
zipflow_request_priv
);
AN
(
task_priv
);
AZ
(
task_priv
->
priv
);
task_priv
->
priv
=
zfr
;
AZ
(
zfr
->
cond
);
zfr
->
cond
=
&
wrk
->
cond
;
//lint -e{716} while(1)
while
(
1
)
{
CNT_Embark
(
wrk
,
req
);
zfr
->
woken
=
0
;
s
=
CNT_Request
(
req
);
if
(
s
==
REQ_FSM_DONE
)
break
;
DSL
(
DBG_WAITINGLIST
,
req
->
vsl
->
wid
,
"waiting for zipflow (%d)"
,
(
int
)
s
);
assert
(
s
==
REQ_FSM_DISEMBARK
);
AN
(
zfr
->
cond
);
Lck_Lock
(
&
sp
->
mtx
);
if
(
!
zfr
->
woken
)
(
void
)
Lck_CondWait
(
zfr
->
cond
,
&
sp
->
mtx
);
Lck_Unlock
(
&
sp
->
mtx
);
AZ
(
req
->
wrk
);
}
VCL_Rel
(
&
req
->
vcl
);
req
->
wrk
=
NULL
;
THR_SetRequest
(
preq
);
Req_Cleanup
(
sp
,
wrk
,
req
);
Req_Release
(
req
);
}
static
void
v_matchproto_
(
vtr_deliver_f
)
zfr_deliver
(
struct
req
*
req
,
struct
boc
*
boc
,
int
wantbody
)
{
int
i
;
const
char
*
p
;
uint16_t
status
;
struct
vrt_ctx
ctx
[
1
];
CHECK_OBJ_NOTNULL
(
req
,
REQ_MAGIC
);
CHECK_OBJ_ORNULL
(
boc
,
BOC_MAGIC
);
CHECK_OBJ_NOTNULL
(
req
->
objcore
,
OBJCORE_MAGIC
);
if
(
wantbody
==
0
)
return
;
status
=
req
->
resp
->
status
%
1000
;
// XXX should we trigger an error like ESI does?
if
(
status
!=
200
)
return
;
if
(
boc
==
NULL
&&
ObjGetLen
(
req
->
wrk
,
req
->
objcore
)
==
0
)
return
;
AZ
(
http_GetHdr
(
req
->
resp
,
H_Content_Encoding
,
&
p
));
INIT_OBJ
(
ctx
,
VRT_CTX_MAGIC
);
VCL_Req2Ctx
(
ctx
,
req
);
i
=
VDP_Push
(
ctx
,
req
->
vdc
,
req
->
ws
,
vdp_zipsub
,
req
->
transport_priv
);
if
(
i
==
0
)
{
i
=
VDP_DeliverObj
(
req
->
vdc
,
req
->
objcore
);
}
else
{
VSLb
(
req
->
vsl
,
SLT_Error
,
"Failure to push ZIP processors"
);
req
->
doclose
=
SC_OVERLOAD
;
}
if
(
i
&&
req
->
doclose
==
SC_NULL
)
req
->
doclose
=
SC_REM_CLOSE
;
req
->
acct
.
resp_bodybytes
+=
VDP_Close
(
req
->
vdc
,
req
->
objcore
,
boc
);
#if 0
if (i && !ecx->incl_cont) {
req->top->topreq->vdc->retval = -1;
req->top->topreq->doclose = req->doclose;
}
#endif
}
src/vmod_zipflow.vcc
View file @
7d378554
...
...
@@ -37,17 +37,25 @@ Example
set resp.filters += " zipflow";
}
$Function VOID subreq(STRING url)
$Function VOID subreq(STRING url
, STRING host=0
)
$Restrict client
Issue a sub requets to *
url
* when the VDP runs, similar to ESI
Issue a sub requets to *
host*/*uri
* when the VDP runs, similar to ESI
processing.
This function can be called any number of times. The sub request can
be identified using `zipflow.is_subreq()`_. In the sub request,
`zipflow.set_level()`_ and `zipflow.meta()`_ should be used to control
how zipflow handles the body.
If *host* is omitted (default), it is taken from the parent request.
This function can be called any number of times to add multiple
files, it can eben be called from a sub request, which is to say that
more files can be added while requests for files are processed.
The sub request can be identified using `zipflow.is_subreq()`_. In the
sub request, `zipflow.set_level()`_ and `zipflow.meta()`_ should be
used to control how zipflow handles the body.
Only sub requests with reponse status 200 will be included in the
resulting zip file.
$Function BOOL is_subreq()
...
...
src/vtc/sub-coalesce.vtc
0 → 100644
View file @
7d378554
varnishtest "vmod-zipflow sub request / race & waitinglist"
feature cmd "type curl && type unzip && echo 'foo' grep -P '^foo'"
server s1 {
rxreq
expect req.url == "/file1"
txresp -gziplevel 1 -gziplen 10240
rxreq
expect req.url == "/file2"
txresp -bodylen 20480
} -start
varnish v1 -vcl+backend {
import zipflow;
sub vcl_recv {
zipflow.set_level(0);
if (zipflow.is_subreq()) {
return (hash);
}
return (synth(200));
}
sub vcl_synth {
synthetic("top zip");
zipflow.meta(name="top");
zipflow.subreq("/file1");
zipflow.subreq("/file2");
set resp.filters += " zipflow";
return (deliver);
}
} -start
client c1 {
txreq
rxresp
expect resp.status == 200
expect resp.bodylen == 31102
} -start
client c2 {
txreq
rxresp
expect resp.status == 200
expect resp.bodylen == 31102
} -start
client c3 {
txreq
rxresp
expect resp.status == 200
expect resp.bodylen == 31102
} -start
client c4 {
txreq
rxresp
expect resp.status == 200
expect resp.bodylen == 31102
} -start
client c1 -wait
client c2 -wait
client c3 -wait
client c4 -wait
\ No newline at end of file
src/vtc/sub.vtc
0 → 100644
View file @
7d378554
varnishtest "vmod-zipflow sub request"
feature cmd "type curl && type unzip && echo 'foo' grep -P '^foo'"
varnish v1 -vcl {
import zipflow;
import std;
backend proforma none;
sub vcl_recv {
return (synth(200));
}
sub synth_top {
synthetic("top zip");
zipflow.meta(name="top");
zipflow.subreq("/file1");
zipflow.subreq("/file2");
set resp.filters += " zipflow";
}
sub synth_sub {
synthetic("sub " + req.url);
}
sub vcl_synth {
if (zipflow.is_subreq()) {
call synth_sub;
if (req.url == "/file1") {
zipflow.meta(name="file1.changed");
zipflow.subreq("/file3");
} else
if (req.url == "/file3") {
zipflow.subreq("/file4");
}
} else {
call synth_top;
}
return (deliver);
}
} -start
client c1 {
txreq
rxresp
expect resp.status == 200
} -run
# all default
shell "curl -so t.zip -H 'Host: ${v1_addr}' http://${v1_addr}:${v1_port}/ && unzip -Z t.zip"
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment