Skip to content

Commit

Permalink
Migrate all examples to varnish macro
Browse files Browse the repository at this point in the history
  • Loading branch information
nyurik committed Oct 6, 2024
1 parent 8a7cbfe commit 40d9c37
Show file tree
Hide file tree
Showing 50 changed files with 872 additions and 635 deletions.
3 changes: 0 additions & 3 deletions examples/vmod_be/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,6 @@ version = "0.0.0"
publish = false
edition.workspace = true

[build-dependencies]
varnish.workspace = true

[dependencies]
varnish.workspace = true

Expand Down
31 changes: 31 additions & 0 deletions examples/vmod_be/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<!--
!!!!!! WARNING: DO NOT EDIT THIS FILE!
This file was generated from the Varnish VMOD source code.
It will be automatically updated on each build.
-->
# Varnish Module (VMOD) `be`

a simple STRING dictionary in your VCL

```vcl
// Place import statement at the top of your VCL file
// This loads vmod from a standard location
import be;
// Or load vmod from a specific file
import be from "path/to/libbe.so";
```

### Object `parrot`

```vcl
// Create a new instance of the object in your VCL init function
sub vcl_init {
new new = parrot.new(STRING to_repeat);
}
```

#### Method `BACKEND backend()`
3 changes: 0 additions & 3 deletions examples/vmod_be/build.rs

This file was deleted.

73 changes: 43 additions & 30 deletions examples/vmod_be/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,41 +1,54 @@
#![allow(non_camel_case_types)]

varnish::boilerplate!();

use std::error::Error;

use varnish::vcl::{Backend, Ctx, Serve, Transfer, VCLBackendPtr};
use varnish::vcl::{Ctx, Serve, Transfer};

varnish::run_vtc_tests!("tests/*.vtc");

