net::ERR_CONTENT_DECODING_FAILED when using Rack::Deflater on jruby - ruby-on-rails

net::ERR_CONTENT_DECODING_FAILED
I am receiving this in chrome when Rack::Deflater is enabled, when using on jruby.
After having some reading it looks like this is some jruby issue with gzipping.
Is there any alternative for serving gzipped assets? And also dynamically gzipping responses?
I am hosting the application on heroku. Rails version is 3.2.X
I think this is related with this issue:
https://github.com/jruby/jruby/issues/1371#ref-issue-15218894

This error comes by browser
The response should contain the header telling the client which compression scheme is being used: Content-Encoding: gzip and
The request should contain the correct header: "Accept-Encoding: gzip, deflate"

Related

Rails sending gzip or uncompressed file

As per rails guides, compression is on atuomatically for assets unless specifically defined differently config.assets.gzip. These, and the uncompressed files are being generated on the application's shared/assets folder.
Context: nginx server version 1.14 + Phusion Passegner 6.0 running
How can I tell whether the call to the server is invoking the .gz vs uncompressed asset (assuming the client browser is not using the cached version)?
In the client request, there will be the Accept-Encoding header
It may contain smth like gzip, deflate, br
In this case, gzipped resource will be sent if there's one available. In the response headers there will be Content-Encoding: gzip then

Rack-cors not showing headers in production env for swagger-ui_rails

I'm currently running a couple of Rails 3.2.x apps. The one using Ruby 1.9.x and is the api endpoint has Rack-cors gem (1.0.1) on it - app Alice; the other runs swagger-ui_rails gem and is the app hosting the api documentation -- app Bob. The swagger docs was created wth swagger-docs gem, which runs format version 1.2. For some reason or another, I cannot get app Alice to give me information for Bob because of this error:
Failed to load https://alice.example.com/api-docs/v1/api-docs.json:
No 'Access-Control-Allow-Origin' header is present on the requested resource.
Origin 'http://bob.example.com:3000' is therefore not allowed access.
However! When I look on the network tab, the response is a 200 and I can see the json information. But the response headers definitely do NOT have the required Access-Control-Allow-Origin header.
This happens both thru AWS Elastic Beanstalk (Bob is hosted on EBS) and locally (w/ a bound address).
In my config/environments/production.rb of Alice, I have the following:
config.middleware.insert_before 0, 'Rack::Cors' do
allow do
origins ->(origin, env) do
Rails.logger.warn("CORS origin: #{origin}")
origin =~ /\.example\.com(:\d+)?\z/
end
resource('*', :methods => [:get, :post, :options], :headers => :any)
end
end
When I have this code in config/environments/development.rb in Alice, localhost connects and swagger-ui shows up as expected with no errors in console.
In the network tab of Chrome, this is what I have locally (Bob and Alice in dev/localhost)
Access-Control-Allow-Methods:GET, POST, OPTIONS
Access-Control-Allow-Origin:http://apitest.bob.com:3000
Access-Control-Expose-Headers:
Access-Control-Max-Age:1728000
Content-Length:1499
Content-Type:application/json
Date:Fri, 22 Sep 2017 21:44:45 GMT
Last-Modified:Mon, 28 Aug 2017 17:37:22 GMT
Server:
Vary:Origin
This is what I get for when Bob is in dev and Alice is in prod:
Accept-Ranges:bytes
Connection:keep-alive
Content-Length:1500
Content-Type:application/json
Date:Fri, 22 Sep 2017 23:10:00 GMT
ETag:"abc-559ce64fb8374"
Last-Modified:Fri, 22 Sep 2017 22:04:35 GMT
Server:
As you can see, prod-Alice does not return any sort of headers the way dev-Alice does, even with the exact same Rack-Cors code block.
rake middleware displays Rack::Cors at the top of the stack, and curl -i https://alice.example.com/api-docs/v1/api-docs.json has never returned the proper access-control headers for me, both locally and on Bob's server.
prod-Bob also has some EBS extensions to add some request headers and methods to nginx. In some other SO post, I saw folks adding in response headers directly via Rails, and so Bob also has the following in application_controller.rb (and in dev, with binding.pry, I can confirm that the response definitely has the specified headers)
after_filter :set_access_control_headers
def set_access_control_headers
headers['Access-Control-Allow-Origin'] = Rails.configuration.hostnames['headers']
headers['Access-Control-Request-Methods'] = 'GET, PUT, POST, OPTIONS'
end
I'm a bit at a loss and any help or thoughts would be appreciated.
The Swagger-docs gem that I'm using puts the .json files that I've created into Rails' /public directory. As such, Rails sees this as static files and not something that should go through Rack middleware. Since our production.rb file had config.serve_static_assets = false, that meant that all these static files were the responsibility of our web server (Apache/Nginx) and not the responsibility of rack-cors gem.
After adding in some CORS headers to Apache, swagger-ui loaded appropriately, but was doubling up the headers - 1st for Apache, 2nd for rack-cors.
I've since removed rack-cors gem and have adjusted the Apache server conf setting on Alice, based on an SO answer related to wildcard subdomains:
/etc/apache2/sites-enabled/mysite.conf
SetEnvIf Origin ^(https?://.+\.example\.com(?::\d{1,5})?)$ CORS_ALLOW_ORIGIN=$1
Header append Access-Control-Allow-Origin %{CORS_ALLOW_ORIGIN}e env=CORS_ALLOW_ORIGIN
Header merge Vary "Origin"
Header set "Access-Control-Allow-Methods" "GET, POST, OPTIONS"

What Rails module or gem does set default response headers?

With empty Rails app I have Cache-Control set to max-age=0, private, must-revalidate by default.
I want to understand this process better so I am trying to detect code that does this job.
I have checked actionpack, rake middleware, config.action_dispatch.default_headers, initializers and envinronment configs.
I am using Rails 4.2, nginx as web server and Passenger as application server.
Possibly this is some rack middleware or application server itself.
Rack::ETag sets default Cache-Control header.

Nginx not rendering .json URLs - Rails

I have a Rails 4 application with nginx 1.4.4 and I'm having issues trying to access JSON routes.
I'm trying to access the following route:
http://www.example.com/products/106.json
Which produces a 404 / Not found in my nginx server. However, in my development server it works correctly (a Thin server), it displays the product as JSON.
I have already added the application/json json; line to the mime.types config file.
What else should I look in order to fix this? I can provide more information if needed. Thanks.

Compressing a JSON response from a Rails app

We have an app that queries for locations for a customer. We're getting to the point where some customers could have upwards of 10,000 locations. The JSON response for this can get quite large, over 1mb sometimes.
I'm wondering first off the best way to compress this. We have apache in front of a Rails app running in trinidad with JRuby. Can I just set mod_deflate to always compress any responses that are application/json? How might I go about doing this?
Next, what is the browser support for gzip'd json? When I gzip a sample response of 200k it goes down to 30k. That's a significant savings. We're really like to be able to minimize the size of that response without having to minimize the number of locations returned.
In general, for newer versions of Rails, you can do it by adding
use Rack::Deflater
before the "run" line in the config.ru file. This will work perfectly with browsers/clients that support gzip. We use it in production on major websites.
Note for JRuby users: This assumes that your Rails app is launched through Rack, which it often isn't for JRuby. You need a recent version of JRuby-Rack and configure it in Warbler to run in 'rack' mode instead of 'rails' mode.
If the browser supports gzip'd/deflated data, then JSON will go through it just fine. AJAX data is just a regular HTTP request that was done on behalf of a script, rather than a human. At the HTTP level, there's absolutely zero difference between transferring some HTML or a JSON string - it's just data.
For Googlers... [I'm running Apache 2.2.16 and don't care about IE6]
JSON Responses with Content-Encoding = gzip didn't happen until I edit mod_deflate.conf to include this:
AddOutputFilterByType DEFLATE application/json
You can check server response headers with Firefox / Firebug / Net tab
First, make sure you have apache's mod_deflate installed by running this command.
a2enmod deflate
If this command installed it, restart apache. If not, you're good for now.
service apache2 restart
In apache2.conf usually located at /etc/apache2 append this line to the end of the file. This will include a file that we'll create in a little.
Include mod_deflate.conf
Next, we'll edit the mod_deflate.conf with our options:
SetOutputFilter DEFLATE
SetEnvIfNoCase Request_URI \
\.(?:exe|t?gz|zip|bz2|sit|rar)$ \
no-gzip dont-vary
SetEnvIfNoCase Request_URI \.pdf$ no-gzip dont-vary
#Skip browsers with known problems
BrowserMatch ^Mozilla/4 gzip-only-text/html
BrowserMatch ^Mozilla/4\.0[678] no-gzip
BrowserMatch \bMSIE !no-gzip !gzip-only-text/html
The first block of code disables gzipping exes, gzs, pdfs.. etc
The second block of code skips deflation from browsers that don't support it.
Finally, restart apache again
service apache2 restart
The settings were copied from the link below:
http://www.howtoforge.com/apache2_mod_deflate

Resources