Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow Caching of POST requests #977

Open
devd opened this issue Sep 13, 2016 · 26 comments
Open

Allow Caching of POST requests #977

devd opened this issue Sep 13, 2016 · 26 comments

Comments

@devd
Copy link

devd commented Sep 13, 2016

(not sure if this is separate from #693 )

https://w3c.github.io/ServiceWorker/#cache-addAll-method doesn't allow storing POST responses in the cache. Not sure why; particularly for same-origin POSTs. Allowing POSTs makes it easy to start using service worker for more requests.

@jakearchibald
Copy link
Contributor

I'm pretty open to adding this. We removed it from v1 plans to make implementation easier. What's your use-case out of curiosity?

@NekR
Copy link

NekR commented Sep 14, 2016

@jakearchibald it's allowed to cache POST requests with cache.put() right? Why have it in addAll()?

@devd do you need to handle/cache POST requests on install, e.g. on precache stage?

@jakearchibald
Copy link
Contributor

@NekR

it's allowed to cache POST requests with cache.put() right? Why have it in addAll()?

No, only GET requests are allowed in the cache currently.

@wanderview
Copy link
Member

Without changing cache.match() allowing POST is a footgun. The matching algorithm does not take anything like body into account. Is that obvious to someone passing a POST to cache.put()? I don't know.

Also, I don't think http cache handles POST and previously we've tried to maintain parity with whats supported there.

@asutherland
Copy link

Presumably the use-case for storing POST would be: app is offline, wants to make this POST when it comes online. It sounds like the under-discussion background-fetch idea might be a better place for that use-case, since it's explicitly about fetches and we explicitly want to be able to enumerate pending fetches, etc. (Whereas DOM Cache is about local at-rest storage.)

@devd
Copy link
Author

devd commented Sep 14, 2016

Security hygiene also suggests using POST for many requests that can be GETs to ensure that sensitive data is not in URIs and provide the usual CSRF protections for endpoints (even if they are not state changing. See the cross origin JSON leakage bug.) Thus, moving to service worker becomes a bit more painful since many POSTs are eminently cacheable.

@delapuente
Copy link

@asutherland you can take a look at that use case at https://serviceworke.rs/request-deferrer/ it seems like a ongoing cache but don't know the specific use cases discouraging this.

@jakearchibald
Copy link
Contributor

Background sync is ideal for the above, but I don't see how adding post requests into the cache would make this easier.

@nolanlawson
Copy link
Member

This could be useful for CouchDB because often POST messages are used in place of GETs where you simply want to be able to pass more parameters in a body than would be possible/ergonomic with query string params, e.g. the _all_docs API.

@wanderview
Copy link
Member

This could be useful for CouchDB because often POST messages are used in place of GETs where you simply want to be able to pass more parameters in a body than would be possible/ergonomic with query string params, e.g. the _all_docs API.

Are all these requests interchangeable? Normally we would perform cache matching on the GET query string to distinguish between them. With POST the requests will overwrite each other without regard to different bodies.

We really need to define the matching semantics for POST requests in order to move forward here, IMO.

@stnwk
Copy link

stnwk commented Sep 21, 2016

Would also be a huge benefit for (web) apps using apollo-stack and GraphQL, as the apollo-server v0.2+ only accepts POST requests.

@jakearchibald
Copy link
Contributor

I'm not massively keen on adding body-based matching semantics to the cache API.

Would it help if we allowed requests (and I guess responses) to be stored in indexeddb? It doesn't help the Couch case, but what about the others?

@eoyleralz
Copy link

eoyleralz commented Apr 11, 2017

I'm running into this issue as well. I utilize third-party APIs for my PWA for our fundraising participant center app (see API doc is at http://open.convio.com/api/#teamraiser_api for examples), and although a handful of APIs allow for GET requests, most require POST (for simplicity, we handle everything in POST because of this fact). I'm guessing it's due to the size of the request, security, or a combo of the two that the provider mostly only supports POST. For our PWA (alz.org/walk, must be registered to log into the PWA), I am able to cache all the static responses so the app can load offline, but I can't access any of the pertinent data (fundraising amount, gifts, contacts, personal page content...) while offline because that data sits behind a POST request. If POST responses can't be cached from the service worker, then I'm guessing I have to handle this within the app - if online, translate the data from POST responses inside the app into a JSON object and then save that JSON object in IDB, and then when offline, have the service worker send a response to notify the app to pull from IDB rather than look to the response? Seems like a messy solution (caching some data via service worker, and other data via app), but I'm at a loss until the service worker can cache the POST responses. Am I missing something more obvious? It just seems that the idea that POST is only used for pushing data to the server isn't valid, as in my example, stnwk's apollo example, and nolanlawson's Couch example.

Though, I now see the dilemma that wanderview presents - how to match on a POST request is imperative.

@delapuente
Copy link

delapuente commented Apr 12, 2017

What about opting in for body-based matching semantics?

var matching = await cache.match(postRequest, { matchBody: true });

@MorganConrad
Copy link

For a request-deferrer like case, it would be ideal to be able to cache.put() a POST (or any method) into a cache, and I don't care about matching, since they will be put into a special cache named "XXX_DEFERRED", and retrieval will be via cache.keys(). This would make it simple (just remember to clone()) to record and then retry failed requests. Indexed Storage is overkill (and a real hassle) for this simple use case. e.g., ServiceWorke.rs Request Deferrer example using localforage.js

@jakearchibald
Copy link
Contributor

@MorganConrad given that the cache API is a request/response pair, which response would you cache in this case?

@MorganConrad
Copy link

@jakearchibald Is a null response legal in the cache? If not, the original request attempt probably created a "sorry you are offline" response, so that would do.

@EricOyler
Copy link

One more idea on POST body matching... What about using a checksum? Then you don't have to worry about the details of the POST body, you just run a checksum function and store that on the URL in the cache, and then when matching you're just comparing URL and checksum. For example, when I make any of my TeamRaiserCR API method calls, the URL is https://act.alz.org/site/CRTeamraiserAPI, but the checksum would be different for different POST parameters, so I might have in cache requests for https://act.alz.org/site/CRTeamraiserAPI:151, https://act.alz.org/site/CRTeamraiserAPI:193, https://act.alz.org/site/CRTeamraiserAPI:2391, where the number after the colon is the checksum number. Would that be simple and efficient enough to support POST body matching without having to know the exact details of the body contents?

@joewoodhouse
Copy link

Our usecase is caching GraphQL requests which some servers dictate must be POST requests with query in the body.

@anirvann
Copy link

Our usecase is caching GraphQL requests which some servers dictate must be POST requests with query in the body.

The GraphQL servers by default use POST, but GET is also allowed.
PFB link:
https://graphql.org/learn/serving-over-http/

Apollo is better at this and easily lets you perform GET requests. Mutations however arent allowed over GET but IMHO, no point in caching mutations.

@iamsank8
Copy link

I have a use case where I don't use query parameters in GET request, rather I provide model with data in POST. I get response for these APIs. Since many of the developers have these kinds of structure, it will be highly appreciated by the community.

@sameerbakre
Copy link

It would be immensely helpful if POST requests can be cached as most of the GET calls are done using POST requests with parameters in the body.

@jtsmedley
Copy link

Use case: post requests contain our api queries to ensure our queries aren’t exposed in network logging. We maintain a shared state for our application caching so we could even do it based on an Etag.

Please and thank you with tons of cherries on top.

@valgussev
Copy link

valgussev commented Feb 20, 2020

We are also interested in POST requests caching since most of the GET requests have been converted to POST due to security issues mentioned above and url length restrictions in passing query parameters.

@ciekawy
Copy link

ciekawy commented Aug 23, 2020

what about possible convention to expect some query param like swPostCacheKey? this might help in cases like GraphQL conditionally enabling cache usage where the state management layer can provide compact keys and ensure the meaningful part of the POST value to be included in cache.

@nnmrts
Copy link

nnmrts commented Nov 17, 2022

What is the way forward or progress here, if there is any? Looking forward to get this added and willing to help if possible.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests