Apache httpd 2.4 reverse proxy does not compress

With Apache httpd 2.2, you could configure a reverse proxy server and use mod_deflate to compress proxy content by observing the Accept-Encoding: gzip headers.

This configuration was sufficient to make it work:

  LoadModule deflate_module modules/mod_deflate.so LoadModule filter_module modules/mod_filter.so SetOutputFilter DEFLATE LoadModule proxy_module modules/mod_proxy.so LoadModule proxy_http_module modules/mod_proxy_http.so ProxyRequests Off ProxyPass /tomcat http://localhost:8880/ ProxyPassReverse /tomcat http://localhost:8880/ ProxyPass /other http://localhost:8001/ ProxyPassReverse /other http://localhost:8001/ 

Now, after upgrading to 2.4 (2.4.29 on Windows), the same configuration is accepted and really compresses the static content that is served from DocumentRoot. But the same content is returned uncompressed when retrieved through ProxyPass.

I know that I can configure Tomcat to compress, but there is this other server that just ignores Accept-Encoding headers.

How can I configure reverse proxy and compressed proxy content?

Edit:

Headers are returned here demonstrating that proxy content is not compressed by server 2.4:

 ----- Retrieving uncompressed from DocumentRoot --------------------------------- C:\Temp>curl -I http://localhost/test.txt HTTP/1.1 200 OK Date: Tue, 09 Jan 2018 17:11:59 GMT Server: Apache/2.4.29 (Win64) OpenSSL/1.1.0g Last-Modified: Fri, 05 Jan 2018 12:58:40 GMT ETag: "75441-5620701eb471c" Accept-Ranges: bytes Content-Length: 480321 Vary: Accept-Encoding Content-Type: text/plain ----- The same from Tomcat ------------------------------------------------------ C:\Temp>curl -I http://localhost:8880/rr/test.txt HTTP/1.1 200 OK Server: Apache-Coyote/1.1 Accept-Ranges: bytes ETag: W/"480321-1515157120042" Last-Modified: Fri, 05 Jan 2018 12:58:40 GMT Content-Type: text/plain Content-Length: 480321 Date: Tue, 09 Jan 2018 17:11:59 GMT ----- 2.4.29: Retrieving compressed from DocumentRoot --------------------------- C:\Temp>curl -I -H "Accept-Encoding: gzip" http://localhost/test.txt HTTP/1.1 200 OK Date: Tue, 09 Jan 2018 17:11:59 GMT Server: Apache/2.4.29 (Win64) OpenSSL/1.1.0g Last-Modified: Fri, 05 Jan 2018 12:58:40 GMT ETag: "75441-5620701eb471c-gzip" Accept-Ranges: bytes Vary: Accept-Encoding Content-Encoding: gzip Content-Length: 48265 Content-Type: text/plain ----- 2.4.29: Not getting any compression for proxied Tomcat content ------------ C:\Temp>curl -I -H "Accept-Encoding: gzip" http://localhost/tomcat/rr/test.txt HTTP/1.1 200 OK Date: Tue, 09 Jan 2018 17:11:59 GMT Server: Apache-Coyote/1.1 Accept-Ranges: bytes ETag: W/"480321-1515157120042" Last-Modified: Fri, 05 Jan 2018 12:58:40 GMT Content-Type: text/plain Content-Length: 480321 ----- 2.2.14: Retrieving compressed from DocumentRoot --------------------------- C:\Temp>curl -I -H "Accept-Encoding: gzip" http://localhost:81/test.txt HTTP/1.1 200 OK Date: Tue, 09 Jan 2018 17:11:59 GMT Server: Apache/2.2.14 (Win32) Last-Modified: Fri, 05 Jan 2018 12:58:40 GMT ETag: "90000000e7463-75441-5620701eb471c" Accept-Ranges: bytes Vary: Accept-Encoding Content-Encoding: gzip Content-Length: 48265 Content-Type: text/plain ----- 2.2.14: Proxied Tomcat content comes compressed --------------------------- C:\Temp>curl -I -H "Accept-Encoding: gzip" http://localhost:81/tomcat/rr/test.txt HTTP/1.1 200 OK Date: Tue, 09 Jan 2018 17:11:59 GMT Server: Apache-Coyote/1.1 Accept-Ranges: bytes ETag: W/"480321-1515157120042" Last-Modified: Fri, 05 Jan 2018 12:58:40 GMT Content-Type: text/plain Vary: Accept-Encoding Content-Encoding: gzip Content-Length: 20 

All of this was tested on a simple installation of 2.4.29 downloaded from ApacheHaus . The above configuration was added to httpd.conf, nothing else was changed. The same applies to installation 2.2.14 (downloaded in 2009 from Apache ), but this one was further changed to port 81.

+8
apache mod-proxy mod-deflate
source share
2 answers

