How to add "Vary: Accept-Encoding" header in yaws to cacheable files - http-headers

I was testing my website for optimization and I got this recommendation:
The following publicly cacheable, compressible resources should have a "Vary: Accept-Encoding" header:
So, How do I add Vary: Accept-Encoding header using an embedded yaws to css and js files?
I am an arg_rewrite_mod I believe I should do something from there but i am not quite sure how.

According to the yaws.hyber.org:
Yaws will add Accept-Encoding in Vary header if the support of gzip compression is enabled or if the response is compressed.
The Vary header can be set using yaws:outh_set_vary(Fields) or by returning {header, {vary, Fields}} from scripts (where Fields is a list of header names).

Related

Vary: Accept-Encoding Response Header

I am trying to understand the response Header "Vary: Accept-Encoding".
I am noticing the response header "Vary: Accept-Encoding" appears for some of the images in the developer tools for our application, but some images doesn't have this response header.
When i tried to hit same image url in the browser, not seeing this header "Vary: Accept-Encoding".
Why this header appears only for selected images in our application? What could be possibilities?
Either Tomcat or the application could be returning this header. If Tomcat is applying e.g. gzip encoding, then it's essential to respond with a Vary: Accept-Encoding because if the client doesn't specify that it supports gzip then the origin server (web server), a proxy, etc. must respond with a different type of data.
If the client requests /myapp/something and advertises that it is willing to accept only responses with encoding gzip, then /myapp/something should really only return a response in the identity or gzip encodings, or reply with a 412 response.
The Vary header is really for proxies. It tells a proxy that clients on the other side might get a different response if they have different Accept-Encoding values in their request headers. So, if two clients request the same resource, but one says Accept-Encoding: identity,gzip and the other says Accept-Encoding: identity,compress, they will (likely) get two responses, and the proxy should understand that it's not just the URL that is important, but also the Accept-Encoding of the client that should govern any caching that the proxy might want to provide.

What is the difference between "always" and "onsuccess" in Apache's Header config?

I have a website where virtual hosts are defined in /etc/apache2/sites-enabled/ with a header being set with the always option like this:
Header always set X-Frame-Options DENY
If I now set the same header using .htaccess in the web site's root folder, but without always then the header is returned twice in the server's response.
The setting in .htaccess (amongst others):
Header set X-Frame-Options DENY
The server's response:
HTTP/1.1 200 OK
Date: Mon, 02 May 2016 16:02:29 GMT
Server: Apache/2.4.10 (Debian)
X-Frame-Options: DENY
Cache-Control: no-cache, no-store, must-revalidate, private
Pragma: no-cache
X-XSS-Protection: 1
X-Content-Type-Options: nosniff
Last-Modified: Mon, 02 May 2016 15:03:42 GMT
Accept-Ranges: bytes
Content-Length: 0
X-Frame-Options: DENY
X-XSS-Protection: 1
X-Content-Type-Options: nosniff
Cache-Control: no-cache, no-store, must-revalidate, private
Pragma: no-cache
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Content-Type: text/html
The Apache docs say that without the always option the default value of onsuccess is used. But they also say that "... the default value of onsuccess does not limit an action to responses with a 2xx status code..." (http://httpd.apache.org/docs/current/en/mod/mod_headers.html#header).
But if I don't add always, then error pages like 301s and 404s will not have the header set. On the other hand, if I do add always then the headers might be set twice if I do use the default value (i.e. onsuccess) in .htaccess. As the docs state: "repeating this directive with both conditions makes sense in some scenarios because always is not a superset of onsuccess with respect to existing headers". Setting headers twice is not always valid for an HTTP response, see https://stackoverflow.com/a/4371395/641481. So I want to avoid it, naturally.
My question now is: When exactly should I use onsuccess (i.e. the default value) and when always? I must admit that even after reading through the Apache docs a couple of times I do not exactly understand this. Pragmatically it seems that always using always leads to the correct/expected behaviour.
I also do not understand why Apache writes the header twice if it is set in always and onsuccess. It seems wrong to me, but there must be a good reason for this, since I assume the Apache-devs know a lot more than I do about HTTP ;-)
This is only a partial answer since it does not cover the onsuccess attribute. It is based on experiences using apache 2.4.7 running on an Ubuntu 14 os. Hope it helps you along.
The pure set parameter, without attributes, to the Header directive overwrites any always attribute by forcing the argument to Header set to be the only one delivered. If the same directive appears in a directory, i.e. file system based .htaccess file it has precedence over the same directive noted in a virtual host definition file related to that directory. If the attribute always is noted additionaly, it has the effect that any, equal or different, notation of the same directive is added to the server answer instead of overwriting/replacing it.
Probably the onsuccess attribute, which i unfortunately do not have the time to explore now, may be handled similar as the always attribute.
We use Adobe Experience Manager with a Dispatcher [caching] module for our Apache webserver. Adobe recently changed the code below. Essentially I believe you may need to use the "expr=" syntax to make sure the value is not already set. That should eliminate the duplicates.
Here's the reference code from Adobe:
Original Config: Header always append X-Frame-Options SAMEORIGIN
New Config: Header merge X-Frame-Options SAMEORIGIN "expr=%{resp:X-Frame-Options}!='SAMEORIGIN'"
When I inquired, Adobe gave me the following reasons. Thanks Adobe.
Explanation:
Using "merge" instead of "append" prevents the entry's value from from being added to the header more than once.
expr=expression: The directive is applied if and only if expression evaluates to true. Details of expression syntax and evaluation are documented in the ap_expr documentation. The "expr" is looking in the response headers from the server (Publisher Application Server) to make sure that it does not include SAMEORIGIN. This ensures that SAMEORGIN is not duplicated in the response header sent back to the request client.
It's required because testing has found that when AEM included this header Apache would duplicate the SAMEORIGIN value even with the merge option. Apache is capable of proper merge when it sources the header from itself, but because the first header was set by AEM outside of the Apache instance is when it gets weird (and requires the extra expression).
It also appears that they do not use "always" with the merge+expr syntax. Perhaps to also work around an Apache weirdness.
PS... remember to change "SAMEORIGIN" for "DENY" in your case.

