I'm having some trouble prevent mod_deflate from jumping in on this scenario:
user running CodeIgniter (or any other framework that re-directs to index.php)
mod_deflate is active
zip file is served by a CodeIgniter controller (headers + readfile)
The thing is that Apache always detects the content as being php and therefor something like the lines bellow wont work as the server assumes the ZIP file as being a PHP one.
<FilesMatch "\.(xml|txt|html|php)$">
SetOutputFilter DEFLATE
</FilesMatch>
Any ideas on how I can have Apache distinguish from an HTML file or a ZIP file both generated by the same index.php framework file.
Edit:
apache log
[Mon Jun 20 02:14:19 2011] [debug]
mod_deflate.c(602): [client 192.168.0.5]
Zlib: Compressed 50870209 to 50878224 : URL /index.php,
referer: http://demo.dev/
Edit:
CI controller that serves the zip
header('Content-Type: application/zip');
header('Content-Transfer-Encoding: binary');
header("Content-Length: " . filesize($file_location));
header('Content-Disposition: attachment; filename="' . $file_title . '"');
readfile($file_location);
Even tough all answers should have been perfectly valid in a reasonable scenario (and were actually tested prior to making the question) the reason to why I've been unable to instruct Apache to deflate a file by MIME-Type remains unknown.
I was able to have it work as desired by forcing the following instructions into the script
apache_setenv('no-gzip', 1);
ini_set('zlib.output_compression', 0);
I do understand that this is a hot patch and is not addressing the problem's root but so far that will have to suffice. As there are others who may hit the same flag, the above code stays here for reference in what is a dirty fix.
You can either:
use the deprecated AddOutputFilterByType and specify only the content types you do want to filter; or
use the more powerful mod_filter. In FilterProvider you can provide a rule that excludes the filter when the zip content type (application/zip) is found in the response headers.
You can make use of mod_rewrite to change the mime-type of the request on the Apache level:
# Serve .zip request as zip-files
RewriteRule \.zip$ - [T=application/zip,E=no-gzip:1]
Place it above the rules of the framework, however this needs to make DEFLATE as well depended on mime-type and not file-extension as you do with <FilesMatch>.
Probably it works well together with
AddOutputFilterByType DEFLATE text/html
instead of the <FilesMatch> Directive.
Edit: Added the L flag which should be used in .htaccess context and additionally turned DEFLATE off via the no-gzip environment variable.
Try this (since your urls appear to end in .zip it might work for you):
<FilesMatch "\.(xml|txt|html|php)$">
SetEnvIf Request_URI "\.zip$" no-gzip
SetOutputFilter DEFLATE
</FilesMatch>
Instead of using
<FilesMatch "\.(xml|txt|html|php)$">
SetOutputFilter DEFLATE
</FilesMatch>
Use this configuration for setting compression rules.
AddOutputFilterByType DEFLATE text/html text/plain text/css text/xml application/x-javascript application/javascript
This way, your output will be compressed only if content-type matches with above directives.
CI controller that serves the zip is already sending correct content-type header, so this will not get compressed.
header('Content-Type: application/zip');
Related
According to checkgzipcompression all my .js and .css are correctly GZIP compressed.
Except for my php webpages:
www.website.nl/webpages.php seem not gzipped, resulting in a 75% increase in "wasted" data transfer. My .htaccess file ends with the following below. What needs to be changed here to get GZIP compression for my php webpages to work properly? (Excluding the .php files from the /includes/ folder ofcourse since those are not "transferred to the browser" and are processed internally so they need no compression). Thanks!
# compress speficic filetypes
<IfModule mod_deflate.c>
<FilesMatch "\.(js|css|txt|php)$">
SetOutputFilter DEFLATE
</FilesMatch>
</IfModule>
Pages served in the browser with .php extension are considered html. PHP uses Content-Type "text/html" as default.
I would say, find out what's your web server, and then find out the correct compression method for it.
Good luck!
Sorry to bother you with a question that seems very well documented, but none of the things I tried was completely satisfying.
My Company switched from a hosting package to a manages Server just last week and I'm still in the process of optimising it.
Now, Googles PageSpeed Insights tell me, it is not compressed, as does GTMetrix. GidNetwork tells me compression works fine.
I have already added
<IfModule mod_deflate.c>
<FilesMatch "\.(html|php|txt|xml|js|css)$">
SetOutputFilter DEFLATE
</FilesMatch>
</IfModule>
to my .htaccess, (as recommended here) which works correctly, other settings I've changed are fine, as well as
zlib.output_compression = On
to my php.ini.
The entire .htaccess and php.ini can be seen at jsFiddle.
Headers sent and received in both Firefox and Chrome claim that compression is happening.
I also created a httpd.conf in my home directory, because none existed on my server yet. Should I move the file somewhere else?
What I really want to know:
Soo... what am I doing wrong? Is it compressed? Is it not? How can I make google 'see' the compression?
Thank you very much for your help.
This should be the function you need, it should automatically generates the headers you need:
http://www.php.net/manual/en/function.gzdecode.php
anyway check your php version because it works only with php 5.4.0 or later ones.
Although my browser accepts deflate/gzip encoding (Accept-Encoding: gzip, deflate), your server does not answer using compressed data:
HTTP/1.1 200 OK
Date: Tue, 11 Mar 2014 09:41:45 GMT
Server: Apache
Connection: Keep-Alive
Keep-Alive: timeout=2, max=200
Etag: "96-100e9-4f4517d791912"
Expires: Fri, 11 Apr 2014 13:28:25 GMT
Cache-Control: max-age=2692000, public
Vary: User-Agent
If it was compressed, the server would send also
Content-Encoding: deflate
Use FireBug or the dev console to see the headers. It must be your httpd.conf.
You cannot simply create this file in your home directory and Apache will load it.
Have a look in /etc/apache* and /etc/httpd/* for config files.
You have already enabled gzip compression but you haven't set it to compress some file types such as javascript and css. That is why Googles PageSpeed was tried to suggest to enable compression. To enble compression for those two types, use
AddOutputFilterByType DEFLATE text/css
AddOutputFilterByType DEFLATE application/javascript
What worked for me in the end to compress the js/css files that were left uncompressed for reasons I don't quite get yet is described here.
In this method, javascript and css-files are forcibly gzipped by a php-script. It also sets new "Expire"-Headers, so if you want caching for more than 5 Minutes, change the number. Adding different files is trickier, but possible, I think.
I am using a controller in CodeIgniter 2 to generate a resized image based on its URL however the pictures are getting randomly cut off on one of our servers (only the top two thirds or so get shown). I believe the problem is related to GZIP being used when the picture is generated but it is difficult to reproduce consistently and disappears entirely when I turn compression off.
Interestingly, the GZIP compression is only added to the outputted JPEG when the text/html is being compressed.
This is my apache configuration:
<IfModule mod_deflate.c>
<FilesMatch "(?<!\.jpg)$">
AddOutputFilterByType DEFLATE text/html
</FilesMatch>
</IfModule>
<FilesMatch "\.jpg$" >
SetEnv no-gzip dont-vary
RemoveOutputFilter php
</FilesMatch>
My htaccess file contains this
SetEnvIfNoCase Request_URI ".jpg$" no-gzip dont-vary
<FilesMatch "\.(gif|jpe?g|png)$">
SetEnv no-gzip dont-vary
</FilesMatch>
PHP code looks like this
//code to generate the image and save it to the hard drive goes here
//output the file
$binarydata = file_get_contents($directory.$file);
$offset = 5184000;
header("Cache-Control: must-revalidate");
header('Content-Type: image/jpeg');
header('Expires: '. gmdate('D, d M Y H:i:s', $dbrecord->updated_at->format("U") + $offset) .' GMT');
header('Last-Modified: '.gmdate('D, d M Y H:i:s', $dbrecord->updated_at->format("U")) .' GMT');
header('Accept-Ranges: bytes');
header("Content-Disposition: inline; filename=".$file);
header('Content-Length: '.strlen($binarydata));
print($binarydata);
die();
The URL of the photo would be something like http://example.com/photo/100x100-abc.jpg and as you can see, there are four different ways of trying to avoid the compression being set however it is still set.
I have tried all the methods above separately and combined but to no avail. I am at my wits end, can anyone help?
UPDATE:
I removed the content length header and apache did not set it on its own but we have just discovered something interesting, the problem only occurs in Chrome and Safari and not Firefox so I wonder if this is also webkit related?
I have a joomla site on a shared server consequently I dont have access to apache to enable gzip or defalte so im wondering what i can do maybee with php to enable compression to speed up my site?
You can try to turn on output compression by setting the zlib.ouput_compression setting:
http://php.net/manual/en/zlib.configuration.php#ini.zlib.output-compression
or you can specifically do output buffering and run it through the GZIP handler:
ob_start("ob_gzhandler");
the first option is the preferred method, if you do use the second method check that it doesn't break any ouput buffering Joomla does - I'm no Joomla expert but I would expect a CMS to provide an option to compress content before delivery.
If gzip enabled on your host you need to add this lines to .htaccess file without change your code
AddOutputFilterByType DEFLATE text/html text/plain text/css application/json
AddOutputFilterByType DEFLATE text/javascript application/javascript application/x-javascript
AddOutputFilterByType DEFLATE text/xml application/xml text/x-component
this lines enables apache deflate in html, css json and xml content
It would be nice if you add the condition to check if it accepts encoding like this.
<?php
if (substr_count($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip'))
ob_start("ob_gzhandler");
else
ob_start();
?>
Note:
you will have to do this for every php file, if your server doesn't support .htaccess configuration.
I want to send my RSS/Atom feeds with the correct Content-type header, can I do this without access to PHP or any other server-side language? The goal is for the browser to treat the file as a feed and not just a plain XML file.
You can tell the server to send that specific file with a specific media type.
Apache has the AddType and ForceType directive to do that:
# send all .atom files with application/atom+xml
AddType application/atom+xml .atom
# send only foo.bar as application/atom+xml
<FilesMatch ^foo\.bar$>
ForceType application/atom+xml
</FilesMatch>
You can use <Directory>, <DirectoryMatch>, <Files>, <FilesMatch>, <Location> and <LocationMatch> sections to restrict the directives only to specific directories, files or URL paths. But be aware of the context they are allowed in. Only <Files> and <FilesMatch> can be used in a .htaccess file.
If your RSS/ATOM feed has a specific extension, or is served from a specific dorectory, I suppose you could use Apache's AddType directive, so Apache would serve your RSS feeds with the right content-type :
The AddType directive maps the given
filename extensions onto the specified
content type. MIME-type is the MIME
type to use for filenames containing
extension.
Not tested, but I suppose something like this, either in your Apache's main configuration file, or in a .htaccess file, might do, for RSS feeds :
AddType application/rss+xml .rss
And, for ATOM, something like this, probably :
AddType application/atom+xml .atom