I was able to reproduce the curl + apache/tomcat behavior that you described

This is how I reproduced it (OS X El Capitan):

Tomcat

 docker run -it --rm -p 8880:8080 tomcat:6.0 

Apache

 httpd -v Server version: Apache/2.4.18 (Unix) Server built: Feb 20 2016 20:03:19 httpd -l Compiled in modules: core.c mod_so.c http_core.c prefork.c 

Apache configuration (fully):

 Listen 80 LoadModule authz_user_module libexec/apache2/mod_authz_user.so LoadModule authz_core_module libexec/apache2/mod_authz_core.so LoadModule access_compat_module libexec/apache2/mod_access_compat.so LoadModule filter_module libexec/apache2/mod_filter.so LoadModule deflate_module libexec/apache2/mod_deflate.so LoadModule mime_module libexec/apache2/mod_mime.so LoadModule log_config_module libexec/apache2/mod_log_config.so LoadModule headers_module libexec/apache2/mod_headers.so LoadModule version_module libexec/apache2/mod_version.so LoadModule proxy_module libexec/apache2/mod_proxy.so LoadModule proxy_http_module libexec/apache2/mod_proxy_http.so LoadModule unixd_module libexec/apache2/mod_unixd.so <IfModule unixd_module> User _www Group _www </IfModule> <IfModule mime_module> TypesConfig /private/etc/apache2/mime.types </IfModule> LogLevel debug <IfModule log_config_module> LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined LogFormat "%h %l %u %t \"%r\" %>s %b" common <IfModule logio_module> # You need to enable mod_logio.c to use %I and %O LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %I %O" combinedio </IfModule> CustomLog "/private/var/log/apache2/access_log" common </IfModule> ErrorLog "/private/var/log/apache2/error_log" TraceEnable off SetOutputFilter DEFLATE ProxyRequests Off ProxyPass /tomcat http://localhost:8880/ ProxyPassReverse /tomcat http://localhost:8880/ ProxyPass /other http://localhost:8001/ ProxyPassReverse /other http://localhost:8001/ DocumentRoot /Library/WebServer/Documents 

Check

 curl -I -H 'Accept-Encoding: gzip' 'http://localhost/tomcat' HTTP/1.1 200 OK Date: Sat, 13 Jan 2018 13:35:14 GMT Server: Apache-Coyote/1.1 Accept-Ranges: bytes ETag: W/"7454-1491118183000" Last-Modified: Sun, 02 Apr 2017 07:29:43 GMT Content-Type: text/html Content-Length: 7454 curl -I -H 'Accept-Encoding: gzip' 'http://localhost/index.html.en' HTTP/1.1 200 OK Date: Sat, 13 Jan 2018 13:35:25 GMT Server: Apache/2.4.18 (Unix) Last-Modified: Tue, 09 Jan 2018 04:51:20 GMT ETag: "45-56250aa712200-gzip" Accept-Ranges: bytes Vary: Accept-Encoding Content-Encoding: gzip Content-Length: 65 Content-Type: text/html 

As you can see, the result very closely matches your example

And here's the fun part

If I use a regular GET request instead of HEAD (via a browser or curl without -I) the answer is tomcats DOES GETS GZIPPED

 curl -D - -H 'Accept-Encoding: gzip' 'http://localhost/tomcat' 2>/dev/null | strings HTTP/1.1 200 OK Date: Sat, 13 Jan 2018 13:37:19 GMT Server: Apache-Coyote/1.1 Accept-Ranges: bytes ETag: W/"7454-1491118183000-gzip" Last-Modified: Sun, 02 Apr 2017 07:29:43 GMT Content-Type: text/html Vary: Accept-Encoding Content-Encoding: gzip Content-Length: 2526 (some junk) 

Not sure why this is happening, it looks like Apache + mod_proxy / defate misbehavior on HEAD requests. If you say that everything is okay in Apache 2.2, I would suggest that this might be due to this setting

 mod_deflate will now skip compression if it knows that the size overhead added by the compression is larger than the data to be compressed. 

So, Id checks to see if the problem persists for GET requests in your case. If yes, provide even more detailed information about your setup so that your environment can be 100% replicated - a valid Docker file for apache and tomcat to isolate a possible environment mismatch would be nice

+1
source

You are sending an HTTP HEAD request with the -I flag in curl. As the answer from ffeast suggests, this could be causing the problem.

If this is true, then this is either a mistake or a deliberate disregard for HTTP RFC: https://tools.ietf.org/html/rfc2616#section-9.4

9.4 HEAD

The HEAD method is identical to GET, except that the server SHOULD NOT return the message body in response. The meta information in the HTTP headers in response to the HEAD request MUST be the same as the information sent in response to the GET request.

If so, you should report it as a possible error through this process: https://httpd.apache.org/bug_report.html

+1
source

All Articles