Showing posts with label gzip. Show all posts
Showing posts with label gzip. Show all posts

Wednesday, June 20, 2018

Meteor Http Client API Call Gzip uncompress resultant JSON not working

Leave a Comment

I don't know if it's the exact issue, but from what I can understand it is. I am making an external API call with the HTTP.call and trying to parse the response as JSON (which it is), but I'm getting strange content returned, which I think is Gzipped content. I'm setting the npmRequestOptions parameter for gzip to true, but it is still returning the same content.

Here's my code:

var result; try {   result = HTTP.call('GET', 'http://atlas.atdw-online.com.au/api/atlas/products', {     params: {       key: '594c18ea1a184997a5457593b5873c8f',       att: 'INDIGENOUSAUTHARTS',       out: 'json',     },     npmRequestOptions : {gzip : true, json: true},     headers: {       // "Accept": "application/json",       'Content-Type' : 'application/json; charset=UTF-16',       "OSLC-Core-Version": "2.0",     },    });  } catch (e) {   // Got a network error, timeout, or HTTP error in the 400 or 500 range. }  // Append data in correct experiences format. var content = JSON.parse(result.content); 

The error is as per the screenshot: Returned content is weird in result.content

Here are the response headers from the API call which seems to indicate the content is being gzipped:

HTTP/1.1 200 OK Access-Control-Allow-Credentials: true CF-RAY: 4291c15b957d4d88-PER Content-Encoding: gzip Content-Type: application/json; charset=utf-16 Date: Mon, 11 Jun 2018 05:42:36 GMT ETag: W/"863e-ylc8HuIAiQAynP7anYY1GA" Server: cloudflare Vary: Origin, Accept-Encoding X-Powered-By: Express 

I believe npmRequestOptions : {gzip : true, json: true} should be working, but it's not. There's no additional information available and I've been searching all day.

1 Answers

Answers 1

So I've figured out the solution to this was not in the Meteor app itself, it was in the content being returned. The response is UTF-16LE so I had to remove special characters from the response to I could JSONify it.

result = result.content.replace(/[^A-Za-z0-9{}@&:\-_() /\\"=[\],.?!]/g, '') 
Read More

Tuesday, March 27, 2018

How to Configure Heroku to host files using gzip compression

Leave a Comment

I am trying to deploy a node.js app on heroku , which is serving unity webGL exported game to clients. After Unity3d 5+ release , WebGL exports by Unity uses gzip compression by default .

Well ,

heroku server [Node.js] dont serves gzip compressed files , which is causing my Game to throw error in console on load , main unity loading window wont update (just blank) till files dont get completely download & a slight delay while browser manually decompresses it.

enter image description hereThese are the file types Unity WebGL Export provides = || . datagz || . jsgz || . memgz ||

So what i need is , a way to configure heroku node.js server for serving the gzip compression .

1 Answers

Answers 1

It doesn't look like you are having issues serving gzipped files. The messages in the console could be a separate issue altogether.

What is more likely is that your node app is not serving the right folder or files. If you can provide a list of files that is in your build folder (I assume that this is where Unity places its files), I can take a look.

Also, do review your Heroku configuration, namely the command used by the web process. If it is npm start or something, then look at the script it points to (see in your package.json file), and see if it is serving files out of the build folder.

Read More

Friday, June 2, 2017

Encoding Response as Gzip Causing Cookie to Not Be Set in Browser

Leave a Comment

I'm trying to reduce the network traffic by Gzipping all responses from backend, but I ran into an issue where cookie is not set in the browser if the login/logout call is being done the same way and I'm not sure why.

This is the backend code in Java.

Cookie cookie = new Cookie("cookie_name", cookieToken); cookie.setPath("/"); cookie.setMaxAge(Integer.MAX_VALUE); response.addCookie(cookie);  response.setContentType("application/json; charset=utf-8"); response.setStatus(HttpServletResponse.SC_OK);  response.setHeader("Content-Encoding", "gzip"); String json=serviceOutput.toString(); byte[] gzip = Utils.gzip(json.getBytes("UTF-8")); response.setContentLength(gzip.length); response.getOutputStream().write(gzip); 

Any pointer on why this doesn't work? I'm pretty sure I did the same thing previously without any issues.

--

Added the gzip method just in case it's relevant

public static byte[] gzip(byte[] content) throws IOException    {      ByteArrayOutputStream baos = new ByteArrayOutputStream();     GZIPOutputStream g = new GZIPOutputStream(baos);      if (content != null && content.length > 0) {         g.write(content, 0, content.length);         g.close();     }      return baos.toByteArray(); } 

2 Answers

Answers 1

I have modified your code for mocking data as

package com.mytests.pack;  import java.io.ByteArrayOutputStream; import java.io.IOException; import java.time.LocalDateTime; import java.util.zip.GZIPOutputStream;  import javax.servlet.ServletException; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse;  public class HomeServlet extends HttpServlet{     private static final long serialVersionUID = -2638972063792556071L;     private Cookie[] cookies;      @Override     protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {         cookies = request.getCookies();          System.out.println("----------------------======================-------------------");         if(null!=cookies){             for(Cookie c : cookies){                 System.out.println(c.getValue());             }         }else {             System.out.println("First request");         }         System.out.println("----------------------======================-------------------");          Cookie cookie = new Cookie("cookie_name", "cookiecontentishereofname"+LocalDateTime.now().toString());         cookie.setPath("/");         cookie.setMaxAge(Integer.MAX_VALUE);          response.setContentType("application/json; charset=utf-8");         response.setStatus(HttpServletResponse.SC_OK);         response.addCookie(cookie);          response.setHeader("Content-Encoding", "gzip");         String json="{\"keyone\":\"Somestring is here in the point\"}";          ByteArrayOutputStream obj=new ByteArrayOutputStream();         GZIPOutputStream gzipstream = new GZIPOutputStream(obj);          byte[] gzip = json.getBytes("UTF-8");         gzipstream.write(gzip);         gzipstream.close();         response.setContentLength(obj.toByteArray().length);         response.getOutputStream().write(obj.toByteArray());     } } 

with above code and jetty-distribution-9.4.0.v20161208

  • Tested Browsers

    -Google Chrome - Version 58.0.3029.110 (64-bit) RESULT :cookie was set

    screenshot

    -Opera - 45.0.2552.812 (PGO) RESULT :cookie was set

    screenshot

    -Mozilla Firefox - 53.0.3 (32-bit)

Important thing to note about FIREFOX
When you open developer tools it doesn't show any cookie set but Practically works fine check screenshots firefox cookie view

Where as

Jetty console output

Jetty console output shows cookie was set successfully!

other change in config I would like to show you

added POM dependency snippet as

  <dependencies>     <dependency>     <groupId>javax.servlet</groupId>     <artifactId>javax.servlet-api</artifactId>     <version>3.1.0</version>     <scope>compile</scope> </dependency>   </dependencies> 

Answers 2

Your code looks pretty ok. What I advice you is to show here the response plain text headers using for example curl -v http://your.host/under/test terminal command. If your cookie appears there, then it is a browser's thing

Read More

Wednesday, May 17, 2017

Safari not passing accept-encoding:gzip, deflate

Leave a Comment

I am making requests to cloudfront CDN and seeing very frustrating behavior. In chrome and firefox, the request passed the proper accept-encoding:gzip, deflate header.

However, safari does not do this and thus gets the uncompressed version of the file. This is a simple script tag in an HTML document. So I can't set the headers.

the same doc produces a request with the following header/browser combos

Safari headers

-H 'Cache-Control: max-age=0' \ -H 'If-Modified-Since: Mon, 08 May 2017 18:01:40 GMT' \ '

Chrome Headers

:method:GET :path:/main-b54b8739d65dfbd36152.js :scheme:https accept:/ accept-encoding:gzip, deflate, sdch, br accept-language:en-US,en;q=0.8 cache-control:no-cache pragma:no-cache

Also, the respective web inspectors provides additional information, in safari,Safari Screen shot

And in chrome, enter image description here

Additionally, the request takes 3 times longer in safari. 55ms in chrome and 150ms in safari, roughly.

I left out some info to protect my privacy. Thanks for the help!

1 Answers

Answers 1

Safari uses a different naming convention in their developer tools, which is consistent with your observations. Citing from this answer,

[1] Encoded = uncompressed filesize, from server [2] Decoded = uncompressed filesize, locally [3] Transferred = uncompressed file size + headers sent and received [4] Content-Length = compressed file sent, from server 

Please check the content-length property to see if it's really compressed.

Read More

Sunday, July 3, 2016

How to check empty gzip file in Python

Leave a Comment

I don't want to use OS commands as that makes it is OS dependent.

This is available in tarfile, tarfile.is_tarfile(filename), to check if a file is a tar file or not.

I am not able to find any relevant commands in the gzip module.


EDIT: Why do I need this: I have list of gzip files, these vary in sizes (1-10 GB) and some are empty. Before reading a file (using pandas.read_csv), I want to check if the file is empty or not, because for empty files I get an error in pandas.read_csv. (Error like: Expected 15 columns and found -1)

Sample command with error:

import pandas as pd pd.read_csv('C:\Users\...\File.txt.gz', compression='gzip', names={'a', 'b', 'c'}, header=False) Too many columns specified: expected 3 and found -1 

pandas version is 0.16.2

file used for testing, it is just a gzip of empty file.

7 Answers

Answers 1

Unfortunately, the gzip module does not expose any functionality equivalent to the -l list option of the gzip program. But in Python 3 you can easily get the size of the uncompressed data by calling the .seek method with a whence argument of 2, which signifies positioning relative to the end of the (uncompressed) data stream.

.seek returns the new byte position, so .seek(0, 2) returns the byte offset of the end of the uncompressed file, i.e., the file size. Thus if the uncompressed file is empty the .seek call will return 0.

import gzip  def gz_size(fname):     with gzip.open(fname, 'rb') as f:         return f.seek(0, whence=2) 

Here's a function that will work on Python 2, tested on Python 2.6.6.

def gz_size(fname):     f = gzip.open(fname, 'rb')     data = f.read()     f.close()     return len(data) 

You can read about .seek and other methods of the GzipFile class using the pydoc program. Just run pydoc gzip in the shell.


Alternatively, if you wish to avoid decompressing the file you can (sort of) read the uncompressed data size directly from the .gz file. The size is stored in the last 4 bytes of the file as a little-endian unsigned long, so it's actually the size modulo 2**32, therefore it will not be the true size if the uncompressed data size is >= 4GB.

This code works on both Python 2 and Python 3.

import gzip import struct  def gz_size(fname):     with open(fname, 'rb') as f:         f.seek(-4, 2)         data = f.read(4)     size = struct.unpack('<L', data)[0]     return size 

However, this method is not reliable, as Mark Adler (gzip co-author) mentions in the comments:

There are other reasons that the length at the end of the gzip file would not represent the length of the uncompressed data. (Concatenated gzip streams, padding at the end of the gzip file.) It should not be used for this purpose. It's only there as an integrity check on the data.


Here is another solution. It does not decompress the whole file. It returns True if the uncompressed data in the input file is of zero length, but it also returns True if the input file itself is of zero length. If the input file is not of zero length and is not a gzip file then OSError is raised.

import gzip  def gz_is_empty(fname):     ''' Test if gzip file fname is empty         Return True if the uncompressed data in fname has zero length         or if fname itself has zero length         Raises OSError if fname has non-zero length and is not a gzip file     '''     with gzip.open(fname, 'rb') as f:         data = f.read(1)     return len(data) == 0 

Answers 2

If you want to check whether a file is a valid Gzip file, you can open it and read one byte from it. If it succeeds, the file is quite probably a gzip file, with one caveat: an empty file also succeeds this test.

Thus we get

def is_gz_file(name):     with gzip.open(name, 'rb') as f:         try:             file_content = f.read(1)             return True         except:             return False 

However, as I stated earlier, a file which is empty (0 bytes), still succeeds this test, so you'd perhaps want to ensure that the file is not empty:

def is_gz_file(name):     if os.stat(name).ST_SIZE == 0:         return False      with gzip.open(name, 'rb') as f:         try:             file_content = f.read(1)             return True         except:             return False 

Answers 3

UPDATE:

i would strongly recommend to upgrade to pandas 0.18.1 (currently the latest version), as each new version of pandas introduces nice new features and fixes tons of old bugs. And the actual version (0.18.1) will process your empty files just out of the box (see demo below).

If you can't upgrade to a newer version, then make use of @MartijnPieters recommendation - catch the exception, instead of checking (follow the Easier to ask for forgiveness than permission paradigm)

OLD answer: a small demonstration (using pandas 0.18.1), which tolerates empty files, different number of columns, etc.

I tried to reproduce your error (trying empty CSV.gz, different number of columns, etc.), but i didn't manage to reproduce your exception using pandas v. 0.18.1:

import os import glob import gzip import pandas as pd  fmask = 'd:/temp/.data/37874936/*.csv.gz'  files = glob.glob(fmask)  cols = ['a','b','c']  for f in files:     # actually there is no need to use `compression='gzip'` - pandas will guess it itself     # i left it in order to be sure that we are using the same parameters ...     df = pd.read_csv(f, header=None, names=cols, compression='gzip', sep=',')     print('\nFILE: [{:^40}]'.format(f))     print('{:-^60}'.format(' ORIGINAL contents '))     print(gzip.open(f, 'rt').read())     print('{:-^60}'.format(' parsed DF '))     print(df)  

Output:

FILE: [    d:/temp/.data/37874936\1.csv.gz     ] -------------------- ORIGINAL contents --------------------- 11,12,13 14,15,16   ------------------------ parsed DF -------------------------     a   b   c 0  11  12  13 1  14  15  16  FILE: [  d:/temp/.data/37874936\empty.csv.gz   ] -------------------- ORIGINAL contents ---------------------  ------------------------ parsed DF ------------------------- Empty DataFrame Columns: [a, b, c] Index: []  FILE: [d:/temp/.data/37874936\zz_5_columns.csv.gz] -------------------- ORIGINAL contents --------------------- 1,2,3,4,5 11,22,33,44,55  ------------------------ parsed DF -------------------------         a   b   c 1  2    3   4   5 11 22  33  44  55  FILE: [d:/temp/.data/37874936\z_bad_CSV.csv.gz ] -------------------- ORIGINAL contents --------------------- 1 5,6,7 1,2 8,9,10,5,6  ------------------------ parsed DF -------------------------    a    b     c 0  1  NaN   NaN 1  5  6.0   7.0 2  1  2.0   NaN 3  8  9.0  10.0  FILE: [d:/temp/.data/37874936\z_single_column.csv.gz] -------------------- ORIGINAL contents --------------------- 1 2 3  ------------------------ parsed DF -------------------------    a   b   c 0  1 NaN NaN 1  2 NaN NaN 2  3 NaN NaN 

Can you post a sample CSV, causing this error or upload it somewhere and post here a link?

Answers 4

Try something like this:

def is_empty(gzfile):     size = gzfile.read().     if len(size) > 0:          gzfile.rewind()          return False     else:          return True 

Answers 5

import gzip  with gzip.open("pCSV.csv.gz", 'r') as f:      f.seek(3)     couterA = f.tell()      f.seek(2,0)     counterB = f.tell()      if(couterA > counterB):         print "NOT EMPTY"     else:         print "EMPTY" 

This should do it without reading the file.

Answers 6

Looking through the source code for the Python 2.7 version of the gzip module, it seems to immediately return EOF, not only in the case where the gzipped file is zero bytes, but also in the case that the gzip file is zero bytes, which is arguably a bug.

However, for your particular use-case, we can do a little better, by also confirming the gzipped file is a valid CSV file.

This code...

import csv import gzip  # Returns true if the specified filename is a valid gzip'd CSV file # If the optional 'columns' parameter is specified, also check that # the first row has that many columns def is_valid(filename, columns=None):      try:          # Chain a CSV reader onto a gzip reader         csv_file = csv.reader(gzip.open(filename))          # This will try to read the first line         # If it's not a valid gzip, this will raise IOError         for row in csv_file:              # We got at least one row             # Bail out here if we don't care how many columns we have             if columns is None:                 return True              # Check it has the right number of columns             return len(row) == columns          else:              # There were no rows             return False      except IOError:          # This is not a valid gzip file         return False   # Example to check whether File.txt.gz is valid result = is_valid('File.txt.gz')  # Example to check whether File.txt.gz is valid, and has three columns result = is_valid('File.txt.gz', columns=3) 

...should correctly handle the following error cases...

  1. The gzip file is zero bytes
  2. The gzip file is not a valid gzip file
  3. The gzipped file is zero bytes
  4. The gzipped file is not zero bytes, but contains no CSV data
  5. (Optionally) The gzipped file contains CSV data, but with the wrong number of columns

Answers 7

Unfortunately, any such attempt will likely have a fair bit of overhead, it would likely be cheaper to catch the exception, such as users commented above. A gzip file defines a few fixed size regions, as follows:

Fixed Regions

First, there are 2 bytes for the Gzip magic number, 1 byte for the compression method, 1 byte for the flags, then 4 more bytes for the MTIME (file creation time), 2 bytes for extra flags, and two more bytes for the operating system, giving us a total of 12 bytes so far.

This looks as follows (from the link above):

+---+---+---+---+---+---+---+---+---+---+ |ID1|ID2|CM |FLG|     MTIME     |XFL|OS | (more-->) +---+---+---+---+---+---+---+---+---+---+ 

Variable Regions

However, this is where things get tricky (and impossible to check without using a gzip module or another deflator).

If extra fields were set, there is a variable region of XLEN bytes set afterwards, which looks as follows:

(if FLG.FEXTRA set) +---+---+=================================+ | XLEN  |...XLEN bytes of "extra field"...| (more-->) +---+---+=================================+ 

After this, there is then a region of N bytes, with a zero-terminated string for the file name (which is, by default, stored):

(if FLG.FNAME set) +=========================================+ |...original file name, zero-terminated...| (more-->) +=========================================+ 

We then have comments:

(if FLG.FCOMMENT set) +===================================+ |...file comment, zero-terminated...| (more-->) +===================================+ 

And finally, a CRC16 (a cyclic redundancy check, in order to make sure the file header then works, all before we get into the variable, compressed data.

Solution

So, any sort of fixed size check will be dependent on whether the filename, or if it was written via pipe (gzip -c "Compress this data" > myfile.gz), other fields, and comments, all which can be defined for null files. So, how do we get around this? Simple, use the gzip module:

import gzip  def check_null(path):     '''     Returns an empty string for a null file, which is falsey,      and returns a non-empty string otherwise (which is truthey)     '''      with gzip.GzipFile(path, 'rb') as f:         return f.read(1) 

This will check if any data exists inside the created file, while only reading a small section of the data. However, this takes a while, it's easier to ask for forgiveness than ask permission.

import contextlib       # python3 only, use a try/except block for Py2 import pandas as pd  with contexlib.suppress(pd.parser.CParserError as error):     df = pd.read_csv(path, compression='gzip', names={'a', 'b', 'c'}, header=False)     # do something here 
Read More

Wednesday, March 23, 2016

HTTPS GZIP NGINX WTF

Leave a Comment

I've been trying for days now to get nginx to serve gzip content mainly because googles speed test told me to do it and we are trying to increase our SEO. I can't for the life of me understand what is going wrong here:

We are behind a firewall and serve two web heads underneath a load balancer. No matter what I've tried I can not get the response headers to come back with content-encoding:gzip. However, when I make the request using curl I can. Also when I access the site via https I do get the response back with gzip however it has nothing to do with nginx as I've turned gzip off in nginx and I still get the same response. What else would be serving the content as gzip?

UPDATE

Ok sorry after posting this several times with no response I was a little frustrated. Here is some info to go off:

We are using nginx 1.8.0 with php-fpm. The site is a Magento framework. I am trying to serve the main html pages compressed with gzip as well as the included css/javascript files. These files currently show not compressed in the response headers and Google pagespeed also says they are not compressed. Here is an example response header I see

Cache-Control:max-age=31536000 Connection:keep-alive Content-Type:application/x-javascript; charset=utf-8 Date:Tue, 15 Mar 2016 15:15:13 GMT ETag:"pub1448944926;gz" Expires:Wed, 15 Mar 2017 15:15:13 GMT Keep-Alive:timeout=8 Last-Modified:Tue, 01 Dec 2015 04:42:06 GMT Server:nginx Transfer-Encoding:chunked Vary:Accept-Encoding 

When I request the page via curl I get the gzip content.

curl -I -H 'Accept-encoding:gzip' mysite.com  

We have removed the staging site from the load balancer and the issue persists; eliminating any issues (for now) that may come form the load balancer.

When I access the site via https I get gzip content and here is the response header

Cache-Control:max-age=31536000 Connection:keep-alive Content-Encoding:gzip Content-Length:67085 Content-Type:application/x-javascript; charset=utf-8 Date:Tue, 15 Mar 2016 15:51:31 GMT ETag:"pub1448944926;gz" Expires:Wed, 15 Mar 2017 15:51:31 GMT Keep-Alive:timeout=8 Last-Modified:Tue, 01 Dec 2015 04:42:06 GMT Server:nginx Vary:Accept-Encoding 

Here are the relative config files for nginx

nginx.conf

user                    nginx; worker_processes        4; pid                     /var/run/nginx.pid; error_log               /var/log/nginx/error.log;  events {     worker_connections  1024;     multi_accept        on;     use                 epoll; }  http {     include             /etc/nginx/mime.types;     charset             utf-8;     default_type        application/octet-stream;      #access_log         /var/log/nginx/access.log main;     access_log          off;      log_format main     '$remote_addr - $remote_user [$time_local]     "$request" '     '$status $body_bytes_sent "$http_referer" '     '"$http_user_agent" "$http_x_forwarded_for"';      # compression     gzip                on;     gzip_http_version   1.0;     gzip_vary           on;     gzip_comp_level     5;     gzip_proxied        any;     gzip_min_length    100;     #   gzip_min_length     10240;     gzip_buffers        16 8k;     gzip_types          text/plain text/css application/x-javascript     text/comma-separated-values text/xml application/xml application/xml+rss     application/atom+xml text/javascript;     #gzip_disable       "MSIE [1-6].(?!.*SV1)";      # general options     sendfile            on;     tcp_nopush          on;     tcp_nodelay         off;     autoindex           off;     server_tokens       off;     merge_slashes       on;     client_header_buffer_size           1k;     client_body_buffer_size             32k;     client_max_body_size                64m;     server_names_hash_bucket_size       128;     large_client_header_buffers         2 1k;      # timeouts     send_timeout                        10;     keepalive_timeout                   2 8;     keepalive_requests                  200;     client_body_timeout                 12;     client_header_timeout               12;     reset_timedout_connection           on;      # pass through from load balancer     real_ip_header X-Forwarded-For;     set_real_ip_from 0.0.0.0/0;      # detect https     map $scheme $fastcgi_https {         default "";         https on;     }      # PHP-FPM     upstream phpfpm {         server unix:/run/php-fpm/php-fpm.sock weight=1 max_fails=5     fail_timeout=10;     }      # include active sites     include /etc/nginx/sites-enabled/*;     server {         listen 80 spdy default_server;         root /var/www/mysite.com;         location ^~ /app/                       { return 403; }         location ^~ /includes/                  { return 403; }         location ^~ /media/downloadable/        { return 403; }         location ^~ /pkginfo/                   { return 403; }         location ^~ /report/config.xml          { return 403; }         location ^~ /var/                       { return 403; }         location ^~ /lib/                       { return 403; }         location ^~ /dev/                       { return 403; }         location ^~ /RELEASE_NOTES.txt          { return 403; }         location ^~ /downloader/pearlib         { return 403; }         location ^~ /downloader/template        { return 403; }         location ^~ /downloader/Maged           { return 403; }         location ~* ^/errors/.+\.xml            { return 403; }     }  } 

Sites-enabled/mysite

server {      #mysiteip is an actual ip that I've removed for security      listen mysiteip:80;       server_name www.test.mysite.com;     return 301 $scheme://test.mysite.com$request_uri; } server {     # settings     listen mysiteip:80;     listen mysiteip:443 ssl;     server_name test.mysite.com;     root /var/www/mysite.com/testing/current/;     index index.html index.htm index.php;      # security     ssl_protocols TLSv1.2;     ssl_ciphers RC4:HIGH:!aNULL:!MD5;     ssl_prefer_server_ciphers on;      # SSL Certificate Settings     ssl_certificate     /etc/nginx/ssl/bundle.crt;     ssl_certificate_key /etc/nginx/ssl/star_mysite_com.key;       access_log /var/log/nginx/mysite.access.log;     error_log /var/log/nginx/www-mysite-com_error.log;      # routes     include /etc/nginx/conf.d/security.conf;     include /etc/nginx/conf.d/assets.conf;     include /etc/nginx/conf.d/rewrites.conf;      # Attempt to serve the request by trying direct file, directory, Magento front controller      large_client_header_buffers 8 16k;      location / {         try_files $uri $uri/ /index.php?$args;         expires max;     }      # The downloader has its own index.php that needs to be used     location ~* ^(/downloader)(.*) {         try_files $uri $uri/ /downloader/index.php$1;     }      # REST API endpoint     location /api {         rewrite ^/api/rest /api.php?type=rest last;         rewrite ^/api/v2_soap /api.php?type=v2_soap last;         rewrite ^/api/soap /api.php?type=soap last;     }      # Pass PHP scripts to PHP-FPM daemon     location ~* \.php$ {         # filter out problem conditions         location ~ \..*/.*\.php$ { return 404; }          # bring in parameters         include /etc/nginx/conf.d/fastcgi.conf;         fastcgi_param MAGE_RUN_CODE default;         fastcgi_param MAGE_RUN_TYPE store;          # DEVELOPER MODE         #fastcgi_param MAGE_IS_DEVELOPER_MODE true;          # send requests to upstream, but blacklist media location from fcgi         if ($uri !~ "^/(media)/") {             fastcgi_pass phpfpm;         }     } } 

conf.d/rewrites.conf

# I am using this rewrite for the fooman speedster extension  location /skin/m {    rewrite ^/skin/m/([^/]+)(/.*.(js|css))$ /lib/minify/m.php?f=$2&d=$1; } 

Any insight as to what is going on or being done wrong would be greatly appreciated. I can provide more info if needed. Also the rewrite for Fooman is used for minification and even without this extension installed and the rewrite removed I still get no gzip.

2 Answers

Answers 1

Your HTTP responses are probably cached. These HTTP headers give it away:

Cache-Control:max-age=31536000 Expires:Wed, 15 Mar 2017 15:15:13 GMT 

This basically tells everyone who requests the response to cache the response as they see fit, because it will be valid and cacheable until March 2017. In your example this is for Javascript, so it's fine, but if you test the resource again, then it is quite possible that the old response is being returned. You would need to make sure every cache is emptied and no proxy has cached the response. Otherwise you may be getting the response from an intermediate location, not your Nginx server, so you cannot verify any GZIP settings in that case.

HTTPS requests are generally not cached by any proxy (because they do not see the content), so that may be the reason why it works there.

The following lines in your config probably leads to accidental caching:

location / {     try_files $uri $uri/ /index.php?$args;     expires max; }  

Nginx adds expires and max-age cache control headers to all requests by using the expires directive here, even dynamic requests. You should check if your HTML/PHP pages aren't cached by using this header and if that may be part of the problem.

Answers 2

Cant add comment now because of Bounty. @iquiot @iquito Thanks I disabled expires max and no luck. I tracked down to this being set in the Fooman extension. and set max-age to zero. Here is the new response header ... but still no gzip

Cache-Control   max-age=0 Connection  keep-alive Content-Type    text/css; charset=utf-8 Date     Thu, 17 Mar 2016 19:35:05 GMT Etag    "pub1457625059;gz" Last-Modified Thu, 10 Mar 2016 15:50:59 GMT Server nginx/1.8.0 Transfer-Encoding chunked Vary    Accept-Encoding 

UPDATE:

I removed myself from the larger picture to try and debug this issue. I created a test.html file and am using this to try and see if I can get any sort of compression going. One strange thing that I am noticing is that if I set the gzip_min_length to say 100 I get content-length in the header when the content is under 100 however as soon as I exceed 100 the content-length goes away.

UPDATE 2: When using curl any sort of "Accept:" header that is set does not return gzip in the response. Could this be a possible culprit?

UPDATE 3: using this little tool for firefox https://addons.mozilla.org/en-US/firefox/addon/modify-headers/developers I was able to modify the headers sent. By completely disabling the user agent header I now get the proper response header with content-encoding gzip. However I do not have anywhere in my nginx config a disable parameter set for gzip which would give such behavior.

Read More