Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

unset bereq.body does not remove Content-Length header if body has been already consumed. #4228

Open
LorenzoPeri opened this issue Nov 14, 2024 · 0 comments
Assignees

Comments

@LorenzoPeri
Copy link

Expected Behavior

My Varnish configuration performs 2 backend requests (first HEAD, then GET) for each client GET request.
The reason why I need to do this is not relevant.

Consider this pseudocode:

sub vcl_backend_fetch {
  if ( [first iteration] ) {
    set bereq.method = "HEAD"; // perform the backend HEAD request first
  } 
  // unset body because I'm not interested in request body that clients might send by mistake
  unset bereq.body;
}

sub vcl_deliver {
 if( [head request completed] ) {
   return (restart); // restart to perform the backend GET request
 }
}

I expect this to work fine even if the client GET request has a body.

Note: I can also move the unset bereq.body; statement inside the if ( [first iteration] ) , the behavior is the same, probably because of https://github.com/varnishcache/varnish-cache/blob/varnish-7.6.1/bin/varnishd/builtin.vcl#L201

Current Behavior

What I see with varnishlog is:

  • for backend HEAD request:
-   BereqHeader    Content-Length: 16
-   BereqUnset     Content-Length: 16
-   BereqAcct      424 0 424 249 0 249 // body is 0 bytes
  • for backend GET request:
-   BereqHeader    Content-Length: 16
-   BereqAcct      611 0 611 424 13497 13921 // body is 0 bytes 

Therefore Content-Length on the GET request it not removed.
It's also not consistent with the actual body, which makes the backend server (Tomcat in my case) to misbehave.

Possible Solution

It's just a guess, but it's possible that bereq_body is NULL on this check for the second backend request:
https://github.com/varnishcache/varnish-cache/blob/varnish-7.6.1/bin/varnishd/cache/cache_vrt_var.c#L631

VRT_u_bereq_body(VRT_CTX)
{
        ...
	if (ctx->bo->bereq_body != NULL) {
		(void)HSH_DerefObjCore(ctx->bo->wrk, &ctx->bo->bereq_body, 0);
		http_Unset(ctx->bo->bereq, H_Content_Length);
	} 
       ...
}

.. and therefore Content-Length is not removed, which would be the ideal behavior.

Steps to Reproduce (for bugs)

I can work on a basic VCL file if you think it's needed.

Context

Clients that are outside of my control are sending GET requests with a useless body.

The second Varnish backend request has a Content-Length header inconsistent with the actual body, which makes the backend server (Tomcat in my case) to misbehave.

I don't need this request body and I want to remove it both from both HEAD and GET backend requests.

As fallback solution, it's also acceptable to forward the body to backends, but Content-Length should be consistent with the actual body.

Varnish Cache version

7.5.0

Operating system

AlmaLinux-8

Source of binary packages used (if any)

No response

@LorenzoPeri LorenzoPeri changed the title unset bereq.body does not remove 'Content-Length' header if body has been already consumed. unset bereq.body does not remove Content-Length header if body has been already consumed. Nov 14, 2024
@nigoroll nigoroll self-assigned this Nov 18, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants