Preflighting for paywall

Use a custom Paywall header to trigger preflight requests to authenticate every article view with a backend paywall service.

VCL

Use this solution in your VCL service (click RUN below to test this solution or clone it to make changes):

Compute@Edge

Use this solution in your Compute@Edge service:

  1. Rust
// Ingest cookies
if let Some(req_cookie_jar) = req
.get_header(COOKIE)
.and_then(|h| parse_cookies_to_jar(&h).ok())
{
req.remove_header(COOKIE);
// Getting a session ID from a cookie is rather simplistic in this
// demo. For a more advanced solution, combine the paywall pattern
// with a JSON web token verification at the edge
req.set_header(
"auth-sessionid",
req_cookie_jar
.get("sessionid")
.map(|c| c.value())
.unwrap_or_default(),
);
}
// Only GETs and HEADs are considered for paywall restriction.
if !matches!(req.get_method(), &Method::GET | &Method::HEAD) {
return Ok(req.send(CONTENT_BACKEND)?);
}
let _ = req.take_body(); // request bodies will not be forwarded.
// run the content request
let mut content_resp = req.send(CONTENT_BACKEND)?;
// if 403 or 5xx - don't continue
if content_resp.get_status() == 403 || content_resp.get_status().is_server_error() {
return Ok(content_resp);
}
// If the response contains `paywall` header we run a check against the URL
let paywall_hdr = match content_resp.remove_header("paywall") {
None => {
// No paywall header received, deliver the content
return Ok(content_resp);
}
Some(paywall_hdr) => paywall_hdr,
};
let paywall_url = Url::parse(paywall_hdr.to_str()?)?;
if paywall_url.host_str() != Some("fiddle-paywall.glitch.me") {
// Not an expected paywall, deliver the content as is
return Ok(content_resp);
}
// First, re-create a request with original headers we received from client
let mut paywall_req = content_resp.take_backend_request().unwrap();
paywall_req.set_url(paywall_url);
// run the request against the paywall and get a response
let paywall_resp = paywall_req.send(PAYWALL_BACKEND)?;
// Check the paywall response
if let Some(result_value) = paywall_resp.get_header("paywall-result") {
if result_value == "BLOCK" {
// if answer is `BLOCK` - deliver an error
return Ok(Response::from_body(
"<p>This content is only available to premium subscribers.</p>\n",
)
.with_content_type(mime::TEXT_HTML)
.with_status(StatusCode::FORBIDDEN));
}
let meta_header = &HeaderName::from_static("paywall-meta");
if let Some(paywall_meta) = paywall_resp.get_header(meta_header) {
content_resp.set_header(meta_header, paywall_meta.clone());
}
}
Ok(content_resp)