Mailing List Archive

VCL: returning early from a custom function
Hi again,

two messages in a day after a few years :-)

I have code similar to the following (also here[1]):

sub vcl_recv {
...
call rate_limit;
...
}

# Throttling based on request inspection
sub rate_limit {

if (req.url ~ "pattern1") {
std.log("pattern1 requests must never be throttled");
return; # <---- Need to return early here, but can't do it
}

if (req.url ~ "pattern2") {
if (vsthrottle.is_denied("pattern2" + client.identity, 100, 10s)) {
std.log("pattern2 throttling for ip " + client.identity);
return(synth(429, "ETOOMANYREQUESTS"));
}
}

if (vsthrottle.is_denied("ip:" + client.identity, 500, 10s)) {
std.log("global throttling for ip " + client.identity);
return(synth(429, "ETOOMANYREQUESTS"));
}

}

Ideally, I'd like to return early from rate_limit() when I know that I don't need
to enforce any rate limiting for some types of requests, but I understand
that's not implemented.

I found some alternatives, though generally they feel uglier.
Any ideas?

--
Cosimo

[1] https://gist.github.com/cosimo/6d3318bf173357dfb2652b7b2e81e1e0#file-gistfile1-txt-L18
_______________________________________________
varnish-misc mailing list
varnish-misc@varnish-cache.org
https://www.varnish-cache.org/lists/mailman/listinfo/varnish-misc
Re: VCL: returning early from a custom function [ In reply to ]
> I found some alternatives, though generally they feel uglier.
> Any ideas?

This has been discussed in the past, including the possibility to
return a value, but as of today you can't break out of a subroutine.

https://github.com/varnishcache/varnish-cache/wiki/VIP2%3A-VCL-typed-functions

With this feature you could break out of a subroutine by turning it
into a function that returns VOID. We are not there yet.

Dridi
_______________________________________________
varnish-misc mailing list
varnish-misc@varnish-cache.org
https://www.varnish-cache.org/lists/mailman/listinfo/varnish-misc
Re: VCL: returning early from a custom function [ In reply to ]
What about:

sub rate_limit {

if (req.url ~ "pattern1") {
std.log("pattern1 requests must never be throttled");
}
else {
if (req.url ~ "pattern2") {
if (vsthrottle.is_denied("pattern2" + client.identity,
100, 10s)) {
std.log("pattern2 throttling for ip " +
client.identity);
return(synth(429, "ETOOMANYREQUESTS"));
}
}

if (vsthrottle.is_denied("ip:" + client.identity, 500, 10s)) {
std.log("global throttling for ip " + client.identity);
return(synth(429, "ETOOMANYREQUESTS"));
}
}

}

tom


Am 11.04.2018 um 15:59 schrieb Cosimo Streppone:
> Hi again,
>
> two messages in a day after a few years :-)
>
> I have code similar to the following (also here[1]):
>
> sub vcl_recv {
> ...
> call rate_limit;
> ...
> }
>
> # Throttling based on request inspection
> sub rate_limit {
>
> if (req.url ~ "pattern1") {
> std.log("pattern1 requests must never be throttled");
> return; # <---- Need to return early here, but can't do it
> }
>
> if (req.url ~ "pattern2") {
> if (vsthrottle.is_denied("pattern2" + client.identity, 100, 10s)) {
> std.log("pattern2 throttling for ip " + client.identity);
> return(synth(429, "ETOOMANYREQUESTS"));
> }
> }
>
> if (vsthrottle.is_denied("ip:" + client.identity, 500, 10s)) {
> std.log("global throttling for ip " + client.identity);
> return(synth(429, "ETOOMANYREQUESTS"));
> }
>
> }
>
> Ideally, I'd like to return early from rate_limit() when I know that I don't need
> to enforce any rate limiting for some types of requests, but I understand
> that's not implemented.
>
> I found some alternatives, though generally they feel uglier.
> Any ideas?
>

_______________________________________________
varnish-misc mailing list
varnish-misc@varnish-cache.org
https://www.varnish-cache.org/lists/mailman/listinfo/varnish-misc
Re: VCL: returning early from a custom function [ In reply to ]
On Wed, Apr 11, 2018, at 16:43, Anheyer, Tom wrote:
> What about:
>
> sub rate_limit {
>
> if (req.url ~ "pattern1") {
> std.log("pattern1 requests must never be throttled");
> }
> else {
> if (req.url ~ "pattern2") {
> if (vsthrottle.is_denied("pattern2" + client.identity,
> 100, 10s)) {
> std.log("pattern2 throttling for ip " +
> client.identity);
> return(synth(429, "ETOOMANYREQUESTS"));
> }
> }
>
> if (vsthrottle.is_denied("ip:" + client.identity, 500, 10s)) {
> std.log("global throttling for ip " + client.identity);
> return(synth(429, "ETOOMANYREQUESTS"));
> }
> }
>
> }

Yes, that's one of the alternatives, though the "whitelisted" patterns
are more than just one.

I ended up doing something like:

set req.http.Rate-Limit = "1";

if (whitelisted-pattern1) { set req.http.Rate-Limit = "0"; }
if (whitelisted-pattern2) { set req.http.Rate-Limit = "0"; }
...

if (req.http.Rate-Limit == "0") {
# no rate limiting
} else {
# yes, do rate limit
}

I intend to look at vmod_var to see if I can make this prettier.

--
Cosimo
_______________________________________________
varnish-misc mailing list
varnish-misc@varnish-cache.org
https://www.varnish-cache.org/lists/mailman/listinfo/varnish-misc