Allow to selectively set metadata, improve test coverage

parent 76b8827a
...@@ -34,6 +34,7 @@ ...@@ -34,6 +34,7 @@
#include <cache/cache.h> #include <cache/cache.h>
#include <cache/cache_filter.h> #include <cache/cache_filter.h>
#include <vcl.h> #include <vcl.h>
#include <vtim.h>
#include "vcc_zipflow_if.h" #include "vcc_zipflow_if.h"
...@@ -71,7 +72,7 @@ struct zipflow_request { ...@@ -71,7 +72,7 @@ struct zipflow_request {
VCL_STRING url; VCL_STRING url;
VCL_STRING name; VCL_STRING name;
unsigned mode; unsigned mode;
uint32_t atime, mtime; VCL_TIME atime, mtime;
VSTAILQ_ENTRY(zipflow_request) list; VSTAILQ_ENTRY(zipflow_request) list;
struct zipflow_top *top; struct zipflow_top *top;
}; };
...@@ -125,10 +126,10 @@ new_zipflow_request(VRT_CTX, struct zipflow_top *zft) ...@@ -125,10 +126,10 @@ new_zipflow_request(VRT_CTX, struct zipflow_top *zft)
zfr->bundle = 1; zfr->bundle = 1;
zfr->level = default_level; zfr->level = default_level;
zfr->name = "unnamed_file"; zfr->name = NULL;
zfr->mode = 0644; zfr->mode = 0644;
zfr->atime = ctx->now; zfr->atime = -1;
zfr->mtime = ctx->now; zfr->mtime = -1;
zfr->top = zft; zfr->top = zft;
return (zfr); return (zfr);
} }
...@@ -232,30 +233,118 @@ vmod_set_level(VRT_CTX, VCL_INT level) ...@@ -232,30 +233,118 @@ vmod_set_level(VRT_CTX, VCL_INT level)
} }
VCL_VOID VCL_VOID
vmod_meta(VRT_CTX, VCL_STRING name, VCL_STRING mode, vmod_meta(VRT_CTX, struct VARGS(meta) *args)
VCL_TIME atime, VCL_TIME mtime)
{ {
unsigned long u;
struct zipflow_request *zfr = get_zipflow_request(ctx); struct zipflow_request *zfr = get_zipflow_request(ctx);
unsigned long u;
char *e;
if (zfr == NULL) if (zfr == NULL)
return; return;
u = strtoul(mode, NULL, 8); if (args->valid_name)
if (u == ULONG_MAX) { zfr->name = args->name;
VRT_fail(ctx, ".meta() error converting mode: %d (%s)",
errno, VAS_errtxt(errno)); if (args->valid_mode) {
return; e = NULL;
u = strtoul(args->mode, &e, 8);
if (u == ULONG_MAX || (e != NULL && *e != '\0')) {
VRT_fail(ctx, ".meta() error converting mode at %s: "
"%d (%s)", e, errno, VAS_errtxt(errno));
} else
zfr->mode = u;
} }
if (atime == 0) if (args->valid_atime)
atime = ctx->now; zfr->atime = args->atime;
if (mtime == 0) if (args->valid_mtime)
mtime = ctx->now; zfr->mtime = args->mtime;
}
zfr->name = name;
zfr->mode = u; static const char *
zfr->atime = atime; get_url(VRT_CTX)
zfr->mtime = mtime; {
const char *url;
VCL_HTTP http;
if (ctx->http_bereq != NULL)
http = ctx->http_bereq;
else if (ctx->http_req != NULL)
http = ctx->http_req;
else
WRONG("No http headers");
AN(http);
url = http->hd[HTTP_HDR_URL].b;
AN(url);
AN(*url);
return (url);
}
static const char *
default_name(VRT_CTX)
{
const char *url = get_url(ctx);
size_t l;
char *p;
url = strrchr(url, '/');
AN(url);
url++;
if (*url == '\0' || *url == '?')
return ("unnamed_file");
p = strchr(url, '?');
if (p == NULL)
return (url);
assert(p > url);
l = p - url;
p = WS_Copy(ctx->ws, url, 1 + l);
if (p == NULL)
return ("unnamed_file");
p[l] = '\0';
return (p);
}
static VCL_TIME
lm(VRT_CTX)
{
const char *p;
VCL_TIME lm;
VCL_HTTP http;
if (ctx->http_beresp != NULL)
http = ctx->http_beresp;
else if (ctx->http_resp != NULL)
http = ctx->http_resp;
else
return (ctx->now);
if (!http_GetHdr(http, H_Last_Modified, &p))
return (ctx->now);
lm = VTIM_parse(p);
return (lm ? lm : ctx->now);
}
static void
fill_meta(VRT_CTX, struct zipflow_request *zfr)
{
const char *r;
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
CHECK_OBJ_NOTNULL(zfr, ZIPFLOW_REQUEST_MAGIC);
if (zfr->name == NULL)
zfr->name = default_name(ctx);
if (zfr->atime < 0)
zfr->atime = ctx->now;
if (zfr->mtime < 0)
zfr->mtime = lm(ctx);
VSLb(ctx->vsl, SLT_Debug, "%s %o %f %f", zfr->name, zfr->mode,
zfr->atime, zfr->mtime);
} }
int int
...@@ -316,8 +405,6 @@ vdp_zipflow_init(VRT_CTX, struct vdp_ctx *vdc, void **priv, struct objcore *oc) ...@@ -316,8 +405,6 @@ vdp_zipflow_init(VRT_CTX, struct vdp_ctx *vdc, void **priv, struct objcore *oc)
if (zfr == NULL) if (zfr == NULL)
return (1); return (1);
AN(zfr->name);
zft = zfr->top; zft = zfr->top;
CHECK_OBJ_NOTNULL(zft, ZIPFLOW_TOP_MAGIC); CHECK_OBJ_NOTNULL(zft, ZIPFLOW_TOP_MAGIC);
...@@ -332,8 +419,9 @@ vdp_zipflow_init(VRT_CTX, struct vdp_ctx *vdc, void **priv, struct objcore *oc) ...@@ -332,8 +419,9 @@ vdp_zipflow_init(VRT_CTX, struct vdp_ctx *vdc, void **priv, struct objcore *oc)
} }
AZ(zip_log(zft->zip, vdc->vsl, vdp_zipflow_log)); AZ(zip_log(zft->zip, vdc->vsl, vdp_zipflow_log));
if (zfr->bundle) { if (zfr->bundle) {
fill_meta(ctx, zfr);
AZ(zip_meta(zft->zip, zfr->name, 3, zfr->mode, AZ(zip_meta(zft->zip, zfr->name, 3, zfr->mode,
zfr->atime, zfr->mtime)); (uint32_t)zfr->atime, (uint32_t)zfr->mtime));
} }
AN(priv); AN(priv);
......
...@@ -84,19 +84,30 @@ default per VCL is not currently supported. ...@@ -84,19 +84,30 @@ default per VCL is not currently supported.
When used elsewhere, sets the level for the current task. Calls from When used elsewhere, sets the level for the current task. Calls from
``esi_level`` > 0 have no effect. ``esi_level`` > 0 have no effect.
$Function VOID meta(STRING name, STRING mode="0644", TIME atime=0, TIME mtime=0) $Function VOID meta([STRING name], [STRING mode], [TIME atime], [TIME mtime])
Set zip metadata for the currently streamed object: Set zip metadata for the currently streamed object. Defaults apply if
`zipflow.meta()`_ is not called, or arguments are not given.
* `name`: Filename * `name`: Filename
* `mode`: UNIX mode bits, default to 0644 Default: Last component of ``req.url`` or, if it is empty,
``unnamed_file``.
Note: This argument is of string type and interpreted as *octal*. * `mode`: UNIX mode bits
* `atime`: Access time, defaults to ``now``. This argument is of string type and interpreted as *octal*.
* `mtime`: Modification time, defaults to ``now``. Default: ``0644``
* `atime`: Access time
Default: ``now``.
* `mtime`: Modification time
Default: ``Last-Modified`` header of the response or, if it is not
available, ``now``.
SEE ALSO SEE ALSO
======== ========
......
varnishtest "test vmod-zipflow" varnishtest "test vmod-zipflow"
feature cmd "type curl && type unzip && echo 'foo' grep -P '^foo'"
server s1 { server s1 {
rxreq rxreq
txresp -body "zip file content" txresp -bodylen 1024
rxreq
expect req.url == "/path/to/lm?p"
txresp -hdr "Last-Modified: Mon, 21 Aug 2023 09:48:03 GMT" -bodylen 512
} -start } -start
varnish v1 -vcl+backend { varnish v1 -vcl+backend {
import zipflow; import zipflow;
import std;
sub vcl_init { sub vcl_init {
zipflow.set_level(1); zipflow.set_level(1);
} }
sub vcl_deliver { sub vcl_deliver {
zipflow.set_level(-1); zipflow.set_level(9);
zipflow.meta("filename", mode="444", atime=now, mtime=now - 1d); if (req.http.filename) {
zipflow.meta(name=req.http.filename);
}
if (req.http.mode) {
zipflow.meta(mode=req.http.mode);
}
if (req.http.mtime) {
zipflow.meta(mtime=std.time(req.http.mtime));
}
set resp.filters += " zipflow"; set resp.filters += " zipflow";
} }
} -start } -start
...@@ -23,6 +38,27 @@ client c1 { ...@@ -23,6 +38,27 @@ client c1 {
txreq txreq
rxresp rxresp
expect resp.status == 200 expect resp.status == 200
txreq -url "/path/to/lm?p"
rxresp
expect resp.status == 200
txreq -hdr "mode: 900"
rxresp
expect resp.status == 503
} -run } -run
shell "curl -svo t.zip -H 'Host: ${v1_addr}' http://${v1_addr}:${v1_port}/ && unzip -l t.zip" # all default
shell "curl -so t.zip -H 'Host: ${v1_addr}' http://${v1_addr}:${v1_port}/ && unzip -Z t.zip | grep -P '^-rw-r--r--.*\\b1024\\b.*\\b..-...-.. ..:.. unnamed_file$'"
# mtime = last-modified
shell "curl -so t.zip -H 'Host: ${v1_addr}' http://${v1_addr}:${v1_port}/path/to/lm?p && unzip -Z t.zip | grep -P '^-rw-r--r--.*\\b512\\b.*\\b23-Aug-21 11:48 lm'"
# filename
shell "curl -so t.zip -H 'Host: ${v1_addr}' -H 'filename: file' http://${v1_addr}:${v1_port}/ && unzip -Z t.zip | grep -P '^-rw-r--r--.*\\b1024\\b.*\\b..-...-.. ..:.. file$'"
# mode
shell "curl -so t.zip -H 'Host: ${v1_addr}' -H 'mode: 0755' http://${v1_addr}:${v1_port}/ && unzip -Z t.zip | grep -P '^-rwxr-xr-x.*\\b1024\\b.*\\b..-...-.. ..:.. unnamed_file$'"
# mtime
shell "curl -so t.zip -H 'Host: ${v1_addr}' -H 'mtime: 157590000' http://${v1_addr}:${v1_port}/ && unzip -Z t.zip | grep -P '^-rw-r--r--.*\\b1024\\b.*\\b74-Dec-30 00:00 unnamed_file$'"
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment