Mailing List Archive

thoughts about vcl cleanup around (be)resp.body and abandon/synth
Hi,

it appeared to me that VCL is cumbersome for handling body replacement on the
backend side and the behavior of abandon from the client side is confusing.

Current status:

- generating synthetic content (setting a body) on the backend side is only
possible in vcl_backend_error. To get there, we need to reach the max
retries or trigger a fetch error. To tell vcl_backend_error what to do,
we need markers in bereq.http.*

- return(abandon) fails the backend request and ends up on the client side,
but we can't tell the client side what to do

Suggestion:

- retire synthetic and support (un)set (be)resp.body
(not directly related to the topic, but something we should do
for consistency)

- add support for (un)set beresp.body to vcl_backend_response
if used:
-> short-term: silently abort the backend connection
-> better: discard-read the response body

- add support for (un)set resp.body to vcl_deliver

- rename vcl_backend_error to vcl_backend_synth to be consistent
with the client side

- add status and reason to abandon which get pre-set for the call
to vcl_synth

503 as default

- add return(backend_synth(status, reason)) to vcl_backend_fetch
as an easy way to return synthetic content at backend request
time.

More thoughts:

- if we want the (un)set beresp.body, should we maybe have

set beresp.body = fetch()

also?

This would be the default if no other beresp.body action happend
in vcl_backend_response

Thanks, Nils

_______________________________________________
varnish-dev mailing list
varnish-dev@varnish-cache.org
https://www.varnish-cache.org/lists/mailman/listinfo/varnish-dev
Re: thoughts about vcl cleanup around (be)resp.body and abandon/synth [ In reply to ]
> - rename vcl_backend_error to vcl_backend_synth to be consistent
> with the client side

I'd rather have both subroutines and distinguish between actual fetch
errors and artificial backend responses.

As a side note, at some point I remember discussing (with at least
phk) carrying the SLT_Error message in a bereq.error readable only
from v_b_e.

> - add status and reason to abandon which get pre-set for the call
> to vcl_synth
>
> 503 as default

+1, except for the default but I wouldn't mind it.

> - add return(backend_synth(status, reason)) to vcl_backend_fetch
> as an easy way to return synthetic content at backend request
> time.

I don't mind namespacing it, but I'd go for just synth.

> More thoughts:
>
> - if we want the (un)set beresp.body, should we maybe have
>
> set beresp.body = fetch()
>
> also?

What happens if I set the beresp.body several times with and without fetch()?

I actually need to check what happens today if you synthetic()/set
*resp.body more than once.

> This would be the default if no other beresp.body action happend
> in vcl_backend_response

I have trouble being convinced by the behavior, despite me being
previously in favor of being able to set beresp.body in v_b_r. After
two mental context switches it no longer seems like such a good idea
to me.

Cheers

_______________________________________________
varnish-dev mailing list
varnish-dev@varnish-cache.org
https://www.varnish-cache.org/lists/mailman/listinfo/varnish-dev
Re: thoughts about vcl cleanup around (be)resp.body and abandon/synth [ In reply to ]
On 29/11/16 16:30, Nils Goroll wrote:
> - generating synthetic content (setting a body) on the backend side is only
> possible in vcl_backend_error. [...]

Thank you to fgs for pointing our that people who are not following IRC may find
it hard to understand the actual use case I am working on.

It's dead simple: Replace bodies for backend responses which should not be sent
downstream while keeping the original response headers (or at least some).

Nils

_______________________________________________
varnish-dev mailing list
varnish-dev@varnish-cache.org
https://www.varnish-cache.org/lists/mailman/listinfo/varnish-dev
Re: thoughts about vcl cleanup around (be)resp.body and abandon/synth [ In reply to ]
On Tue, Nov 29, 2016 at 3:30 PM, Nils Goroll <slink@schokola.de> wrote:

> [..]
> Suggestion:
>
> - retire synthetic and support (un)set (be)resp.body
> (not directly related to the topic, but something we should do
> for consistency)
>

set (be)resp.body is already supported, but restricted to vcl_backend_error
/ vcl_synth.
I did not retire it to maintain compatibility and because I'm was, and
still am, unclear as to what the future plans are wrt bodies.


> - add support for (un)set beresp.body to vcl_backend_response
> if used:
> -> short-term: silently abort the backend connection
> -> better: discard-read the response body
>

I will not object "unset beresp.body" but setting the body in the middle of
vcl_backend_response{} feels odd to me.


> - add support for (un)set resp.body to vcl_deliver
>

Is this the same use case but for hits?
If so, I'm on the opinion of allowing to unset the body but not generating
one, same as above in the vcl_backend_response{} case.


> - rename vcl_backend_error to vcl_backend_synth to be consistent
> with the client side
>

I'd object to this. I think the current name is fine and self-explanatory.


> - add status and reason to abandon which get pre-set for the call
> to vcl_synth
>
> 503 as default
>

+1


> - add return(backend_synth(status, reason)) to vcl_backend_fetch
> as an easy way to return synthetic content at backend request
> time.
>

I'm all for adding return(error(code, reason)) to go to vcl_backend_error{}.
I think this subroutine should not be renamed.


> More thoughts:
>
> - if we want the (un)set beresp.body, should we maybe have
>
> set beresp.body = fetch()
>
> also?
>

I'd prefer to have a way to express the opposite, as in "unset beresp.body".



> This would be the default if no other beresp.body action happend
> in vcl_backend_response
>
> Thanks, Nils
>
> _______________________________________________
> varnish-dev mailing list
> varnish-dev@varnish-cache.org
> https://www.varnish-cache.org/lists/mailman/listinfo/varnish-dev
>
Re: thoughts about vcl cleanup around (be)resp.body and abandon/synth [ In reply to ]
On 29/11/16 21:45, Federico Schwindt wrote:
> I will not object "unset beresp.body" but setting the body in the middle of
> vcl_backend_response{} feels odd to me.

This seems to be the item with the least consensus.

For the use case of replacing the body while keeping headers, the alternative is

- copy response headers to bereq or
- use a vmod to save them
- resurrect them in v_b_e

While this is feasible, I sill don't understand why we would need a de-tour over
v_b_e just to create a synthetic body.

Why would we

- want unset beresp.body;
- but not set beresp.body;

?

Both need to abort the backend connection or drain the request in progress, the
only difference would be if we end up with an empty ws non-empty object.

Nils

P.S.: Actually this is something which worked in varnish2, where one could just
call synthetic in vcl_fetch

_______________________________________________
varnish-dev mailing list
varnish-dev@varnish-cache.org
https://www.varnish-cache.org/lists/mailman/listinfo/varnish-dev
Re: thoughts about vcl cleanup around (be)resp.body and abandon/synth [ In reply to ]
On Wed, Nov 30, 2016 at 9:44 AM, Nils Goroll <slink@schokola.de> wrote:
> On 29/11/16 21:45, Federico Schwindt wrote:
>> I will not object "unset beresp.body" but setting the body in the middle of
>> vcl_backend_response{} feels odd to me.
>
> This seems to be the item with the least consensus.
>
> For the use case of replacing the body while keeping headers, the alternative is
>
> - copy response headers to bereq or
> - use a vmod to save them

I will merely point out that you can't iterate over a headers in VCL,
and you'd need a way to distinguish bereq headers from beresp headers
if you copy them in one place.

> - resurrect them in v_b_e
>
> While this is feasible, I sill don't understand why we would need a de-tour over
> v_b_e just to create a synthetic body.

The problem with using v_b_e is that you need to trick Varnish to get
there on purpose

It would work better like this:

- in v_b_r
- some_vmod.save_headers(beresp) (with some priv_task-ness)
- return synth or backend_synth(XXX)
- in a v_b_synth
- check status is XXX
- some_vmod.restore_headers(beresp)
- set beresp.body

But as discussed on IRC yesterday after the initial use case was
reminded, I finally made up my mind and agreed it would make sense
having set beresp.body in v_b_r.

I also see a case for having synthetic (even cacheable if needed)
backend responses, eg via a vmod. This is doable today, but as I said
by tricking Varnish before the fetch and from v_b_r you can't jump
directly to v_b_e. Very convoluted for a simple need.

