Commit 465fdb8c authored by Nils Goroll's avatar Nils Goroll

A 30 minute development time vmod

parent 62eb0761
Pipeline #283 skipped
This is a running log of changes to libvmod-example.
This is a running log of changes to libvmod-blobsynth.
libvmod-example 0.2 (unreleased)
libvmod-blobsynth 0.2 (unreleased)
--------------------------------
* The most recent release entry is at the top.
libvmod-example 0.1 (1970-01-01)
libvmod-blobsynth 0.1 (1970-01-01)
--------------------------------
* Add list items with changes done.
......
============
vmod-example
vmod-blobsynth
============
SYNOPSIS
========
import example;
import blobsynth;
DESCRIPTION
===========
Example Varnish vmod demonstrating how to write an out-of-tree Varnish vmod.
Quick hack to use blobs for synthetic responses.
Implements the traditional Hello World as a vmod.
Example:
FUNCTIONS
=========
hello
-----
::
import blob;
import blobsynth;
Prototype
::
sub vcl_init {
new gif = blob.blob(BASE64,
"R0lGODlhAQABAPAAAAAAAAAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==");
}
hello(STRING S)
Return value
STRING
Description
Returns "Hello, " prepended to S
Example
::
sub vcl_synth {
set resp.http.Content-Type = "image/gif";
blobsynth.synthetic(gif.get());
return (deliver);
}
set resp.http.hello = example.hello("World");
INSTALLATION
============
......@@ -82,18 +79,6 @@ By default, the vmod ``configure`` script installs the built vmod in the
directory relevant to the prefix. The vmod installation directory can be
overridden by passing the ``vmoddir`` variable to ``make install``.
USAGE
=====
In your VCL you could then use this vmod along the following lines::
import example;
sub vcl_deliver {
# This sets resp.http.hello to "Hello, World"
set resp.http.hello = example.hello("World");
}
COMMON PROBLEMS
===============
......@@ -111,10 +96,10 @@ COMMON PROBLEMS
START YOUR OWN VMOD
===================
The basic steps to start a new vmod from this example are::
The basic steps to start a new vmod from this blobsynth are::
name=myvmod
git clone libvmod-example libvmod-$name
git clone libvmod-blobsynth libvmod-$name
cd libvmod-$name
./rename-vmod-script $name
......
AC_PREREQ([2.68])
AC_INIT([libvmod-example], [0.1], [], [vmod-example])
AC_INIT([libvmod-blobsynth], [0.1], [], [vmod-blobsynth])
AC_COPYRIGHT([Copyright (c) 2011-2016 Varnish Software AS])
AC_CONFIG_MACRO_DIR([m4])
AC_CONFIG_AUX_DIR([build-aux])
AC_CONFIG_SRCDIR(src/vmod_example.vcc)
AC_CONFIG_SRCDIR(src/vmod_blobsynth.vcc)
AC_CONFIG_HEADER([config.h])
AM_INIT_AUTOMAKE([1.12 -Wall -Werror foreign parallel-tests])
......@@ -29,7 +29,7 @@ AC_ARG_WITH([rst2man],
m4_ifndef([VARNISH_PREREQ], AC_MSG_ERROR([Need varnish.m4 -- see README.rst]))
VARNISH_PREREQ([5.2])
VARNISH_VMODS([example])
VARNISH_VMODS([blobsynth])
VMOD_TESTS="$(cd $srcdir/src && echo tests/*.vtc)"
AC_SUBST(VMOD_TESTS)
......
#!/bin/bash
#
# Script to rename libvmod-example into libvmod-foo.
# (where "foo" is your new vmod name, of course.)
#
# Leaves the changes uncommitted in the working tree, so you get to fix any
# unintended changes.
#
# Author: Lasse Karstensen <lkarsten@varnish-software.com>, September 2014.
#
set -o errexit
NAME=$1
if [ -z "$NAME" ]; then
echo "Usage: $0 <new-vmod-name-without-libvmod-prefix>"
echo "Rename libvmod-example source tree."
echo "If the name is an acronym, you can use capital letters."
echo
exit -1
fi
SYM_NAME=${NAME,,*}
CAP_NAME=${NAME^?}
UPP_NAME=${NAME^^?}
if ! git diff-index --quiet HEAD --; then
echo "ERROR: Need a clean working tree. Run \"git stash\" first."
exit -2
fi
git mv src/vmod_example.c src/vmod_${SYM_NAME}.c
git mv src/vmod_example.vcc src/vmod_${SYM_NAME}.vcc
git grep -z -l example | xargs -0 sed -i -s -e "s/example/${SYM_NAME}/g"
git grep -z -l Example | xargs -0 sed -i -s -e "s/Example/${CAP_NAME}/g"
git grep -z -l EXAMPLE | xargs -0 sed -i -s -e "s/EXAMPLE/${UPP_NAME}/g"
git rm -f rename-vmod-script
# restore foreign files
git checkout -- m4/
cat <<EOF
All done.
For your cut&paste needs:
git commit -a -m "Automatic rename of libvmod-example to libvmod-${SYM_NAME}."
EOF
AM_CFLAGS = $(VARNISHAPI_CFLAGS) -Wall -Werror
AM_LDFLAGS = $(VARNISHAPI_LIBS) $(VMOD_LDFLAGS)
vmod_LTLIBRARIES = libvmod_example.la
vmod_LTLIBRARIES = libvmod_blobsynth.la
libvmod_example_la_SOURCES = \
vmod_example.c
libvmod_blobsynth_la_SOURCES = \
vmod_blobsynth.c
nodist_libvmod_example_la_SOURCES = \
vcc_example_if.c \
vcc_example_if.h
nodist_libvmod_blobsynth_la_SOURCES = \
vcc_blobsynth_if.c \
vcc_blobsynth_if.h
dist_man_MANS = vmod_example.3
dist_man_MANS = vmod_blobsynth.3
@BUILD_VMOD_EXAMPLE@
@BUILD_VMOD_BLOBSYNTH@
AM_TESTS_ENVIRONMENT = \
PATH="$(VMOD_TEST_PATH)" \
LD_LIBRARY_PATH="$(VARNISH_LIBRARY_PATH)"
TEST_EXTENSIONS = .vtc
VTC_LOG_COMPILER = varnishtest -v
AM_VTC_LOG_FLAGS = -Dvmod_example="$(VMOD_EXAMPLE)"
AM_VTC_LOG_FLAGS = -Dvmod_blobsynth="$(VMOD_BLOBSYNTH)"
TESTS = @VMOD_TESTS@
EXTRA_DIST = \
vmod_example.vcc \
vmod_blobsynth.vcc \
$(VMOD_TESTS)
varnishtest "Test example vmod"
varnishtest "Test blobsynth vmod"
server s1 {
rxreq
......@@ -6,29 +6,33 @@ server s1 {
} -start
varnish v1 -vcl+backend {
import std;
import ${vmod_example};
import blob;
import ${vmod_blobsynth};
sub vcl_init {
std.log(example.info());
new gif = blob.blob(BASE64,
"R0lGODlhAQABAPAAAAAAAAAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==");
}
sub vcl_deliver {
set resp.http.hello = example.hello("World");
set resp.http.info = example.info();
sub vcl_recv {
blobsynth.synthetic(gif.get());
return(synth(200));
}
sub vcl_synth {
set resp.http.Content-Type = "image/gif";
blobsynth.synthetic(gif.get());
return (deliver);
}
} -start
logexpect l1 -v v1 -g raw -d 1 {
expect 0 0 CLI {^Rd vcl.load}
expect 0 = VCL_Log {^vmod_example loaded at }
} -start
client c1 {
txreq -url "/"
rxresp
expect resp.http.hello == "Hello, World"
expect resp.http.info ~ "^vmod_example warmed at "
}
client c1 -run
......
#include "config.h"
#include <stdio.h>
#include <stdlib.h>
/* need vcl.h before vrt.h for vmod_evet_f typedef */
#include "vcl.h"
#include "vrt.h"
#include "cache/cache.h"
#include "vtim.h"
#include "vcc_blobsynth_if.h"
VCL_VOID
vmod_synthetic(VRT_CTX, VCL_BLOB blob)
{
struct vsb *vsb;
if ((ctx->method & (VCL_MET_SYNTH | VCL_MET_BACKEND_ERROR)) == 0) {
VSLb(ctx->vsl, SLT_VCL_Error,
"blobsynth.synthetic() only valid in vcl_synth{}"
" and vcl_backend_error{}");
return;
}
CAST_OBJ_NOTNULL(vsb, ctx->specific, VSB_MAGIC);
if (blob == NULL || blob->len == 0)
return;
AN(blob->priv);
if (VSB_bcat(vsb, blob->priv, blob->len))
VRT_fail(ctx, "blobsynth.synthetic(): %s",
strerror(VSB_error(vsb)));
}
#
# Copyright YOU (c) 1900.
#
# (vmodtool requires this format.)
#
$Module blobsynth 3 Blobsynth VMOD
DESCRIPTION
===========
$Function VOID synthetic(BLOB blob)
Create a synthetic response from *blob*.
Has no effect outside ``vcl_synth`` and ``vcl_backend_error``.
#include "config.h"
#include <stdio.h>
#include <stdlib.h>
/* need vcl.h before vrt.h for vmod_evet_f typedef */
#include "vcl.h"
#include "vrt.h"
#include "cache/cache.h"
#include "vtim.h"
#include "vcc_example_if.h"
const size_t infosz = 64;
char *info;
/*
* handle vmod internal state, vmod init/fini and/or varnish callback
* (un)registration here.
*
* malloc'ing the info buffer is only indended as a demonstration, for any
* real-world vmod, a fixed-sized buffer should be a global variable
*/
int __match_proto__(vmod_event_f)
event_function(VRT_CTX, struct vmod_priv *priv, enum vcl_event_e e)
{
char ts[VTIM_FORMAT_SIZE];
const char *event = NULL;
(void) ctx;
(void) priv;
switch (e) {
case VCL_EVENT_LOAD:
info = malloc(infosz);
if (! info)
return (-1);
event = "loaded";
break;
case VCL_EVENT_WARM:
event = "warmed";
break;
case VCL_EVENT_COLD:
event = "cooled";
break;
case VCL_EVENT_DISCARD:
free(info);
return (0);
break;
default:
return (0);
}
AN(event);
VTIM_format(VTIM_real(), ts);
snprintf(info, infosz, "vmod_example %s at %s", event, ts);
return (0);
}
VCL_STRING
vmod_info(VRT_CTX)
{
(void) ctx;
return (info);
}
VCL_STRING
vmod_hello(VRT_CTX, VCL_STRING name)
{
char *p;
unsigned u, v;
u = WS_Reserve(ctx->ws, 0); /* Reserve some work space */
p = ctx->ws->f; /* Front of workspace area */
v = snprintf(p, u, "Hello, %s", name);
v++;
if (v > u) {
/* No space, reset and leave */
WS_Release(ctx->ws, 0);
return (NULL);
}
/* Update work space with what we've used */
WS_Release(ctx->ws, v);
return (p);
}
#
# Copyright YOU (c) 1900.
#
# (vmodtool requires this format.)
#
$Module example 3 Example VMOD
DESCRIPTION
===========
This is the embedded documentation for the example VMOD. It should
mention what the vmod is intended to do.
It can span multiple lines and is written in RST format.
You can even have links and lists in here:
* https://github.com/varnish/libvmod-example/
* https://www.varnish-cache.org/
$Event event_function
$Function STRING info()
Returns a string set by the last VCL event, demonstrating the use of
event functions.
$Function STRING hello(STRING)
The different functions provided by the VMOD should also have their own
embedded documentation. This section is for the hello() function.
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