I would like to gzip the html sources of my webpages, what's the best way to do it on a lighttpd/php5 server.
I have tried to do it by editing my php.ini file with:
zlib.output_compression = On
zlib.output_handler = On
but it seems to be a transparent compression only.
You'll need to enable mod_compress on lighthttpd in addition to the changes you made in your php file.
http://www.cyberciti.biz/tips/lighttpd-mod_compress-gzip-compression-tutorial.html
Edit:
I believe you're looking for an html minimizer then. If you check out the headers that google is sending back they look like this:
(Status-Line) HTTP/1.1 200 OK
Date Thu, 22 Oct 2009 18:28:47 GMT
Expires -1
Cache-Control private, max-age=0
Content-Type text/html; charset=UTF-8
Content-Encoding gzip
Server gws
Content-Length 3519
X-XSS-Protection 0
The "Content-Encoding gzip" is what you're looking for if you want to check for to see if your webserver is properly compressing your files.
Related
We are trying to put all of our file assets on s3 and cloudfront to reduce load on our server. For almost all file types things are working fine and Cloudfront is caching files. For fonts files there always seems to be a miss. What am I doing wrong?
When we first put the fonts online and called them we got an error which pointed to the CORS protocol issue. This is where we learned about CORS.
We followed this solution, Amazon S3 CORS (Cross-Origin Resource Sharing) and Firefox cross-domain font loading
Here is my CORS setting. We have to have AllowedOrigion as a wildcard because we are supporting many websites.
<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<CORSRule>
<AllowedOrigin>*</AllowedOrigin>
<AllowedMethod>GET</AllowedMethod>
<MaxAgeSeconds>3000</MaxAgeSeconds>
<AllowedHeader>Content-*</AllowedHeader>
<AllowedHeader>Authorization</AllowedHeader>
</CORSRule>
</CORSConfiguration>
I setup behavior rules in the cloudfront distribution for each font type type:
/*.ttf
with Whitelist Headers to origin
I checked with curl and there is always a miss and access-control-allow-origin is always *
curl -i -H "Origin: https://www.example.com" https://path/to-file/font-awesome/fonts/fontawesome-webfont.woff
HTTP/2 200
content-type: binary/octet-stream
content-length: 98024
date: Tue, 08 Jan 2019 09:07:03 GMT
access-control-allow-origin: *
access-control-allow-methods: GET
access-control-max-age: 3000
last-modified: Mon, 07 Jan 2019 08:44:46 GMT
etag: "fee66e712a8a08eef5805a46892932ad"
accept-ranges: bytes
server: AmazonS3
vary: Origin
x-cache: Miss from cloudfront
via: 1.1 d76fac2b5a2f460a1cbffb76189f59ef.cloudfront.net (CloudFront)
x-amz-cf-id: 1azzRgw3h33KXW90xyPMXCTUAfZdXjCb2osrSkxxdU5lCoq6VNC7fw==
I should also mentioned that when I go directly to the file it downloads instead of opens in browser (which might be the correct behavior, not sure).
The files are loading today, which is good but in the end I would like for Cloudfront to server the files when it has it in the cache instead of always missing.
Your Curl dump indicate there is no "cache-control" headers in the response. You should have this header setted (https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/Expiration.html). Best practice is to havec cache-control to "public, max-age=xxx, s-maxage=yyy" (xxx = time cached on user browser, yyy time cached in CDN).
Do you have this header for other ressources (like a css or js) and not for woff ?
Check this : how to add cache control in AWS S3?
I am trying to fix my headers. I see two errors when checking the network requests as I visit my page:
1) X-FRAME-OPTIONS: SAMEORIGIN is shown twice:
Cache-Control:no-cache
Connection:Keep-Alive
Content-Encoding:gzip
Content-Type:text/html; charset=UTF-8
Date:Wed, 04 Oct 2017 12:58:30 GMT
Keep-Alive:timeout=3, max=1000
Server:Apache
Set-Cookie:laravel_session=eifQ%3D%3D; expires=Wed, 04-Oct-2017 14:58:30 GMT; Max-Age=7200; path=/; secure; httponly
Set-Cookie:XSRF-TOKEN=n0%3D; expires=Wed, 04-Oct-2017 14:58:30 GMT; Max-Age=7200; path=/
Transfer-Encoding:chunked
X-CDN:Incapsula
X-Frame-Options:SAMEORIGIN * <-------------- HERE
X-Frame-Options:SAMEORIGIN * <-------------- HERE
X-Iinfo:7-6626704-6651371 NNNN CT(0 0 0) RT(1507121414380 495318) q(0 1 1 -1) r(2 2) U16
X-XSS-Protection:%E2%80%9C1;mode=block%E2%80%9D <-------- Strange Encoding here...
2) I can see the following error on the console for X-XSS-PROTECTION:
Error parsing header X-XSS-Protection: â1;mode=blockâ: expected 0 or 1 at character position 0. The default protections will be applied.
I am using Laravel 5.0. The FrameGuard.php middleware is not active by default since Laravel 4.2, but you have the option to enable it if needed. When it's disabled, I see the above errors and I really can't understand why, so my first though was to overwrite those headers by actually using that middleware.
When I add the Illuminate\Http\Middleware\FrameGuard.php middleware, which contains the below code, nothing seems to change:
public function handle($request, Closure $next)
{
$response = $next($request);
$response->headers->set('X-XSS-Protection', '1; mode=block');
$response->headers->set('Content-Type','text/html; charset=UTF-8');
$response->headers->set('X-Frame-Options', 'SAMEORIGIN', true);
return $response;
}
I also use Socialite which provides Facebook authentication. Is there a chance that it modifies any headers?
The webserver may be adding headers to responses in addition to those sent by PHP. We can check which headers the webserver adds by creating an empty HTML file in the public directory, such as public/dummy.html
Then, visit that page in the browser, http://example.com/dummy.html, and check which headers the response includes. Alternatively, we can use the curl command to show the response headers:
$ curl -I 'http://example.com/dummy.html'
HTTP/2 200
date: Mon, 16 Oct 2017 20:34:24 GMT
...
x-xss-protection: 1; mode=block
x-frame-options: SAMEORIGIN
If we see the x-xss-protection or x-frame-options headers in this output, it means that the webserver is sending these headers. There may be a corrupted value for x-xss-protection in the webserver configuration (it looks like someone pasted stylized double quotation marks (“…”) instead of straight quotes ("…") which the server interprets as part of the header's value).
For nginx, look for add_header ... directives in the configuration files. If using Apache httpd, check for Header set ... directives in the server config or the .htaccess file.
It also appears as if the site uses the Incapsula CDN, which may be injecting the headers as well, but I couldn't find any information in the Incapsula documentation that suggests this is the case.
Laravel Socialite does not add these headers to responses.
I'm using Apache 2.2 and PHP 7.0.1. I force chunked encoding with flush() like in this example:
<?php
header('HTTP/1.1 200 OK');
echo "hello";
flush();
echo "world";
die;
And I get unwanted characters at the beginning and end of the response:
HTTP/1.1 200 OK
Date: Fri, 09 Sep 2016 15:58:20 GMT
Server: Apache/2.2.15 (CentOS)
X-Powered-By: PHP/7.0.9
Connection: close
Transfer-Encoding: chunked
Content-Type: text/html; charset=UTF-8
a
helloworld
0
The first one is the chunk size in hex (10 = A). I'm using Klein as PHP router and I have found that the problem comes up only when the HTTP status header is rewritten. I guess there is a problem with my Apache config, but I wasn't able to figure it out.
Edited: My problem had nothing to do with Apache but Nginx and chunked_transfer_encoding directive. Check the answer below.
This is how Transfer-Encoding: chunked works. The extra characters you're seeing are part of the encoding, rather than the body.
A client that understands the encoding will not include them in the result; a client that doesn't doesn't support HTTP/1.1, and should be considered bugged.
As #Joe pointed out before, that is the normal behavior when Chunked transfer enconding is enabled. My tests where not accurate because I was requesting Apache directly on the server. Actually, when I was experiencing the problem in Chrome I was querying a Nginx service as a proxy for Apache.
By running tcpdump I realized that Nginx was rechunking responses, but only when rewritting HTTP status header (header('HTTP/1.1 200 OK')) in PHP. The solution to sending Transfer-Encoding: chunked twice is to set chunked_transfer_encoding off in the location context of my Nginx .php handler.
On the embedded device I'm working on, the web-pages' Javascript sends requests to local PHP files and then uses the responses to update DOM elements dynamically. Everything works fine: AJAX is cool.
Annoyingly, though, all the responses are gzip encoded even though I'd rather they weren't (the target device's processor doesn't have much processing bandwidth). The problem is that I can't see how to disable gzip compressing the responses.
Note that:
(1) On the server side, I'm testing using PHP 5.3.10 and Apache/2.2.22 under Ubuntu
(2) On the client side, I'm using Firefox 19.0 and Firebug
(3) The PHP files are just echoing their output, i.e. I don't think they're invoking ob_gzhandler()
(4) The JavaScript is using GET rather than POST (it's what was specified for the project)
According to Firebug, the request headers look lke this:
Accept text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Encoding gzip, deflate
Accept-Language en-gb,en;q=0.5
Cookie PHPSESSID=<whatever>
Host 10.0.2.15
Referer http://10.0.2.15/pages/status.php
User-Agent Mozilla/5.0 (X11; Ubuntu; Linux i686; rv:19.0) Gecko/20100101 Firefox/19.0
And the response headers typically look like this:-
Cache-Control no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Connection Keep-Alive
Content-Encoding gzip
Content-Length 59
Content-Type text/html
Date Wed, 13 Mar 2013 12:08:02 GMT
Expires Thu, 19 Nov 1981 08:52:00 GMT
Keep-Alive timeout=5, max=43
Pragma no-cache
Server Apache/2.2.22 (Ubuntu)
Vary Accept-Encoding
X-Powered-By PHP/5.3.10-1ubuntu3.5
Approaches I've already tried (but without any success):-
(a) Preventing php files' output from being gzipped via the local .htaccess file
<IfModule mod_env.c>
SetEnvIfNoCase Request_URI "\.php$" no-gzip dont-vary
</IfModule>
This was as per http://support.modwest.com/content/1/117/en/how-do-i-turn-off-webservers_-gzip-compression.html but didn't seem to have any effect, even when I restarted apache2 between calls.
(b) Preventing php files' output from being gzipped via the /etc/apache2/httpd.conf file
<Directory /myfolder>
RemoveOutputFilter php
</Directory>
This also didn't seem to have any obvious effect, even when I restarted apache2 between calls.
(c) Setting the "Accept-Encoding" header to "" or "identity" using XMLHttpHeader.setHeaderRequest()
I tried both
xmlhttp.setRequestHeader("Accept-Encoding", "identity");
...and...
xmlhttp.setRequestHeader("Accept-Encoding", "");
Neither seemed to have any obvious effect: Firebug still reports that the request header holds
Accept-Encoding gzip, deflate
I checked the spec for this, and it seems as though setRequestHeader() should be allowed to change the AcceptEncoding header line, so this is a bit odd. Possibly a FF security hole that's been filled?
http://www.w3.org/TR/2006/WD-XMLHttpRequest-20060405/#dfn-setrequestheader
Note that the setRequestHeader() mechanism is apparently working ok, because adding...
xmlhttp.setRequestHeader("X-FavouriteFruit", "banana");
...adds a line to the Firebug request output:
X-FavouriteFruit banana
Basically, I'm pretty much out of ideas. How else can I stop my php responses being gzipped?
it would seem you use apache on the device to serve the PHP files, which means you could try something like this in /etc/php.ini (or in .htaccess via #php_value)
zlib.output_compression = Off
in the Language options section.
When I simply echo something out of php file, I do not send any headers intentionally, however - there are some default headers present anyway when I look at firebug response:
response headers:
HTTP/1.1 200 OK
Server: nginx
Date: Thu, 23 Jun 2011 19:33:51 GMT
Content-Type: text/html
Transfer-Encoding: chunked
Connection: keep-alive
Vary: Accept-Encoding
X-Powered-By: PHP/5.3.6-6~dotdeb.1
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
Content-Encoding: gzip
I'm curious - are these default response headers set by the server(nginx) or by PHP?
I believe it is a combination of both... You can tell that "X-Powered-By: PHP/5.3.6-6~dotdeb.1" comes from PHP and "Server: nginx" comes from NGINX.
You can alter the headers in PHP as follows:
<?php
header("HTTP/1.0 404 Not Found");
?>
The gzip header most definitely comes from NGINX as it is compressing the output (html) to the browser. PHP can "add" to the headers by calling a function like the one above. Then the server combines it with the PHP headers and serves the request.
It depends on your server whether or not the PHP headers take precedence over the server headers.
Hope this helps.
The majority are set by nginx, for example the Server, Date, Content-Encoding, and Connection. However, some other headers are set by PHP, and you can add others in PHP like this header("Name: Value");
The X-Powered-By header is controlled by the value of the expose_php directive in php.ini:
Decides whether PHP may expose the fact that it is installed on the server (e.g. by adding its signature to the Web server header). It is no security threat in any way, but it makes it possible to determine whether you use PHP on your server or not.
Most headers are sent by nginx. To list the headers (to be) sent by PHP, use the function headers_list:
<?php
echo htmlentities(print_R(headers_list(), true));
?>
PHP automatically sets some of them, like Content-Type: text/html for the hello world page. nginx sets the ones that have to do with the socket, like Connection: keep-alive.
You'll find settings for connections in nginx's configuration. Content-wise, it's PHP. You're allowed to override quite a few of them with the header() function in PHP, as well as add your own custom headers.
http://php.net/manual/en/function.header.php
For example, you could set the Content-Type to application/json if you're planning to have PHP send out a JSON string.
What's still missing in the answers is the role of PHP:
Some of the headers are indeed set by PHP itself, but the reason is not that easy to find. It's the default session cache delimiter behavior explained here: http://www.php.net/manual/en/function.session-cache-limiter.php
What's afaik not in the docs is how to turn them off completely - simply pass some undefined value to it:
session_cache_limiter(false);
You must to do this before you start your session. In case you are using the Zend Framework, you have to set this before your applications bootstrap() - otherwise it won't work.
You can also overwrite any of the default server headers using the header() function. For example, if you include in your PHP header('Server: ') this will reset the Server: header to be blank.