Using Etags with ember-data - caching

I am trying to implement some client side caching via etags and last modified headers; however, ember-data doesn't seem to be using the etags for the ajax requests. I only get 200 responses and never a 304. I don't see any ETag header being sent with the request headers.
When I make the ajax request multiple times directly from the browser address bar, I'll get 304 not modified responses after the first request, so I know the server is sending things back correctly.
Is there a configuration I need to set up to make this happen?
This is a CORS request, but I think that I have and I have exposed the ETag header:
Access-Control-Expose-Headers: ETag
and the Etag header is sent back with the response.

Related

Are preflight requests made for ajax call to same origin domain?

This answer states, that one way X-Requested-With header prevents CSRF attacks is that if server doesn't allow it then a modern browser wont allow javascript code to add this header. And if header is present server can be sure that request didn't originate from another page a user might have opened.
To my understanding the way browser determines whether a custom header is allowed or not in an ajax request is by making a preflight request. And then a server responds with header Access-Control-Allow-Headers. Which contains list of headers allowed for a request in question. So if servers returns an empty list then CORS ajax calls couldn't have xhr header present. Indicating different origin.
So my question is whether preflight request is triggered if origin is the same. Because if they are, then server would say dont add any header, and if browser doesn't then to server a request from its own origin would be indistinguishable from another origin.
So my question is whether preflight request is triggered if origin is the same.
No, it isn't.
Because if they are, then server would say dont add any header, and if browser doesn't then to server a request from its own origin would be indistinguishable from another origin.
The browser not sending a preflight request doesn't stop the server from testing the actual request for a header and throwing an error if it isn't present.

Handling CORS for API that serving ajax call and server to server calls

I'm building an endpoint (let say /v1/getdata). This endpoint will serve a call from both ajax and server to server. Since this endpoint has different origin than the website that will use it (lets say http://www.t.com), i need to implement a CORS for ajax call. I know i must add Access-Control-Allow-Origin: * header to response whenever the request has http://www.t.com in it's Origin header, so the browser will accept ajax call from cross origin.
But server to server call doesn't send Origin header. What is the best approach for this? Should i add Origin header manually into the request from server?
If you are making the API public, then you can simply add Access-Control-Allow-Origin: * to all responses.
If you are making it available to only certain sites, then the logic you should use is:
Is the Origin request header present?
If not, don't add an Access-Control-Allow-Origin response header
Is the Origin one that is on your whitelist of acceptable sites?
If not, don't add an Access-Control-Allow-Origin response header
Otherwise, add an Access-Control-Allow-Origin response header
with a value that matches the Origin request header

Heroku CSRF and POST httpRequest

I have a web crawler on Heroku and I'm trying to call the script from a POST request on Parse Cloud Code httpRequest but I receive a 403 forbidden response basically telling me the Referer Header didn't pass. How can I get past this?
Django's CSRF protection tests the Referer header: see https://docs.djangoproject.com/es/1.9/ref/csrf/#how-it-works. Browsers typically send that header to indicate the page that originated a request, but programmatic user agents don't (cURL, Python requests, and presumably Parse.Cloud.httpRequest) without being told to do so.
To add custom headers to a Parse request, see: Parse.Cloud.httpRequest call with HTTP request header (note the headers object).
That said, you also need to make sure you have a way to get the CSRF token to begin with, and include it either in a XCSRF-Token header or a form field (unclear from your question whether you are doing that).

Does if-no-match need to be set programmatically in ajax request, if server sends Etag

My question is pretty simple. Although while searching over, I have not found a simple satisfying answer.
I am using Jquery ajax request to get the data from a server. Server
hosts a rest API that sets the Etag and Cach-control headers to the GET requests. The Server also sets CORS headers to allow the Etag.
The client of the Api is a browser web app. I am using Ajax request to call the Api. Here are the response headers from server after a simple GET request:
Status Code: 200 OK
Access-Control-Allow-Origin: *
Cache-Control: no-transform, max-age=86400
Connection: Keep-Alive
Content-Encoding: gzip
Content-Type: application/json
Date: Sun, 30 Aug 2015 13:23:41 GMT
Etag: "-783704964"
Keep-Alive: timeout=15, max=99
Server: Apache-Coyote/1.1
Transfer-Encoding: chunked
Vary: Accept-Encoding
access-control-allow-headers: X-Requested-With, Content-Type, Etag,Authorization
access-control-allow-methods: GET, POST, DELETE, PUT
All I want to know is:
Do I need to manually collect the Etag from response headers sent from the server and attach an if-no-match header to ajax request?OR the Browser sends it by-default in a conditional get request when it has an 'Etag'
I have done debugging over the network console in the browser and It
seems the browser is doing the conditional GET automatically and
sets the if-no-match header.
if it is right, Suppose, I created a new resource, and then I called the get request. It gives me the past cached data for the first time. But when I reload the page, It gives the updated one. So I am confused that, If the dataset on the server-side has changed and it sends a different Etag, Why doesn't the browser get an updated data set from the server unless I have to reload
Also in case of pagination. Suppose I have a URL /users?next=0. next is a query param where the value for the next changes for every new request. Since each response will get its own 'Etag'. Will the browser store the 'Etag' based on request or it just stores the lastest Etag of the previous get request, irrespective of the URL.
Well, I have somehow figured out the solution myself:
The browser sends the if-no-match header itself when it sees url had the e-tag header on a previous request. Browser saves the e-tag with respect to that URL, so it does not matter how many requests with different URLs happen.
Also, a trick to force the browser to fetch a conditional-get to check the e-tag:
Set the max-age header to the lowest (for me 60s works great)
once the cache expires, thebrowser will send a conditional-get to check if the expired cached resource is valid. If the if-no-match header matches with e-tag. The server sends the response back with 304: Not-Modified header. This means the expired cached resource is valid and can be used.

What does a proper etag response look like?

We were wondering,
Header wise... What does a proper etag response look like.
Etag response, in the sense that an e-tagged request is made, and yes it matches the etag on our end, thus no content must be sent.
Does it need to contain a content-length header?
Do we use a 304 header response?
Claritifaction:
We want to etag handle via php.
The flow is as follows:
a) Etagged request comes in.
b) PHP checks the etag to see if it meets what we think is a proper condition NOT to send back a full document body.
c) What do we manually send back via php to signal to the browser to use the cached content?
Thanks!
Answered my own question after reading the wiki as lanzz sudgested in the comment above:
"In this subsequent request, the server may now compare the client's
ETag with the ETag for the current version of the resource. If the
ETag values match, meaning that the resource has not changed, then the
server may send back a very short response with an HTTP 304 Not
Modified status. The 304 status tells the client that its cached
version is still good and that it should use that."
So yes, a 304 response is the correct way to answer an etagged request if you want the user agent to use the cached copy.

Resources