Apache - serving pre-compressed gzip file doesn't work - javascript

I'm having trouble using the rewrite rules for Apache (2.4) to serve compressed files.
My javascript bundling process generate .gz files for every .js it creates. I've activated the rewrite module on apache a2enmod rewrite and set the .htacess file like this:
AddEncoding gzip .gz
RewriteEngine on
RewriteCond %{HTTP:Accept-encoding} gzip
RewriteCond %{REQUEST_FILENAME}\.gz -s
RewriteRule "^(.*)\.js" "$1\.js\.gz" [QSA]
# Serve correct content types, and prevent mod_deflate double gzip.
RewriteRule "\.js\.gz$" "-" [T=text/javascript,E=no-gzip:1]
<FilesMatch ".+\.(js\.gz)$">
Header append Content-Encoding gzip
Header append worked yes
</FilesMatch>
The problems I'm running are:
The first condition RewriteCond %{HTTP:Accept-encoding} gzip never evaluates to true. On Chrome Developer tools the client is sending this header Accept-Encoding:gzip, deflate, br (I've tried adding gzip, deflate, br to the condition but it doesn't work);
Even if I take this above condition out I can't see the header Content-Encoding in Chrome dev-tools;
I don't see Content-length in response headers. But it responds with a Transfer-Encoding:chunked which I find weird;
These are the modules that are enabled on my apache (I think they are enabled by default in my ubuntu dist because I didn't active any of those)
access_compat.load authz_user.load filter.load rewrite.load
alias.conf autoindex.conf headers.load setenvif.conf
alias.load autoindex.load mime.conf setenvif.load
auth_basic.load deflate.conf mime.load status.conf
authn_core.load deflate.load mpm_event.conf status.load
authn_file.load dir.conf mpm_event.load
authz_core.load dir.load negotiation.conf
authz_host.load env.load negotiation.load

The code you have there looks correct and seems to work fine on my computer, which suggests the problem is elsewhere. Some possibilities I can think of:
Perhaps a cache server/reverse proxy is messing with things (that would be my first guess, unless you're testing on localhost or set up everything yourself or otherwise know there isn't such a server)
Or perhaps mod_deflate is interfering anyways (I don't seem to have it installed on my computer so I can't test it); if you have access to the main server configuration maybe try commenting out the LoadModule line for it?
If any subdirectory has a .htaccess file that also uses rewrite rules, then rewrite rules in the parent directory won't run. (If this is the issue, RewriteOptions Inherit should work with these specific rules. However, this wouldn't explain the chunked encoding.)
Force refresh or clear cache in your browser?

Related

ERR_CONTENT_DECODING_FAILED for one file after Joomla update

After updating Joomla to 3.8.1 today most of the admin tabbing and navigation functions stopped working in Chrome, FireFox, Win Safari, and IE 11. media/jui/js/bootstrap.min.js was failing to load with ERR_CONTENT_DECODING_FAILED. It still works in MS Edge.
This is occurring on machines in multiple locations and over multiple ISPs.
Actions taken (none of which have resolved):
Deleted file from server and replaced with backed up copy from last week and re-issued chmod 0644
Verified that public $gzip = '0'; in configuration.php
Tested in MS Edge where the error did not occur
Used MS Edge to go to Joomla Global Configuration > Server Settings and set Gzip Page Compression to No. Had been Yes.
Found that in browsers where it was failing if JS file is accessed without the versioning query string the browser can load file without error.
Found in Safari, IE 11, and iPhone Chrome the JS file displays and appears to be gzipped or otherwise encoded. Screenshot:
Cleared browser cache in Chrome
Went to chrome://net-internals and clicked Flush Socket Pools and Close Idle Sockets
Cache settings checked and it has been set to off the whole time:
System - Page Cache module also disabled
In this case the client had failed to mention they had added Sucuri Firewall service and that was where they corrupted cached file was being delivered from. Cleared cache at Sucuri and file no longer throws ERR_CONTENT_DECODING_FAILED
I had the same situation. Gzip on 0 in configuration.php did not work. So I found out that get_magic_quotes_gpc was deprecated in
libraries\src\Application\AdministratorApplication.php.
In my case I solved it by editing the default htaccess that my Joomla 4.2.X came with.
You have to leave these lines activated.
Header always set Cross-Origin-Resource-Policy "same-origin".
Header always set Cross-Origin-Embedder-Policy "require-corp".
And you have to remove this code:
<IfModule mod_headers.c>
# Serve gzip compressed CSS files if they exist
# and the client accepts gzip.
RewriteCond "%{HTTP:Accept-encoding}" "gzip"
RewriteCond "%{REQUEST_FILENAME}\.gz" -s
RewriteRule "^(.*)\.css" "$1\.css\.gz" [QSA]
# Serve gzip compressed JS files if they exist
# and the client accepts gzip.
RewriteCond "%{HTTP:Accept-encoding}" "gzip"
RewriteCond "%{REQUEST_FILENAME}\.gz" -s
RewriteRule "^(.*)\.js" "$1\.js\.gz" [QSA]
# Serve correct content types, and prevent mod_deflate double gzip.
RewriteRule "\.css\.gz$" "-" [T=text/css,E=no-gzip:1]
RewriteRule "\.js\.gz$" "-" [T=text/javascript,E=no-gzip:1]
<FilesMatch "(\.js\.gz|\.css\.gz)$">
# Serve correct encoding type.
Header append Content-Encoding gzip
# Force proxies to cache gzipped &
# non-gzipped css/js files separately.
Header append Vary Accept-Encoding
</FilesMatch>

