Commit 38cad67f authored by Nils Goroll's avatar Nils Goroll

initial - esiextra.bodyhash working

parents
# editors
*~
# build system
.deps/
.libs/
autom4te.cache/
build-aux/
m4/
*.la
*.lo
*.o
*.tar.gz
Makefile
Makefile.in
aclocal.m4
config.h
config.h.in
config.log
config.status
configure
libtool
stamp-h1
# test suite
*.log
*.trs
# vmodtool
vcc_*_if.[ch]
vmod_*.rst
# man
*.1
*_options.rst
*_synopsis.rst
vmod_*.3
# rpm
mockbuild/
rpmbuild/
*.rpm
*.spec
ACLOCAL_AMFLAGS = -I m4 -I $(VARNISHAPI_DATAROOTDIR)/aclocal
DISTCHECK_CONFIGURE_FLAGS = RST2MAN=:
SUBDIRS = src
EXTRA_DIST = libvmod-esiextra.spec
#!/bin/sh
set -e
WORK_DIR="$PWD"
ROOT_DIR="$(dirname "$0")"
test -n "$ROOT_DIR"
cd "$ROOT_DIR"
if ! which libtoolize >/dev/null 2>&1
then
echo "libtoolize: command not found, falling back to glibtoolize" >&2
alias libtoolize=glibtoolize
fi
mkdir -p m4
aclocal
libtoolize --copy --force
autoheader
automake --add-missing --copy --foreign
autoconf
cd "$WORK_DIR"
"$ROOT_DIR"/configure "$@"
AC_PREREQ([2.68])
AC_INIT([libvmod-esiextra], [0.1])
AC_CONFIG_MACRO_DIR([m4])
AC_CONFIG_AUX_DIR([build-aux])
AC_CONFIG_HEADER([config.h])
AM_INIT_AUTOMAKE([1.12 -Wall -Werror foreign parallel-tests])
AM_SILENT_RULES([yes])
AM_PROG_AR
LT_PREREQ([2.2.6])
LT_INIT([dlopen disable-static])
AC_ARG_WITH([rst2man],
AS_HELP_STRING(
[--with-rst2man=PATH],
[Location of rst2man (auto)]),
[RST2MAN="$withval"],
AC_CHECK_PROGS(RST2MAN, [rst2man rst2man.py], []))
VARNISH_PREREQ([5.2.0])
VARNISH_VMODS([esiextra])
AC_CONFIG_FILES([
Makefile
src/Makefile
libvmod-esiextra.spec
])
AC_OUTPUT
AS_ECHO("
==== $PACKAGE_STRING ====
varnish: $VARNISH_VERSION
prefix: $prefix
vmoddir: $vmoddir
vcldir: $vcldir
pkgvcldir: $pkgvcldir
compiler: $CC
cflags: $CFLAGS
ldflags: $LDFLAGS
")
%global __debug_package 0
%global __strip true
%global vmoddir %{_libdir}/varnish/vmods
%global vcldir %{_datadir}/varnish/vcl
Name: @PACKAGE@
Version: @PACKAGE_VERSION@
Release: 1%{?dist}
Summary: XXX: put your summary here
License: XXX: put your license here
URL: XXX://put.your/url/here
Source: %{name}-%{version}.tar.gz
BuildRequires: pkgconfig(varnishapi) >= 5.2.0
%description
XXX: put your long description here
%prep
%setup -q
%build
%configure CFLAGS="%{optflags}" RST2MAN=:
%make_build V=1
%install
%make_install
rm -f %{buildroot}%{vmoddir}/*.la
%check
%make_build check
%files
%{_mandir}/man*/*
%{vmoddir}/libvmod_esiextra.so
%changelog
* Sun Nov 5 2017 XXX: author <your@email> - 0.1
- Initial spec
AM_CFLAGS = $(VARNISHAPI_CFLAGS)
# Modules
vmod_LTLIBRARIES = \
libvmod_esiextra.la
libvmod_esiextra_la_LDFLAGS = $(VMOD_LDFLAGS)
libvmod_esiextra_la_SOURCES = vmod_esiextra.c
nodist_libvmod_esiextra_la_SOURCES = \
vcc_esiextra_if.c \
vcc_esiextra_if.h \
vfp_bodyhash.c \
vfp_bodyhash.h
@BUILD_VMOD_ESIEXTRA@
# Test suite
AM_TESTS_ENVIRONMENT = \
PATH="$(abs_builddir):$(VARNISH_TEST_PATH):$(PATH)" \
LD_LIBRARY_PATH="$(VARNISH_LIBRARY_PATH)"
TEST_EXTENSIONS = .vtc
VTC_LOG_COMPILER = varnishtest -v
AM_VTC_LOG_FLAGS = \
-p vcl_path="$(abs_top_srcdir)/vcl" \
-p vmod_path="$(abs_builddir)/.libs:$(vmoddir)"
TESTS = \
vtc/vmod_esiextra.vtc
# Documentation
dist_doc_DATA = \
vmod_esiextra.vcc \
$(TESTS)
dist_man_MANS = \
vmod_esiextra.3
.rst.1:
$(AM_V_GEN) $(RST2MAN) $< $@
/*-
* XXX TODO
*
*/
#include "config.h"
#include <stdlib.h>
#include <string.h>
//#include "cache/cache_varnishd.h"
#include "cache/cache.h"
#include "cache/cache_filter.h"
#include "vsha256.h"
#include "miniobj.h"
const struct vfp VFP_bodyhash;
struct bodyhash {
unsigned magic;
#define BODYHASH_MAGIC 0xb0d16a56
struct SHA256Context sha256ctx;
char *hdr;
// unsigned char hash[SHA256_LEN];
};
const char placeholder[] = "\"vmod-esiextra magic placeholder " \
"vmod-esiextra magic placeholder \"";
const size_t placeholder_l = sizeof(placeholder) - 1;
static enum vfp_status __match_proto__(vfp_init_f)
vfp_bodyhash_init(struct vfp_ctx *vc, struct vfp_entry *vfe)
{
struct bodyhash *bh;
CHECK_OBJ_NOTNULL(vc, VFP_CTX_MAGIC);
CHECK_OBJ_NOTNULL(vfe, VFP_ENTRY_MAGIC);
AN(vfe->priv1);
assert(vfe->vfp == &VFP_bodyhash);
assert(placeholder_l == SHA256_LEN * 2 + 2);
// XXX workspace
ALLOC_OBJ(bh, BODYHASH_MAGIC);
if (bh == NULL)
return (VFP_ERROR);
SHA256_Init(&bh->sha256ctx);
bh->hdr = vfe->priv1;
vfe->priv1 = bh;
http_ForceHeader(vc->resp, H_ETag, placeholder);
return (VFP_OK);
}
static enum vfp_status __match_proto__(vfp_pull_f)
vfp_bodyhash_pull(struct vfp_ctx *vc, struct vfp_entry *vfe, void *p,
ssize_t *lp)
{
struct bodyhash *bh;
enum vfp_status vp;
CHECK_OBJ_NOTNULL(vc, VFP_CTX_MAGIC);
AN(lp);
vp = VFP_Suck(vc, p, lp);
if (*lp <= 0)
return (vp);
CHECK_OBJ_NOTNULL(vfe, VFP_ENTRY_MAGIC);
CAST_OBJ_NOTNULL(bh, vfe->priv1, BODYHASH_MAGIC);
SHA256_Update(&bh->sha256ctx, p, *lp);
return (vp);
}
const char hexe[16] = {
"0123456789abcdef",
};
// XXX make non-void
static void __match_proto__(vfp_fini_f)
vfp_bodyhash_fini(struct vfp_ctx *vc, struct vfp_entry *vfe)
{
struct bodyhash *bh;
unsigned char sha[SHA256_LEN];
char *etag, *p;
int i;
ssize_t l;
CHECK_OBJ_NOTNULL(vc, VFP_CTX_MAGIC);
CHECK_OBJ_NOTNULL(vfe, VFP_ENTRY_MAGIC);
if (vfe->priv1 == NULL)
return;
CAST_OBJ_NOTNULL(bh, vfe->priv1, BODYHASH_MAGIC);
vfe->priv1 = NULL;
// HACKY
p = TRUST_ME(ObjGetAttr(vc->wrk, vc->oc, OA_HEADERS, &l));
if (p == NULL) {
VSLb(vc->wrk->vsl, SLT_Error, "bodyhash: no object");
goto out;
}
etag = p;
p = etag + l;
do {
etag = memchr(etag, '"', l);
if (etag == NULL)
break;
l = p - etag;
if (l < placeholder_l) {
etag = NULL;
break;
}
if (strncmp(etag, placeholder, placeholder_l) == 0)
break;
etag++;
} while(1);
if (etag == NULL) {
VSLb(vc->wrk->vsl, SLT_Error, "bodyhash: no placeholder");
goto out;
}
SHA256_Final(sha, &bh->sha256ctx);
assert(*etag == '"');
p = etag;
p++;
for (i = 0; i < SHA256_LEN; i++) {
*p++ = hexe[(sha[i] & 0xf0) >> 4];
*p++ = hexe[sha[i] & 0x0f];
}
assert(*p == '"');
out:
FREE_OBJ(bh);
}
const struct vfp VFP_bodyhash = {
.name = "bodyhash",
.init = vfp_bodyhash_init,
.pull = vfp_bodyhash_pull,
.fini = vfp_bodyhash_fini
};
// XXX in cache_varnishd.h
struct vfp_entry *VFP_Push(struct vfp_ctx *, const struct vfp *);
void *
Bodyhash_push(struct vfp_ctx *vc, const char *hdr)
{
struct vfp_entry *vfe = VFP_Push(vc, &VFP_bodyhash);
if (vfe)
vfe->priv1 = TRUST_ME(hdr);
return (vfe);
}
void *Bodyhash_push(struct vfp_ctx *vc, const char *hdr);
#include "config.h"
#include <cache/cache.h>
#include <vcl.h>
#include "vcc_esiextra_if.h"
#include "vfp_bodyhash.h"
VCL_VOID __match_proto__(td_esiextra_bodyhash)
vmod_bodyhash(VRT_CTX, VCL_HEADER hdr)
{
struct busyobj *bo;
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
if (ctx->method != VCL_MET_BACKEND_RESPONSE) {
VRT_fail(ctx, "bodyhash only valid in vcl_backend_response");
return;
}
if (hdr->where != HDR_BERESP) {
VRT_fail(ctx, "bodyhash can only modify beresp.http.*");
return;
}
CAST_OBJ_NOTNULL(bo, ctx->bo, BUSYOBJ_MAGIC);
bo->do_stream = 0;
if (Bodyhash_push(bo->vfc, hdr->what) == NULL)
VRT_fail(ctx, "bodyhash push failed");
}
$Module esiextra 3 Varnish Esiextra Module
DESCRIPTION
===========
Example
::
import esiextra;
$Function VOID bodyhash(HEADER)
Hash the received body.
SEE ALSO
========
``vcl``\(7),
``varnishd``\(1),
``varnishesiextra``\(1)
varnishtest "Generate an ETag as the hash of the received body"
server s1 {
rxreq
txresp -body "foo"
} -start
varnish v1 -vcl+backend {
import esiextra;
sub vcl_backend_response {
esiextra.bodyhash(beresp.http.ETag);
}
} -start
client c1 -repeat 3 {
txreq
rxresp
expect resp.http.ETag == {"2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae"}
} -run
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