> Both need to abort the backend connection or drain the request in progress, the
> only difference would be if we end up with an empty ws non-empty object.

Ideally drain the response (you meant response?) because the backend
may not be a native h1/tcp one.

> P.S.: Actually this is something which worked in varnish2, where one could just
> call synthetic in vcl_fetch

Wut? There was a Varnish before 3.0?

_______________________________________________
varnish-dev mailing list
varnish-dev@varnish-cache.org
https://www.varnish-cache.org/lists/mailman/listinfo/varnish-dev
Re: thoughts about vcl cleanup around (be)resp.body and abandon/synth [ In reply to ]
On Wed, Nov 30, 2016 at 9:24 AM, Dridi Boukelmoune <dridi@varni.sh> wrote:

> [..]
> > While this is feasible, I sill don't understand why we would need a
> de-tour over
> > v_b_e just to create a synthetic body.
>
> The problem with using v_b_e is that you need to trick Varnish to get
> there on purpose
>

I think we all agree that there should be a way to go to vcl_backend_error
from the other 2 backend subroutines.
Re: thoughts about vcl cleanup around (be)resp.body and abandon/synth [ In reply to ]
> I think we all agree that there should be a way to go to vcl_backend_error
> from the other 2 backend subroutines.

For completeness, I did not agree to that yesterday because I'd rather
keep error handling separate from artificial responses. I don't have
fond memories of vcl_error days.

_______________________________________________
varnish-dev mailing list
varnish-dev@varnish-cache.org
https://www.varnish-cache.org/lists/mailman/listinfo/varnish-dev
Re: thoughts about vcl cleanup around (be)resp.body and abandon/synth [ In reply to ]
Sorry for being extremely late to this debate.

The fundamental problem is that the body is not like headers, and
IMO trying to make it look like one is a grave mistake.

I am also very surprised that the word "filter" appears nowhere in
the emails in this thread?

We need to decide how VCL produced fetch bodies work with VFP, and why.

If the answer is "They dont", then the "why" part needs a better
answer than "I personally wont need that", because we know there
are users wanting this.

If the answer is "They do", then we need to figure out how VFP's work
in VCL in the first place, before we can progress much.

I think the correct answer is "They do", but I'm willing to be persuaded.

I have been thinking about the VCL/filter issue a lot, and all but
one of my ideas becomes a royal mess to implement.

The one idea which only becomes a mere ducal mess, is that
vcl_backend_response{} gets a new variable named beresp.filter_list
which contains a space-separated list of VFP's to use ("gunzip esi gzip")

If you want modify the filter stack, you edit that beresp.filter_list,
probably with a regsub().

VMODs offering novel filters, must register them, so they can be
found when the list is interpreted, which unfortunately leaves a
hole wrt. to passing parameters from VCL to that filter instance.

As for stuffing actual content through the filters and into the
resp.body, that cannot happen in backend_response{} because we have
neither object, storage or filterstack yet.

The vcl_synth{} vcl_backend_error{} situation is not very satisfying
and trying to build on that seems unwise.

One possible solution, on both client and backend side, would be to
be able to tell what function to call to produce the body, in straw-man
form something like:

sub my_error {
body += "<HTML>";
body += "<H1>" + bereq.url + "</H1>"
body += vmod.foobar(something, something);
body += "<BLINK>Because We Can</BLINK>";
body += "</HTML>";
}

sub vcl_backend_response {
[...]
set beresp.[...];
return (synth(my_error));
}

It goes without saying that the "body-functions" would not be able
to do anything else etc.

Semi-major VCC work in other words...

The final thing I want to say at this point is that before we do
any of this, we need to change how VCL fails.

It used to be that we would try to muddle through when VCL did
something counter-productive, but that is increasingly hard and
increasingly wrong.

I'm not done figuring out how a "VCL botched up" state would look,
inputs welcome.

--
Poul-Henning Kamp | UNIX since Zilog Zeus 3.20
phk@FreeBSD.ORG | TCP/IP since RFC 956
FreeBSD committer | BSD since 4.3-tahoe
Never attribute to malice what can adequately be explained by incompetence.

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