PHP Web Server - Change localhost to custom domain name?

I am currently creating a Laravel project and need to store cookies in a http://localhost:8000 address, of course, I have found out that to set a cookie through JavaScript, the domain must have two or more periods (.) in.
Obviously, with the address set to localhost:8000, cookies fail to be stored. I need to be able to fake my host to point something like http://dev.project.laravel as opposed to localhost:8000
Apologies if I'm not making sense, but hopefully you catch my drift. Thanks in advance for any help given.
Try the following:
Assuming you have Windows OS and have installed XAMPP (or similar) stack:
Add the following line to httpd.conf file under # Supplemental configuration which is in the configuration folder of apache... (I have XAMP installed and for me, this path is: C:\xampp\apache\conf)
Include conf/extra/httpd-vhosts.conf
it should be around line 484
if you already have that line, but its commented out, then un-commment it.
Add the following to your httpd-vhosts.conf file (which, in my case, is located at C:\xampp\apache\conf\extra)--
In the first line below, change 80 to whatever port your localhost is running on... if you do not use port to access localhost, then leave it as 80)
<VirtualHost *:80>
DocumentRoot "C:/xampp/htdocs/"
ServerName desired.name.of.your.site
ServerAlias desired.name.of.your.site
</VirtualHost>
And lastly, and most importantly, add the following in your hosts file (for me, this is located at C:\Windows\System32\drivers\etc) and then restart apache
127.0.0.1 desired.name.of.your.site
If you have a LAMP stack, the above should still apply... just the folder paths would need to change.
Hope this helps!
Best,
-Rush

reverseProxy: how to change content in embedded JavaScript file

I use Apache HTTP 2.4 as a reverse proxy. My configuration works fine except one thing:
I would like to change a string content (url) in an embedded JavaScript file
This is my actual virtual host configuration:
<VirtualHost web.mydomain.com:80>
ServerName web.mydomain.com
ServerAlias web.mydomain.com
DocumentRoot "..."
...
RewriteEngine On
RewriteCond %{REQUEST_METHOD} OPTIONS
RewriteRule ^(.*)$ $1 [R=200,L]
#Options -Indexes
#ProxyRequests On
#ProxyPreserveHost Off
# Web App
ProxyPass /hello http://middleware.mydomain.com:8082/hello-world-0.0.7
ProxyPassReverse /hello http://middleware.mydomain.com:8082/hello-world-0.0.7
AddOutputFilterByType SUBSTITUTE text/html
Substitute "s|hello-world-0.0.7|hello|ni"
</VirtualHost>
Could you please help me?
Usually, you should be able to configure the external URL in your application server, thereby eliminating the need to do the substitution in your Apache server. Such a configuration would be more efficient.
Did you validate in your browser that the returned Content-Type matches your filter? You indicate a Javascript file but filter for text/html. (e.g. Chrome: open Developer tools > navigate to the page > open Network tab > click on the resource that needs substitution > Look for the Content-Type header in the response headers). The Content-Type header should match your filter.
If it still does not work, it is likely that the application server returns gzipped content (check for Content-Encoding: gzip in the response headers). In that case, it makes sense that substitution won't work.
To work around that, add the following directive in your Apache configuration:
RequestHeader unset Accept-Encoding
Please note that this results in a performance penalty since more data needs to be sent across the network. I won't recommend this solution in a production environment since it applies to all requests for the current Virtual Host. If you only need to use substitution for a single file, I recommend wrapping the AddOutputFilterByType, Substitute and RequestHeader directives in a block, so that Apache only does the additional work for that file:
<Location "/hello/path/to/your/javascript/file.js">
RequestHeader unset Accept-Encoding
AddOutputFilterByType SUBSTITUTE text/html
Substitute "s|hello-world-0.0.7|hello|ni"
</Location>

