Heroku production setting Cache-Control differently from local production - ruby-on-rails

I have an app running on heroku at http://chesseng.herokuapp.com/ when I visit the page with chrome and its caching disabled I get a response header for application-fingerprint.css that is something like
Cache-Control:private
Connection:keep-alive
Content-Encoding:gzip
Content-Type:text/css
Date:Wed, 17 Oct 2012 00:17:19 GMT
Last-Modified:Tue, 16 Oct 2012 03:13:38 GMT
Status:200 OK
transfer-encoding:chunked
Vary:Accept-Encoding
X-Rack-Cache:miss
However if I start up a local instance with rails s -e production and visit it the response header for application-fingerprint.css is something like
Age:5119
Cache-Control:public, max-age=31536000
Connection:Keep-Alive
Content-Encoding:gzip
Content-Length:95828
Content-Type:application/javascript
Date:Tue, 16 Oct 2012 23:01:27 GMT
Etag:"0bf9e9837d421c2e28be1ef4f0794a48"
Last-Modified:Tue, 16 Oct 2012 01:07:17 GMT
Server:WEBrick/1.3.1 (Ruby/1.9.3/2012-04-20)
Vary:Accept-Encoding
X-Content-Digest:add442e2036c1e6e9f4860dcc44496582a5c91b1
X-Rack-Cache:fresh
X-Request-Id:b89de17e397ac7b60acfe500e8d15df9
X-Runtime:0.001632
X-Ua-Compatible:IE=Edge,chrome=1
Why are the caching related fields like Cache-Control, Etag so different compared to heroku? Presumably I want heroku to return Cache-Control:public, max-age=31536000. But I need to first understand why Cache-Control:public, max-age=31536000 is being set in my local production mode. Its puzzling because if I set config.static_cache_control = "public, max-age=3600" in config/environments/production.rb and start up a local server in production it still gives back max-age=31536000 and seems to ignore max-age=3600

From the X-Rack-Cache headers it looks like you’re using the rack-cache middleware which would affect the caching headers. Since locally your resource is in the cache (X-Rack-Cache:fresh), but on Heroku it isn’t (X-Rack-Cache:miss) that would explain the difference.
Try removing rack-cache from your middleware stack and see if the differences go away.

Related

Rails static assets not caching with CloudFlare

I have a Rails 4.2.10 site on Heroku with CloudFlare activated. However, CloudFlare keeps reporting a MISS on my static assets. CloudFlare has been no help. Any ideas?
Website: https://www.eventingvolunteers.com/
Request URL:https://www.eventingvolunteers.com/assets/application-c5697db660693224e57f66260130bdeb07762900fb1b56009477833c84c6c589.js
Request Method:GET
Status Code:200 (from memory cache)
Remote Address:104.27.157.140:443
Referrer Policy:no-referrer-when-downgrade
Response Headers
cache-control:public, max-age=31536000
cf-cache-status:MISS
cf-ray:3c3d502a79045735-IAD
content-encoding:br
content-type:application/javascript
date:Sun, 26 Nov 2017 13:49:48 GMT
expires:Mon, 26 Nov 2018 13:49:48 GMT
last-modified:Sun, 26 Nov 2017 13:47:31 GMT
server:cloudflare-nginx
status:200
vary:Accept-Encoding
via:1.1 vegur
Request Headers
Provisional headers are shown
This js file was served from your browser cache, hence CF cache status is MISS
Disable cache in browser an reload, cf-cache-status will be HIT

How to force nginx to include Content-Length header on HEAD requests

