-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
27 changed files
with
1,860 additions
and
118 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,49 +1,55 @@ | ||
varnish::boilerplate!(); | ||
|
||
use std::fs::read_to_string; | ||
|
||
use varnish::vcl::ctx::Ctx; | ||
|
||
varnish::vtc!(test01); | ||
|
||
// 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 { | ||
return ctx | ||
.fail("manual_fail: couldn't read file into string") | ||
.into(); | ||
}; | ||
|
||
// try to convert the string into an i64 | ||
// no need to return as the last expression is automatically returned | ||
content | ||
.parse::<i64>() | ||
.unwrap_or_else(|_| ctx.fail("manual_fail: conversion failed").into()) | ||
/// This is a simple example of how to handle errors in a Varnish VMOD. | ||
#[varnish::vmod] | ||
mod error { | ||
use std::fs::read_to_string; | ||
|
||
use varnish::vcl::ctx::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) | ||
} | ||
|
||
// 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 { | ||
return ctx | ||
.fail("manual_fail: couldn't read file into string") | ||
.into(); | ||
}; | ||
|
||
// try to convert the string into an i64 | ||
// no need to return as the last expression is automatically returned | ||
content | ||
.parse::<i64>() | ||
.unwrap_or_else(|_| ctx.fail("manual_fail: conversion failed").into()) | ||
} | ||
|
||
// 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(fp: &str) -> Result<i64, String> { | ||
read_to_string(fp) // read the file | ||
.map_err(|e| format!("result_fail: {e}"))? // convert the error (if any!), into a string | ||
// the ? will automatically return in case | ||
// of an error | ||
.parse::<i64>() // convert | ||
// map the type, and we are good to | ||
// automatically return | ||
.map_err(|e| format!("result_fail: {e}")) | ||
} | ||
} | ||
|
||
// 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_to_string(fp) // read the file | ||
.map_err(|e| format!("result_fail: {e}"))? // convert the error (if any!), into a string | ||
// the ? will automatically return in case | ||
// of an error | ||
.parse::<i64>() // convert | ||
.map_err(|e| format!("result_fail: {e}")) // map the type, and we are good to | ||
// automatically return | ||
#[cfg(test)] | ||
mod tests { | ||
varnish::vtc!(test01); | ||
} |
File renamed without changes.
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,60 +1,45 @@ | ||
// import the generated boilerplate | ||
varnish::boilerplate!(); | ||
#[varnish::vmod] | ||
mod example { | ||
// we now implement both functions from vmod.vcc, but with rust types. | ||
// Don't forget to make the function public with "pub" in front of them | ||
|
||
// even though we won't use it here, we still need to know what the context type is | ||
use varnish::vcl::ctx::Ctx; | ||
|
||
// we now implement both functions from vmod.vcc, but with rust types. | ||
// Don't forget to make the function public with "pub" in front of them | ||
|
||
pub fn is_even(_: &Ctx, n: i64) -> bool { | ||
n % 2 == 0 | ||
} | ||
pub fn is_even(n: i64) -> bool { | ||
n % 2 == 0 | ||
} | ||
|
||
// in vmod.vcc, n was an optional INT, so here it translates into an Option<i64> | ||
pub fn captain_obvious(_: &Ctx, opt: Option<i64>) -> String { | ||
// we need to first "match" to know if a number was provided, if not, | ||
// return a default message, otherwise, build a custom one | ||
match opt { | ||
// no need to return, we are the last expression of the function! | ||
None => String::from("I was called without an argument"), | ||
// pattern matching FTW! | ||
Some(n) => format!("I was given {n} as argument"), | ||
// in vmod.vcc, n was an optional INT, so here it translates into an Option<i64> | ||
pub fn captain_obvious(opt: Option<i64>) -> String { | ||
// we need to first "match" to know if a number was provided, if not, | ||
// return a default message, otherwise, build a custom one | ||
match opt { | ||
// no need to return, we are the last expression of the function! | ||
None => String::from("I was called without an argument"), | ||
// pattern matching FTW! | ||
Some(n) => format!("I was given {n} as argument"), | ||
} | ||
} | ||
} | ||
|
||
#[cfg(test)] | ||
mod tests { | ||
use varnish::vcl::ctx::TestCtx; | ||
use super::example::*; | ||
|
||
use super::*; | ||
// test with test/test01.vtc | ||
varnish::vtc!(test01); | ||
|
||
#[test] | ||
fn obviousness() { | ||
let mut test_ctx = TestCtx::new(100); | ||
let ctx = test_ctx.ctx(); | ||
|
||
assert_eq!( | ||
"I was called without an argument", | ||
captain_obvious(&ctx, None) | ||
); | ||
assert_eq!("I was called without an argument", captain_obvious(None)); | ||
assert_eq!( | ||
"I was given 975322 as argument", | ||
captain_obvious(&ctx, Some(975_322)) | ||
captain_obvious(Some(975_322)) | ||
); | ||
} | ||
|
||
#[test] | ||
fn even_test() { | ||
// we don't use it, but we still need one | ||
let mut test_ctx = TestCtx::new(100); | ||
let ctx = test_ctx.ctx(); | ||
|
||
assert!(is_even(&ctx, 0)); | ||
assert!(is_even(&ctx, 1024)); | ||
assert!(!is_even(&ctx, 421_321)); | ||
assert!(is_even(0)); | ||
assert!(is_even(1024)); | ||
assert!(!is_even(421_321)); | ||
} | ||
|
||
// we also want to run test/test01.vtc | ||
varnish::vtc!(test01); | ||
} |
File renamed without changes.
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,21 +1,27 @@ | ||
varnish::boilerplate!(); | ||
#[varnish::vmod] | ||
mod infiniteloop { | ||
use varnish::ffi::{BUSYOBJ_MAGIC, REQ_MAGIC}; | ||
use varnish::vcl::ctx::Ctx; | ||
|
||
use varnish::ffi::{BUSYOBJ_MAGIC, REQ_MAGIC}; | ||
use varnish::vcl::ctx::Ctx; | ||
|
||
varnish::vtc!(test01); | ||
|
||
/// # Safety | ||
/// this function is unsafe from the varnish point of view, doing away with | ||
/// important safeguards, but it's also unsafe in the rust way: it dereferences | ||
/// pointers which may lead nowhere | ||
pub unsafe fn reset(ctx: &mut Ctx) { | ||
if let Some(req) = ctx.raw.req.as_mut() { | ||
assert_eq!(req.magic, REQ_MAGIC); | ||
req.restarts = 0; | ||
} | ||
if let Some(bo) = ctx.raw.bo.as_mut() { | ||
assert_eq!(bo.magic, BUSYOBJ_MAGIC); | ||
bo.retries = 0; | ||
/// # Safety | ||
/// this function is unsafe from the varnish point of view, doing away with | ||
/// important safeguards, but it's also unsafe in the rust way: it dereferences | ||
/// pointers which may lead nowhere | ||
pub fn reset(ctx: &mut Ctx) { | ||
unsafe { | ||
if let Some(req) = ctx.raw.req.as_mut() { | ||
assert_eq!(req.magic, REQ_MAGIC); | ||
req.restarts = 0; | ||
} | ||
if let Some(bo) = ctx.raw.bo.as_mut() { | ||
assert_eq!(bo.magic, BUSYOBJ_MAGIC); | ||
bo.retries = 0; | ||
} | ||
} | ||
} | ||
} | ||
|
||
#[cfg(test)] | ||
mod tests { | ||
varnish::vtc!(test01); | ||
} |
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
lints.workspace = true | ||
|
||
[package] | ||
name = "vmod_proc" | ||
version = "0.0.1" | ||
edition = "2021" | ||
|
||
# if you copy this into a standalone repository, | ||
# replace `{ path = "../.." }` with `"0.0.19"` | ||
[build-dependencies] | ||
varnish = { path = "../.." } | ||
|
||
[dependencies] | ||
varnish = { path = "../.." } | ||
|
||
[lib] | ||
crate-type = ["cdylib"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
# vmod_example | ||
|
||
Here you will find a starting point for your own vmods, and to learn coding vmods in `rust`. Ideally, you should be familiar at least with either vmod development, or with `rust` development, but if your starting fresh, this should get you going too. | ||
|
||
# Compiling | ||
|
||
You need only two things: | ||
- a stable version of `cargo`/`rust` | ||
- the `libvarnish` development files installed where `pkg-config` can find them | ||
- `python31 | ||
|
||
From within this directory, run: | ||
|
||
``` | ||
# build | ||
cargo build | ||
# you should now have a file name target/debug/libvmod_example.so | ||
# test (you need to build first!) | ||
cargo test | ||
``` | ||
|
||
That's it! | ||
|
||
# Files | ||
|
||
Look around, everything should be decently documented: | ||
- [vmod.vcc](vmod.vcc): your starting point, where you will describe your vmod API | ||
- [src/vmod.rs](src/vmod.rs): the file containing the actual implementation and unit tests | ||
- [tests/test01.vtc](tests/test01.vtc): a VTC (full stack) test, actually running Varnish against mock clients and servers | ||
- [Cargo.toml](Cargo.toml): the file describing the name of the vmod, as well as its dependencies | ||
- [build.rs](build.rs): a short program in charge of generating some boilerplate before the compiler starts |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
#[varnish::vmod] | ||
mod proc { | ||
pub fn is_even(n: i64) -> bool { | ||
n % 2 == 0 | ||
} | ||
} | ||
|
||
#[cfg(test)] | ||
mod tests { | ||
use super::proc::*; | ||
|
||
#[test] | ||
fn even_test() { | ||
assert!(is_even(0)); | ||
assert!(is_even(1024)); | ||
assert!(!is_even(421_321)); | ||
} | ||
|
||
// we also want to run test/test01.vtc | ||
varnish::vtc!(test01); | ||
} |
Oops, something went wrong.