// parrot is our VCL object, which just holds a rust Backend,
// it only needs two functions:
// - new(), so that the VCL can instantiate it
// - backend(), so that we can produce a C pointer for varnish to use
pub struct parrot {
be: Backend<Sentence, Body>,
}
/// a simple STRING dictionary in your VCL
#[varnish::vmod(docs = "README.md")]
mod be {
use std::error::Error;

use varnish::vcl::{Backend, Ctx, VCLBackendPtr};

impl parrot {
pub fn new(ctx: &mut Ctx, vcl_name: &str, to_repeat: &str) -> Result<Self, Box<dyn Error>> {
// to create the backend, we need:
// - the vcl context, that we just pass along
// - the vcl_name (how the vcl writer named the object)
// - a struct that implements the Serve trait
let be = Backend::new(
ctx,
vcl_name,
Sentence {
v: Vec::from(to_repeat),
},
false,
)?;

Ok(parrot { be })
use super::{Body, Sentence};

/// parrot is our VCL object, which just holds a rust Backend,
/// it only needs two functions:
/// - new(), so that the VCL can instantiate it
/// - backend(), so that we can produce a C pointer for varnish to use
#[allow(non_camel_case_types)]
pub struct parrot {
be: Backend<Sentence, Body>,
}

pub fn backend(&self, _ctx: &Ctx) -> VCLBackendPtr {
self.be.vcl_ptr()
impl parrot {
pub fn new(
ctx: &mut Ctx,
// Varnish automatically supplies this parameter if listed here
// It is not part of the object instantiation in VCL
#[vcl_name] name: &str,
to_repeat: &str,
) -> Result<Self, Box<dyn Error>> {
// to create the backend, we need:
// - the vcl context, that we just pass along
// - the vcl_name (how the vcl writer named the object)
// - a struct that implements the Serve trait
let be = Backend::new(
ctx,
name,
Sentence {
v: Vec::from(to_repeat),
},
false,
)?;

Ok(parrot { be })
}

pub fn backend(&self) -> VCLBackendPtr {
self.be.vcl_ptr()
}
}
}

Expand Down
5 changes: 0 additions & 5 deletions examples/vmod_be/vmod.vcc

This file was deleted.

3 changes: 0 additions & 3 deletions examples/vmod_error/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,6 @@ version = "0.0.0"
publish = false
edition.workspace = true

[build-dependencies]
varnish.workspace = true

[dependencies]
varnish.workspace = true
rand = "0.8.3"
Expand Down
44 changes: 44 additions & 0 deletions examples/vmod_error/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<!--
!!!!!! WARNING: DO NOT EDIT THIS FILE!
This file was generated from the Varnish VMOD source code.
It will be automatically updated on each build.
-->
# Varnish Module (VMOD) `error`

Parse files into numbers

This is a simple example of how to handle errors in a Varnish VMOD.
All three functions will do the same thing: read a file and try to parse its content into a VCL_INT.
However, they will handle failure (file not found, permission issue, unparsable content, etc.) differently.

```vcl
// Place import statement at the top of your VCL file
// This loads vmod from a standard location
import error;
// Or load vmod from a specific file
import error from "path/to/liberror.so";
```

### Function `INT cannot_fail(STRING path)`

This function never fails, returning 0 if anything goes wrong

### Function `INT manual_fail(STRING fp)`

If the file cannot be parsed into an INT, the vmod will trigger a VCL error,
stopping the processing of the request and logging the error.
The client will receive an error message with a 500 status code.

We call `ctx.fail()` ourselves, but we still need to return an i64.

### Function `INT result_fail(STRING fp)`

From a user perspective, this function does the same thing as `.manual_fail()`,
except its underlying `rust` implementation is slightly different.

In a more idiomatic way, we return a Result, and the generated boilerplate will be in charge of
calling `ctx.fail() and return a default value.
3 changes: 0 additions & 3 deletions examples/vmod_error/build.rs

This file was deleted.

109 changes: 60 additions & 49 deletions examples/vmod_error/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,52 +1,63 @@
varnish::boilerplate!();

use std::fs::read_to_string;

use varnish::vcl::Ctx;

varnish::run_vtc_tests!("tests/*.vtc");

// no error, just return 0 if anything goes wrong
pub fn cannot_fail(_: &Ctx, fp: &str) -> i64 {
// try to read the path at fp into a string, but return if there was an error
let Ok(content) = read_to_string(fp) else {
return 0;
};

// try to convert the string into an i64, if parsing fails, force 0
// no need to return as the last expression is automatically returned
content.parse::<i64>().unwrap_or(0)
}

// we call ctx.fail() ourselves, but we still need to return an i64 (which will
// be discarded), so we just convert the 0_u8 returned into an i64 (.into() is
// smart enough to infer the type)
pub fn manual_fail(ctx: &mut Ctx, fp: &str) -> i64 {
// try to read the path at fp into a string, but return if there was an error
let Ok(content) = read_to_string(fp) else {
ctx.fail("manual_fail: couldn't read file into string");
return 0;
};

// try to convert the string into an i64
// no need to return as the last expression is automatically returned
let Ok(result) = content.parse::<i64>() else {
ctx.fail("manual_fail: conversion failed");
return 0;
};

result
}

// more idiomatic, we return a Result, and the generated boilerplate will be in charge of
// calling `ctx.fail() and return a dummy value
pub fn result_fail(_: &mut Ctx, fp: &str) -> Result<i64, String> {
// read the file
read_to_string(fp)
// convert the error (if any!), into a string and return right away with the `?` operator
.map_err(|e| format!("result_fail: {e}"))?
// try to parse content into i64
.parse::<i64>()
// map the error to a string message and return either the parsed integer or that error
.map_err(|e| format!("result_fail: {e}"))
/// Parse files into numbers
///
/// This is a simple example of how to handle errors in a Varnish VMOD.
/// All three functions will do the same thing: read a file and try to parse its content into a VCL_INT.
/// However, they will handle failure (file not found, permission issue, unparsable content, etc.) differently.
#[varnish::vmod(docs = "README.md")]
mod error {
use std::fs::read_to_string;

use varnish::vcl::Ctx;

/// This function never fails, returning 0 if anything goes wrong
pub fn cannot_fail(path: &str) -> i64 {
// try to read the path at fp into a string, but return if there was an error
let Ok(content) = read_to_string(path) else {
return 0;
};

// try to convert the string into an i64, if parsing fails, force 0
// no need to return as the last expression is automatically returned
content.parse::<i64>().unwrap_or(0)
}

/// If the file cannot be parsed into an INT, the vmod will trigger a VCL error,
/// stopping the processing of the request and logging the error.
/// The client will receive an error message with a 500 status code.
///
/// We call `ctx.fail()` ourselves, but we still need to return an i64.
pub fn manual_fail(ctx: &mut Ctx, fp: &str) -> i64 {
// try to read the path at fp into a string, or return 0 if there was an error
let Ok(content) = read_to_string(fp) else {
ctx.fail("manual_fail: couldn't read file into string");
return 0;
};

// try to convert the string into an i64
// no need to return as the last expression is automatically returned
let Ok(result) = content.parse::<i64>() else {
ctx.fail("manual_fail: conversion failed");
return 0;
};

result
}

/// From a user perspective, this function does the same thing as `.manual_fail()`,
/// except its underlying `rust` implementation is slightly different.
///
/// In a more idiomatic way, we return a Result, and the generated boilerplate will be in charge of
/// calling `ctx.fail() and return a default value.
pub fn result_fail(fp: &str) -> Result<i64, String> {
// read the file
read_to_string(fp)
// convert the error (if any!), into a string and return right away with the `?` operator
.map_err(|e| format!("result_fail: {e}"))?
// try to parse content into i64
.parse::<i64>()
// map the error to a string message and return either the parsed integer or that error
.map_err(|e| format!("result_fail: {e}"))
}
}
19 changes: 0 additions & 19 deletions examples/vmod_error/vmod.vcc

This file was deleted.

3 changes: 0 additions & 3 deletions examples/vmod_event/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,6 @@ version = "0.0.0"
publish = false
edition.workspace = true

[build-dependencies]
varnish.workspace = true

[dependencies]
varnish.workspace = true

Expand Down
24 changes: 24 additions & 0 deletions examples/vmod_event/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<!--
!!!!!! WARNING: DO NOT EDIT THIS FILE!
This file was generated from the Varnish VMOD source code.
It will be automatically updated on each build.
-->
# Varnish Module (VMOD) `event`

Listen to VCL event

```vcl
// Place import statement at the top of your VCL file
// This loads vmod from a standard location
import event;
// Or load vmod from a specific file
import event from "path/to/libevent.so";
```

### Function `INT loaded()`

Return the number of VCL loads stored during when the event function ran.
3 changes: 0 additions & 3 deletions examples/vmod_event/build.rs

This file was deleted.

Loading

0 comments on commit 40d9c37

Please sign in to comment.