Rails caching works only if I send the If-None-Match header manually - ruby-on-rails

My rails code:
def index
battles = Battle.feed(current_user, params[:category_name], params[:future_time])
#battles = paginate battles, per_page: 50
if stale?([#battles, current_user.id], template: false)
render 'index'
end
end
If I send the If-None-Match header with the last Etag manually I get 304 status code in return, If I don't send it manually (The header is sent automatically with the same If-None-Match header) I get 200 status code...
I'm checking the server using Postman rest client (Cache enabled).

I cannot comment on the Rails side of things here but this is correct behaviour if I'm following you.
When sending "If-None-Match" you get a 304 if the content has not changed (same e-tag). This is basically saying either yourself or something in between such as a proxy has the content already and so does not need to transfer the body again.
If you omit the header then you see a 200. Postman by default will send a set of a headers but it's also pretty lean in the sense that it strips a lot away. Try the same request in your browser and you'll get a 304. You'll see your browser will be set to use caching where possible.
Things may get different if you are relying upon server side caching. You may be seeing what looks like a new response yet the server is actually doing very little yet yielding a 200 response.
To summarise the header is doing the right job from your description.

Related

Can Erlang's mod_esi redirect?

I'm trying to learn doing web application development in Erlang, just using the standard library's inets modules at this stage.
The snag I've hit is that I want to validate the data from a post query, and then either redirect back to the form page with error messages or to a welcome page.
Basically, what I need to do is get a return header which looks like
HTTP/1.1 303 OK
Location: /form.html
...
While mod_esi:deliver/2 lets me add header key: value fields, I don't see how I can replace the default
HTTP/1.1 200 OK
...
With HTTP/1.1 303 OK to do a redirect.
While I'm sure cowboy, elli, etc can do this easily, before learning a third-party application I was wondering if mod_esi or other inets modules can do this.
What I have is a module called handler which has a function form/3 (adhering to http://erlang.org/doc/man/mod_esi.html#Module:Function-3) which returns http://erlang.org/doc/man/mod_esi.html#deliver-2 as required.
If you include a Location header, mod_esi should automatically set the status to 302. If you want to set the status to something else, you can use the Status header. e.g. Status: 303 See Other. (This is how CGI works too.)

How does Rails know when to respond with 304 status?

Given I have rails controller which accesses DB to retrieve data and render JSON response using serializer, what conditions must be met to make rails respond with 304?
If it has to compare previous response to currently retrieved, what kind of comparison is it?
The magic happens in Rack::ETag and Rack::ConditionalGet. (Mine are located at $GEM_HOME/rack-1.5.5/lib/rack/conditionalget.rb and $GEM_HOME/rack-1.5.5/lib/rack/etag.rb.)
These are middlewares.
Rack::ETag makes a digest out of the body (the very same body which gets returned by the rack function #app.call) and sets the response ETag header to this value. For Rails 4.0, at least, it's an MD5 hex digest.
Rack::ConditionalGet compares the request's If-None-Match header against the response's ETag header. If they match, then it returns a 304.
Server look for Cache-Control, Content-Location, Date, ETag, Expires, and Vary http header values in previous and current request from same requester.
If everything is same it return 304 response otherwise change content and return 200.
You can look https://httpstatuses.com/304 for more information.

Cannot get list of Projects from OnDemand Jira REST API + Basic Auth

I seem to be getting intermittent results back from our OnDemand Jira instance's REST API.
If I properly set the Authorization header to 'Basic [base64login]' & the Content-Type header to 'application/json', and then issue a GET to http://[installation].atlassian.net/rest/api/2/project I get different results each time.
The first result always seems to be an empty JSON array ([]). Subsequent calls seem to work as expected for the most part, but occasionally I get an empty response. Also, if I enter invalid credentials I get an empty response rather than an error / 401 / etc.
Is there some gotcha to using Basic Auth on OnDemand instances? Does it require the additional use of cookies or something else?

Headers missing from XMLHttpRequest on iOS UIWebView

I'm experincing an odd situation where I have some JavaScript code running in a UIWebView. That JS code creates and fires off an XMLHttpRequest to pull some data off a server.
I listen for onreadystatechange and I have an event listener for the "progress" event.
For some reason this XMLHttpRequest returns only a subset of the Response Headers when queried using request.getAllResponseHeaders() or request.getResponseHeader('whatever'). Note that I've tried GETting any number of different of URLs and they all exhibit the same partial lack of headers.
The only headers returned are Pragma, Cache-Control, Expires & Content-Type, nothing else returns (content-length, encoding, various custom headers, etc).
The odd thing is that the same JS code executed in Mobile-Safari will show all the headers, in strike contrast to how that code behaves when inside a UIWebView.
Any idea what's going on here?

max age with nginx/passenger/memcached/rails2.3.5

I notice that in my production enviornment (where I have memcached implemented) in see a cache-control - max-age header in firebug, anytime I am looking at an index page (posts for example).
Cache-Control max-age=315360000
In my dev environment that header looks like following.
Cache-Contro private, max-age=0, must-revalidate
As far as I know I have not done anything special with my nginx.conf file to specify max age for regular content, I do have expires-max set for css, jpg etc. here is my nginx.conf file..
http://pastie.org/1167080
So why is this cache-control is being set? How can I control this cache-control, because the side effect of this is kinda bad. This is what happens.
1 - User request all_posts listing and get a list of 10 pages (paginated)
2 - User view page 1, 2 3 and the respective caches are created.
3 - User goes back to page 1 and firefox does not even make a request to the server. Normally I would expect it would reqeust and hit the cache created in step #2.
The other issue is that if a new post has been created and now the cache is refreshed and it should be at the top of page 1, the user does not get to see it..because the browser isn't hitting the server.
Please help!
Thanks
Update :
I tried setting expires_now in my index action. NO difference the max-age is still the same large value.
Could this be a problem with my max-age regex? I basically want it to match only asset files(images, js, css etc)
I think you're right that this is a problem with your max-age regex.
You're matching against this pattern: ^.+.(jpg|jpeg|gif|png|css|js|swf)?([0-9]+)?$
Because you have question marks ("this part is optional") after both parenthesized sections, the only mandatory part of the regex is that the request URI have at least two characters (.+.). In other words, it's matching pretty near every request to your site.
This is the pattern we use: \.(js|css|jpg|jpeg|gif|png|swf)$
That will match only requests for paths ending with a dot and then one of those seven patterns.

Resources