Why is this simple CORS GET failing?

I have a server running apache. The .htaccess contains the following:
<IfModule mod_headers.c>
<FilesMatch "\.(eot|ttf|otf|woff|css)$">
Header add Access-Control-Allow-Origin "*"
</FilesMatch>
</IfModule>
Why is it that
$.get('https://www.sarahlawrence.edu/_assets/v6/fonts/otama-text-regular/otamatextregular.eot')`
works (try it in the console from any domain), whereas
$.get('https://www.sarahlawrence.edu/_assets/v6/lib/icons.data.svg.css')
fails with this error:
XMLHttpRequest cannot load https://www.sarahlawrence.edu/_assets/v6/lib/icons.data.svg.css. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'https://whatever.com' is therefore not allowed access.
And how can I get it working?
The missing Header can be confirmed using curl:
curl -v https://www.sarahlawrence.edu/_assets/v6/fonts/otama-text-regular/otamatextregular.eot > delme.txt
curl -v https://www.sarahlawrence.edu/_assets/v6/lib/icons.data.svg.css > delme.txt
The regex should be happy with the filename so I expect that the problem is either because there is a conflicting configuration somewhere in the apache configuration.
Another diagnostic check would be to copy the failing file into the fonts directory and check whether the header is present - this will confirm that the regex or the filename isn't the problem but indicates that it is directory configuration related.
You have stated that there are no other .htaccess files in the document root or children ( this could cause the problem ) and the file is being served just without the headers.
My feeling at this stage is that this may be related to your mod_pagespeed which is disabled for lib/icons. It could even come down to the ordering of the modules being loaded.
Trivially I would first restart your apache just in case. Any caching or proxy infrastructure in between should be disabled. Next I would disable mod_pagespeed and see if the issue remains.
I would also check to see whether there is a block of configuration in either your httpd.conf or the virtual hosts configuration that is similar as it is possible that this is catching some directories and not others and that your .htaccess is not doing what is expected. As a further check I would try removing or temporarily renaming .htaccess ( to htaccess-removed or something similar ) to confirm that the URL request headers are no longer being included using the curl or other approaches to validating the CORS headers.
Probably not related however another thing I'd check is the permissions and ownership of the files and directories - thought worth mentioning just in case.
Also worth checking the error logs on restarting the apache and on making the requests as this may provide further insight.
What is the full path to your .htaccess file?
Ether your .htaccess file is not set up in a way to have it apply it's rules to files in the https://www.sarahlawrence.edu/_assets/v6/lib/ location, or there is another rule somewhere else superseding the rule you have shown above.

Apache .htaccess for deny all files in a folder not ending with .min.js?

I'm already using (in my /web/css folder) the following .htaccess file for obscuring source .less files (LESS files):
<Files ~ "\.less$">
Order allow,deny
Deny from all
</Files>
I can't do something very similar for JavaScript files in /web/js: deny if the file doesn't end in .min.js. This maybe due to my little understanding of regular expression, so please go easy with me!
<Files ~ "[^min]\.js$">
Order allow,deny
Deny from all
</Files>
A file not ending with min.js should be denied, but - actually - seems to allow all.
Try FilesMatch like this:
<FilesMatch "(?!^.*min\.js$)^.+?\.js$">
Order allow,deny
Deny from all
</FilesMatch>
Alternative solution using mod_rewrite:
RewriteEngine On
RewriteRule !^min\.js$ - [F]

Categories