Custom modules for the Apache HTTP server: what's the behavior of mod_deflate?

I wrote a custom module for the apache http server as described in: http://httpd.apache.org/docs/2.4/developer/modguide.html
ap_rprintf(r, "Hello, world!");
I've been asked about the behavior of mod_deflate http://httpd.apache.org/docs/2.2/mod/mod_deflate.html .
Will response to the client produced by my module will be compressed by mod_deflate if the client accepts the compression with Accept-Encoding: gzip ?
If my response is already gzipped , can I prevent mod_deflate to work ?
Do you have any reference/link about this ?
Thanks.
By default, it would be compressed if it met the normal conditions. You can opt out a few ways (below in rough order of intrusiveness):
set the no-gzip per-request environment variable (r->subprocess_env)
remove the mod_deflate output filter (mod_proxy_wstunnel.c has an example of moving a filter)
unset the accept-encoding header before writing your response
set a Content-Encoding: gzip response header
The only reference is mod_deflate.c + output filter basics.

How to determine a webpage is compressed with Live HTTP Headers?

When I look at every page in live http headers, the page contains the below parts in header:
Accept Encoding: gzip, deflate
Content Encoding: Gzip
When I use websites to check whether it is compressed or not, it says it's not compressed. How can we be sure that a page is compressed?
For example I tested this site in Gzip tester and it says it's not compressed, but I see Content Encoding in live http headers.
Your headers are wrong, it should be:
Content-Encoding: gzip
so basically: dashes not spaces between words in the headername
It's your webserver that needs to add those and do the compression, see https://httpd.apache.org/docs/2.0/mod/mod_deflate.html

Prevent Apache from chunking gzipped content

When using mod_deflate in Apache2, Apache will chunk gzipped content, setting the Transfer-encoding: chunked header. While this results in a faster download time, I cannot display a progress bar.
If I handle the compression myself in PHP, I can gzip it completely first and set the Content-length header, so that I can display a progress bar to the user.
Is there any setting that would change Apache's default behavior, and have Apache set a Content-length header instead of chunking the response, so that I don't have to handle the compression myself?
You could maybe play with the sendBufferSize to get a value big enough to contain your response in one chunk.
Then chunked content is part of the HTTP/1.1 protocol, you could force an HTTP/1.0 response (so not chunked: “A server MUST NOT send transfer-codings to an HTTP/1.0 client.”) by setting the force-response-1.0 in your apache configuration. But PHP breaks this settings, it's a long-known-bug of PHP, there's a workaround.
We could try to modify the request on the client side with an header preventing the chunked content, but w3c says: "All HTTP/1.1 applications MUST be able to receive and decode the "chunked" transfer-coding", so I don't think there's any header like 'Accept' and such which can prevent the server from chunking content. You could however try to set your request in HTTP/1.0, it's not really an header of the request, it's the first line, should be possible with jQuery, certainly.
Last thing, HTTP/1.0 lacks one big thing, the 'host' headers is not mandatory, verify your requests in HTTP/1.0 are still using the 'host' header if you work with name based virtualhosts.
edit: by using the technique cited in the workaround you can see that you could tweak Apache env in the PHP code. This can be used to force the 1.0 mode only for your special gzipped content, and you should use it to prevent having you complete application in HTTP/1.0 (or use the request mode to set the HTTP/1.0 for you gzip requests).