How do you configure nginx to return a valid Content-Length header when responding to a HTTP HEAD request? Currently my server returns this:
curl --head http://example.com/myfile.xml
HTTP/1.1 200 OK
Date: Tue, 23 Aug 2016 13:49:46 GMT
Content-Type: text/xml
Set-Cookie: __cfduid=da2daeaa59809916192f7ac0645d3a3e91471960186; expires=Wed, 23-Aug-17 13:49:46 GMT; path=/; domain=.example.com; HttpOnly
Last-Modified: Mon, 22 Aug 2016 16:20:26 GMT
Vary: Accept-Encoding
ETag: W/"57bb264a-5442b26a"
Expires: Thu, 31 Dec 2037 23:55:55 GMT
Cache-Control: max-age=315360000
Access-Control-Allow-Origin: *
Access-Control-Request-Method: *
Cache-Control: public
Server: cloudflare-nginx
CF-RAY: 9dac40-LHR
X-Cache: MISS from Squid
Via: 1.1 Squid (squid/3.2.14)
I must send the Content-Length header with the response to HEAD (if I don't, the service that checks that URL will never see that the file was changed, and will not download the new version). How do you set it up?
I might be wrong, but nginx probably isn't showing the content-length because of nature of dynamic content generated by Rails's application server.
You can ask Rails to send that in response header. In your Rails application's config/application.rb add the following middleware:
config.middleware.use "Rack::ContentLength"
This should return the content-length header in response.

enabling rails page caching causes http header charset to disappears

I need charset to be utf-8, which seem to be the case by default. Recently I enabled page caching for a few static pages:
caches_page :about
The caching works fine, and I see the corresponding about.html and contact.html pages generated in my /public folder, except when the page renders, it's no longer in utf-8.
After googling for a bit I tried looking at the http headers with wget, before and after caching:
first time:
$wget --server-response http://localhost:3000/about
HTTP request sent, awaiting response...
1 HTTP/1.1 200 OK
2 X-Ua-Compatible: IE=Edge
3 Etag: "f7b0b4dea015140f3b5ad90c3a392bef"
4 Connection: Keep-Alive
5 Content-Type: text/html; charset=utf-8
6 Date: Sun, 12 Jun 2011 03:44:22 GMT
7 Server: WEBrick/1.3.1 (Ruby/1.8.7/2009-06-12)
8 X-Runtime: 0.235347
9 Content-Length: 5520
10 Cache-Control: max-age=0, private, must-revalidate
cached:
$wget --server-response http://localhost:3000/about
Resolving localhost... 127.0.0.1
Connecting to localhost[127.0.0.1]:3000... connected.
HTTP request sent, awaiting response...
1 HTTP/1.1 200 OK
2 Last-Modified: Sun, 12 Jun 2011 03:34:42 GMT
3 Connection: Keep-Alive
4 Content-Type: text/html
5 Date: Sun, 12 Jun 2011 03:39:53 GMT
6 Server: WEBrick/1.3.1 (Ruby/1.8.7/2009-06-12)
7 Content-Length: 5783
as a result the page displays in ISO-8859-1 and I get a bunch of garbled text. Does anyone know how I can prevent this undesirable result? Thank you.
The solution will depend on the server used.
When you use page cache, the servers reads the server directly, so the rails stack does not provide encoding information to the server. Then the server default apply.
If you're using apache with passenger, add to the configuration:
AddDefaultCharset UTF-8
If you need specific charsets, use a solution like the one in http://www.philsergi.com/2007/06/rails-page-caching-and-mime-types.html
<LocationMatch \/(rss)\/?>
ForceType text/xml;charset=utf-8
</LocationMatch>
<LocationMatch \/(ical)\/?>
ForceType text/calendar;charset=utf-8
</LocationMatch>

Set MIME type for server

i've seen a bunch of topics about setting the MIME types.
But, no one helped me.
He is my problem:
I have a Rails website with bunch of video in .ogv and .mov formats, located in /public folder.
I refer to these files in HTML5 video tag.
There is no problem with .mov files, they are played nice in WebKit browsers.
The problem is with .ogv.
I think, it's because wrong MIME type for .ogv.
Here is what i get for .mov (correct):
$ curl -I http:/mywebsite.com/video.mov
HTTP/1.1 200 OK
Date: Sun, 03 Apr 2011 19:57:41 GMT
ETag: "4d98744c-1bb-87563c0"
Last-Modified: Sun, 03 Apr 2011 13:21:16 GMT
Content-Type: video/quicktime
Content-Length: 443
And here is what i get for .ogv:
$ curl -I http://mywebsite.com/video.ogv
HTTP/1.1 200 OK
Date: Sun, 03 Apr 2011 19:22:20 GMT
ETag: "4d987dcf-379884-81c533dc"
Last-Modified: Sun, 03 Apr 2011 14:01:51 GMT
Content-Type: application/octet-stream
Content-Length: 3643524
Instead of "application/octet-stream" i need "video/ogg".
I have a Mongrel server (no Apache as front-end), as i recently got to know. So, there is no way to use .htaccess.
I need to set MIME-type for regular files, not responses from controller etc.
I've tried several ways, described in my previous question: HTML 5 video (ogv) and MIME types
But i does't works. I still get "application/octet-stream".
My Questions are:
How can i set mime types for regular files, not responses from controller ?
Does Mongrel serves files, located in /public directory, or something else ?
I've figured it out.
All the methods, described in my previous question are setting MIME-types for Rails environment, not Mongrel.
I need additional MIME-types at Mongrel level, not Rails.
So, by starting mongrel via …
/usr/bin/mongrel_rails,
… I need to pass a YAML file to it, that contains additional MIME-types, i want to declare. This YAML file might look like this (mongrel_mime_types.yml):
.ogv: video/ogg
.ogg: application/ogg
.ogx: application/ogg
I keep it in /config/initializers, for convenience.
So, by starting Mongrel, i need to pass this file:
/usr/bin/mongrel_rails -m /path_to_my_project/http/config/initializers/mongrel_mime_types.yml
Now, if i check with curl, I'm getting correct MIME:
$ curl -I http://mywebsite.com/video.ogv
HTTP/1.1 200 OK
Date: Mon, 04 Apr 2011 05:38:01 GMT
ETag: "4d987dcf-379884-81c533dc"
Last-Modified: Sun, 03 Apr 2011 14:01:51 GMT
Content-Type: video/ogg
Content-Length: 3643524

Passenger/Apache: Can't set expire headers for versioned resources (rewrite rule not recognized)

I'm trying to set the expire headers for Rails' auto-versioned resources, like whatever.css?1234567890 . (I don't want to set the expire headers for unversioned resources.) The only method I could find online involved two steps: 1) rewrite all urls that end in 10 digits to load from /public/add_expires_header instead of from /public, where add_expires_header is a symlink that points to /public 2) Add an expiry date to all files from add_expires_header.
Seems like a good idea -- but passenger doesn't seem to recognize the rewrite rule, as indicated by the below curl results.
(Note: a lot of people seemed to think they could accomplish my goal using FilesMatch, but I read elsewhere that FilesMatch can't see the query string.)
#from sites_enabled/sitename in the tags
...
RewriteCond %{QUERY_STRING} ^[0-9]{10}$
RewriteRule ^(.*)$ /add_expires_header%{REQUEST_URI} [QSA]
ExpiresActive On
ExpiresDefault "access plus 1 years"
...
-----
#curl indicates that rewrite rule isn't taking effect
manu#Blade-Server:~$ curl -I -L "http://x.com/stylesheets/style.css?1249092148"
HTTP/1.1 200 OK
Date: Tue, 11 Aug 2009 04:07:49 GMT
Server: Apache/2.2.11 (Ubuntu) Phusion_Passenger/2.2.4 PHP/5.2.6-3ubuntu4.1 with Suhosin-Patch
Last-Modified: Sat, 01 Aug 2009 02:02:28 GMT
ETag: "455b-2fbb-4700aedc5f500"
Accept-Ranges: bytes
Content-Length: 12219
Vary: Accept-Encoding
Content-Type: text/css
manu#Blade-Server:~$ curl -I -L "http://x.com/add_expires_header/stylesheets/style.css?1249092148"
HTTP/1.1 200 OK
Date: Tue, 11 Aug 2009 04:07:55 GMT
Server: Apache/2.2.11 (Ubuntu) Phusion_Passenger/2.2.4 PHP/5.2.6-3ubuntu4.1 with Suhosin-Patch
Last-Modified: Sat, 01 Aug 2009 02:02:28 GMT
ETag: "455b-2fbb-4700aedc5f500"
Accept-Ranges: bytes
Content-Length: 12219
Cache-Control: max-age=31536000
Expires: Wed, 11 Aug 2010 04:07:55 GMT
Vary: Accept-Encoding
Content-Type: text/css
I've also tried including the rewrite stuff in apache2.conf, httpd.conf, and public/.htacess
I prefer to do this by combining it with using an assets host on a separate subdomain to avoid the whole rewrite issue. That way you can set the expire headers for everything on that subdomain. You can activate this in rails in environments/production.rb.
If you don't want to go with a separate subdomain I think the code below should do it, although I have not tested it myself:
ExpiresActive On
<FilesMatch "\.(ico|gif|jpe?g|png|js|css)$">
ExpiresDefault "access plus 1 year"
</FilesMatch>

Resources