1VMOD_BLOB(3)                                                      VMOD_BLOB(3)
2
3
4

NAME

6       vmod_blob - Utilities for the VCL blob type, encoding and decoding
7

SYNOPSIS

9          import blob [as name] [from "path"]
10
11          BLOB decode(ENUM decoding, INT length, STRING encoded)
12
13          STRING encode(ENUM encoding, ENUM case, BLOB blob)
14
15          STRING transcode(ENUM decoding, ENUM encoding, ENUM case, INT length, STRING encoded)
16
17          BOOL same(BLOB, BLOB)
18
19          BOOL equal(BLOB, BLOB)
20
21          INT length(BLOB)
22
23          BLOB sub(BLOB, BYTES length, BYTES offset)
24
25          new xblob = blob.blob(ENUM decoding, STRING encoded)
26
27              BLOB xblob.get()
28
29              STRING xblob.encode(ENUM encoding, ENUM case)
30

DESCRIPTION

32       This  VMOD  provides  utility  functions and an object for the VCL data
33       type BLOB, which may contain arbitrary data of any length.
34
35       Examples:
36
37          sub vcl_init {
38              # Create blob objects from encodings such as base64 or hex.
39              new myblob   = blob.blob(BASE64, "Zm9vYmFy");
40              new yourblob = blob.blob(encoded="666F6F", decoding=HEX);
41          }
42
43          sub vcl_deliver {
44              # The .get() method retrieves the BLOB from an object.
45              set resp.http.MyBlob-As-Hex
46                  = blob.encode(blob=myblob.get(), encoding=HEX);
47
48              # The .encode() method efficiently retrieves an encoding.
49              set resp.http.YourBlob-As-Base64 = yourblob.encode(BASE64);
50
51              # decode() and encode() functions convert blobs to text and
52              # vice versa at runtime.
53              set resp.http.Base64-Encoded
54                  = blob.encode(BASE64,
55                                blob=blob.decode(HEX,
56                                                 encoded=req.http.Hex-Encoded));
57          }
58
59          sub vcl_recv {
60              # transcode() converts from one encoding to another.
61              # case=UPPER specifies upper-case hex digits A-F.
62              set req.http.Hex-Encoded
63                  = blob.transcode(decoding=BASE64, encoding=HEX,
64                                   case=UPPER, encoded="YmF6");
65
66              # transcode() from URL to IDENTITY effects a URL decode.
67              set req.url = blob.transcode(encoded=req.url, decoding=URL);
68
69              # transcode() from IDENTITY to URL effects a URL encode.
70              set req.http.url_urlcoded
71                  = blob.transcode(encoded=req.url, encoding=URL);
72          }
73
74   ENCODING SCHEMES
75       Binary-to-text encoding schemes are specified by ENUMs  in  the  VMOD's
76       constructor,  methods and functions. Decodings convert a (possibly con‐
77       catenated) string into a blob, while encodings convert a  blob  into  a
78       string.
79
80       ENUM values for an encoding scheme can be one of:
81
82IDENTITY
83
84BASE64
85
86BASE64URL
87
88BASE64URLNOPAD
89
90BASE64CF
91
92HEX
93
94URL
95
96       Empty  strings  are  decoded into a "null blob" (of length 0), and con‐
97       versely a null blob is encoded as the empty string.
98
99       For encodings with HEX or URL, you may also specify a  case  ENUM  with
100       one  of  the  values  LOWER,  UPPER or DEFAULT to produce a string with
101       lower- or uppercase hex digits (in [a-f] or [A-F]). The  default  value
102       for case is DEFAULT, which for HEX and URL means the same as LOWER.
103
104       The  case  ENUM is not relevant for decodings; HEX or URL strings to be
105       decoded as BLOBs may have hex digits in either case, or in mixed case.
106
107       The case ENUM MUST be set to DEFAULT for the other  encodings  (BASE64*
108       and IDENTITY).  You cannot, for example, produce an uppercase string by
109       using the IDENTITY scheme with case=UPPER. To  change  the  case  of  a
110       string,   use   the   std.toupper()  or  std.tolower()  functions  from
111       vmod_std(3).
112
113   IDENTITY
114       The simplest encoding converts between the BLOB and STRING data  types,
115       leaving the contents byte-identical.
116
117       Note  that  a  BLOB  may contain a null byte at any position before its
118       end; if such a BLOB is decoded with IDENTITY, the resulting STRING will
119       have  a  null byte at that position. Since VCL strings, like C strings,
120       are represented with a terminating null byte, the string will be  trun‐
121       cated, appearing to contain less data than the original blob. For exam‐
122       ple:
123
124          # Decode from the hex encoding for "foo\0bar".
125          # The header will be seen as "foo".
126          set resp.http.Trunced-Foo1
127              = blob.encode(IDENTITY, blob=blob.decode(HEX,
128                                                       encoded="666f6f00626172"));
129
130       IDENTITY is the default encoding and decoding. So the above can also be
131       written as:
132
133          # Decode from the hex encoding for "foo\0bar".
134          # The header will be seen as "foo".
135          set resp.http.Trunced-Foo2
136            = blob.encode(blob=blob.decode(HEX, encoded="666f6f00626172"));
137
138       The case ENUM MUST be set to DEFAULT for IDENTITY encodings.
139
140   BASE64*
141       The  base64  encoding schemes use 4 characters to encode 3 bytes. There
142       are no newlines or maximal line lengths -- whitespace is not permitted.
143
144       The BASE64 encoding uses the alphanumeric characters, + and /; and  en‐
145       coded  strings  are padded with the = character so that their length is
146       always a multiple of four.
147
148       The BASE64URL encoding also uses the alphanumeric characters, but - and
149       _ instead of + and /, so that an encoded string can be used safely in a
150       URL. This scheme also uses the padding character =.
151
152       The BASE64URLNOPAD encoding uses the same  alphabet  as  BASE6URL,  but
153       leaves out the padding. Thus the length of an encoding with this scheme
154       is not necessarily a multiple of four.
155
156       The BASE64CF` is similar to ``BASE64URL, with the following changes  to
157       BASE64: + replaced with -, / replaced with ~ and _ as the padding char‐
158       acter. It is used by a certain CDN provider who also inspired the name.
159
160       The case ENUM MUST be set to DEFAULT for for all of the BASE64*  encod‐
161       ings.
162
163   HEX
164       The HEX encoding scheme converts hex strings into blobs and vice versa.
165       For encodings, you may use the case ENUM to specify upper- or lowercase
166       hex  digits  A  through  f  (default  DEFAULT,  which means the same as
167       LOWER).  A prefix such as 0x is not used for an encoding and is illegal
168       for a decoding.
169
170       If  a  hex  string to be decoded has an odd number of digits, it is de‐
171       coded as if a 0 is prepended to it; that is, the first digit is  inter‐
172       preted  as representing the least significant nibble of the first byte.
173       For example:
174
175          # The concatenated string is "abcdef0", and is decoded as "0abcdef0".
176          set resp.http.First = "abc";
177          set resp.http.Second = "def0";
178          set resp.http.Hex-Decoded
179              = blob.encode(HEX, blob=blob.decode(HEX,
180                                 encoded=resp.http.First + resp.http.Second));
181
182   URL
183       The URL decoding replaces any %<2-hex-digits> substrings with  the  bi‐
184       nary value of the hexadecimal number after the % sign.
185
186       The URL encoding implements "percent encoding" as per RFC3986. The case
187       ENUM determines the case of the hex digits, but does not affect  alpha‐
188       betic characters that are not percent-encoded.
189
190   BLOB decode(ENUM decoding, INT length, STRING encoded)
191          BLOB decode(
192             ENUM {IDENTITY, BASE64, BASE64URL, BASE64URLNOPAD, BASE64CF, HEX, URL} decoding=IDENTITY,
193             INT length=0,
194             STRING encoded
195          )
196
197       Returns  the  BLOB  derived  from  the  string encoded according to the
198       scheme specified by decoding.
199
200       If length > 0, only decode the first length characters of  the  encoded
201       string.  If  length <= 0 or greater than the length of the string, then
202       decode the entire string. The default value of length is 0.
203
204       decoding defaults to IDENTITY.
205
206       Example:
207
208          blob.decode(BASE64, encoded="Zm9vYmFyYmF6");
209
210          # same with named parameters
211          blob.decode(encoded="Zm9vYmFyYmF6", decoding=BASE64);
212
213          # convert string to blob
214          blob.decode(encoded="foo");
215
216   STRING encode(ENUM encoding, ENUM case, BLOB blob)
217          STRING encode(
218             ENUM {IDENTITY, BASE64, BASE64URL, BASE64URLNOPAD, BASE64CF, HEX, URL} encoding=IDENTITY,
219             ENUM {LOWER, UPPER, DEFAULT} case=DEFAULT,
220             BLOB blob
221          )
222
223       Returns a string representation of the BLOB blob as specified by encod‐
224       ing.  case determines the case of hex digits for the HEX and URL encod‐
225       ings, and is ignored for the other encodings.
226
227       encoding defaults to IDENTITY, and case defaults to  DEFAULT.   DEFAULT
228       is  interpreted  as LOWER for the HEX and URL encodings, and is the re‐
229       quired value for the other encodings.
230
231       Example:
232
233          set resp.http.encode1
234              = blob.encode(HEX,
235                            blob=blob.decode(BASE64, encoded="Zm9vYmFyYmF6"));
236
237          # same with named parameters
238          set resp.http.encode2
239              = blob.encode(blob=blob.decode(encoded="Zm9vYmFyYmF6",
240                                                     decoding=BASE64),
241                                encoding=HEX);
242
243          # convert blob to string
244          set resp.http.encode3
245              = blob.encode(blob=blob.decode(encoded="foo"));
246
247   STRING transcode(ENUM decoding,  ENUM  encoding,  ENUM  case,  INT  length,
248       STRING encoded)
249          STRING transcode(
250             ENUM {IDENTITY, BASE64, BASE64URL, BASE64URLNOPAD, BASE64CF, HEX, URL} decoding=IDENTITY,
251             ENUM {IDENTITY, BASE64, BASE64URL, BASE64URLNOPAD, BASE64CF, HEX, URL} encoding=IDENTITY,
252             ENUM {LOWER, UPPER, DEFAULT} case=DEFAULT,
253             INT length=0,
254             STRING encoded
255          )
256
257       Translates  from  one encoding to another, by first decoding the string
258       encoded according to the scheme decoding, and then returning the encod‐
259       ing of the resulting blob according to the scheme encoding. case deter‐
260       mines the case of hex digits for the HEX and URL encodings, and is  ig‐
261       nored for other encodings.
262
263       As  with  blob.decode():  If  length  > 0, only decode the first length
264       characters of the encoded string, otherwise decode the  entire  string.
265       The default value of length is 0.
266
267       decoding  and  encoding  default  to IDENTITY, and case defaults to DE‐
268       FAULT. DEFAULT is interpreted as LOWER for the HEX and  URL  encodings,
269       and is the required value for the other encodings.
270
271       Example:
272
273          set resp.http.Hex2Base64-1
274               = blob.transcode(HEX, BASE64, encoded="666f6f");
275
276           # same with named parameters
277           set resp.http.Hex2Base64-2
278              = blob.transcode(encoded="666f6f",
279                                    encoding=BASE64, decoding=HEX);
280
281           # URL decode -- recall that IDENTITY is the default encoding.
282           set resp.http.urldecoded
283              = blob.transcode(encoded="foo%20bar", decoding=URL);
284
285           # URL encode
286           set resp.http.urlencoded
287               = blob.transcode(encoded="foo bar", encoding=URL);
288
289   BOOL same(BLOB, BLOB)
290       Returns true if and only if the two BLOB arguments are the same object,
291       i.e. they specify exactly the same region of memory, or both are empty.
292
293       If the BLOBs are both empty (length is 0 and/or the internal pointer is
294       NULL), then blob.same() returns true. If any non-empty BLOB is compared
295       to an empty BLOB, then blob.same() returns false.
296
297   BOOL equal(BLOB, BLOB)
298       Returns true if and only if the two BLOB arguments have equal  contents
299       (possibly in different memory regions).
300
301       As with blob.same(): If the BLOBs are both empty, then blob.equal() re‐
302       turns true. If any non-empty BLOB is compared to an  empty  BLOB,  then
303       blob.equal() returns false.
304
305   INT length(BLOB)
306       Returns the length of the BLOB.
307
308   BLOB sub(BLOB, BYTES length, BYTES offset=0)
309       Returns a new BLOB formed from length bytes of the BLOB argument start‐
310       ing at offset bytes from the start of its memory  region.  The  default
311       value of offset is 0B.
312
313       blob.sub()  fails and returns NULL if the BLOB argument is empty, or if
314       offset + length requires more bytes than are available in the BLOB.
315
316   new xblob = blob.blob(ENUM decoding, STRING encoded)
317          new xblob = blob.blob(
318             ENUM {IDENTITY, BASE64, BASE64URL, BASE64URLNOPAD, BASE64CF, HEX, URL} decoding=IDENTITY,
319             STRING encoded
320          )
321
322       Creates an object that contains the BLOB derived from  the  string  en‐
323       coded according to the scheme decoding.
324
325       Example:
326
327          new theblob1 = blob.blob(BASE64, encoded="YmxvYg==");
328
329          # same with named arguments
330          new theblob2 = blob.blob(encoded="YmxvYg==", decoding=BASE64);
331
332          # string as a blob
333          new stringblob = blob.blob(encoded="bazz");
334
335   BLOB xblob.get()
336       Returns the BLOB created by the constructor.
337
338       Example:
339
340          set resp.http.The-Blob1 =
341              blob.encode(blob=theblob1.get());
342
343          set resp.http.The-Blob2 =
344              blob.encode(blob=theblob2.get());
345
346          set resp.http.The-Stringblob =
347              blob.encode(blob=stringblob.get());
348
349   STRING xblob.encode(ENUM encoding, ENUM case)
350          STRING xblob.encode(
351                ENUM {IDENTITY, BASE64, BASE64URL, BASE64URLNOPAD, BASE64CF, HEX, URL} encoding=IDENTITY,
352                ENUM {LOWER, UPPER, DEFAULT} case=DEFAULT
353          )
354
355       Returns  an  encoding  of BLOB created by the constructor, according to
356       the scheme encoding. case determines the case of hex digits for the HEX
357       and URL encodings, and MUST be set to DEFAULT for the other encodings.
358
359       Example:
360
361          # blob as text
362          set resp.http.The-Blob = theblob1.encode();
363
364          # blob as base64
365          set resp.http.The-Blob-b64 = theblob1.encode(BASE64);
366
367       For  any  blob.blob()  object,  encoding  and  case,  encodings via the
368       xblob.encode() method and the blob.encode() function are equal:
369
370          # Always true:
371          blob.encode(ENC, CASE, blob.get()) == blob.encode(ENC, CASE)
372
373       But the xblob.encode() object method is more efficient -- the  encoding
374       is  computed  once and cached (with allocation in heap memory), and the
375       cached  encoding  is  retrieved   on   every   subsequent   call.   The
376       blob.encode()  function computes the encoding on every call, allocating
377       space for the string in Varnish workspaces.
378
379       So if the data in a BLOB are fixed at VCL initialization time, so  that
380       its  encodings  will  always  be  the  same,  it  is better to create a
381       blob.blob() object. The VMOD's functions should be used for  data  that
382       are not known until runtime.
383

ERRORS

385       The encoders, decoders and blob.sub() may fail if there is insufficient
386       space to create the new blob or string. Decoders may also fail  if  the
387       encoded  string  is an illegal format for the decoding scheme. Encoders
388       will fail for the IDENTITY and BASE64* encoding  schemes  if  the  case
389       ENUM is not set to DEFAULT.
390
391       If  any  of the VMOD's methods, functions or constructor fail, then VCL
392       failure is invoked, just as if return(fail) had been called in the  VCL
393       source. This means that:
394
395       • If  the  blob.blob()  object  constructor fails, or if any methods or
396         functions fail during vcl_init{}, then the VCL program will  fail  to
397         load, and the VCC compiler will emit an error message.
398
399       • If  a  method  or  function fails in any other VCL subroutine besides
400         vcl_synth{}, then control is directed to  vcl_synth{}.  The  response
401         status  is set to 503 with the reason string "VCL failed", and an er‐
402         ror message will be written to the vsl(7) using the tag VCL_Error.
403
404       • If  the  failure  occurs  during  vcl_synth{},  then  vcl_synth{}  is
405         aborted.  The  response  line  "503  VCL failed" is returned, and the
406         VCL_Error message is written to the log.
407

LIMITATIONS

409       The VMOD allocates memory in various ways for new  blobs  and  strings.
410       The  blob.blob()  object and its methods allocate memory from the heap,
411       and hence they are only limited by available virtual memory.
412
413       The blob.encode(), blob.decode() and blob.transcode()  functions  allo‐
414       cate  Varnish workspace, as does blob.sub() for the newly created BLOB.
415       If these functions are failing, as indicated by "out of space" messages
416       in  the Varnish log (with the VCL_Error tag), then you will need to in‐
417       crease the varnishd parameters workspace_client and/or  workspace_back‐
418       end.
419
420       The  blob.transcode()  function also allocates space on the stack for a
421       temporary BLOB. If this function causes stack overflow, you may need to
422       increase the varnishd parameter thread_pool_stack.
423

SEE ALSO

425varnishd(1)
426
427vcl(7)
428
429vsl(7)
430
431vmod_std(3)
432
434          This document is licensed under the same conditions as Varnish itself.
435          See LICENSE for details.
436
437          SPDX-License-Identifier: BSD-2-Clause
438
439          Authors: Nils Goroll <nils.goroll@uplex.de>
440                   Geoffrey Simmons <geoffrey.simmons@uplex.de>
441
442
443
444
445                                                                  VMOD_BLOB(3)
Impressum