web-dev-qa-db-fra.com

Les ouvriers de service peuvent-ils cacher POST demandes?

J'ai essayé de mettre en cache une demande POST dans un service worker sur un événement d'extraction.

J'ai utilisé cache.put(event.request, response), mais la promesse retournée a été rejetée avec TypeError: Invalid request method POST..

Lorsque j'ai essayé de frapper la même POST API, caches.match(event.request) me donnait undefined.

Mais lorsque j'ai fait la même chose pour les méthodes GET, cela a fonctionné: caches.match(event.request) pour une demande GET me donnait une réponse.

Les employés de service peuvent-ils mettre en cache des demandes POST??

15
Aniket

Vous ne pouvez pas mettre en cache les demandes POST à l'aide de l'API de cache. Voir https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#cache-put-method (point 2.2).

Il y a une discussion connexe dans le référentiel de spécifications: https://github.com/slightlyoff/ServiceWorker/issues/693

Une solution intéressante est celle présentée dans le livre de recettes ServiceWorker: https://serviceworke.rs/request-deferrer.html En gros, la solution sérialise les demandes adressées à IndexedDB.

20
Marco

J'ai utilisé la solution suivante dans un projet récent avec une API GraphQL: J'ai mis en cache toutes les réponses des routes d'API dans une librairie IndexedDB en utilisant une représentation sérialisée de la requête en clé cache. Ensuite, j'ai utilisé le cache comme solution de secours si le réseau n'était pas disponible:

// ServiceWorker.js
self.addEventListener('fetch', function(event) {
    // We will cache all POST requests to matching URLs
    if(event.request.method === "POST" || event.request.url.href.match(/*...*/)){
        event.respondWith(
            // First try to fetch the request from the server
        fetch(event.request.clone())
            // If it works, put the response into IndexedDB
            .then(function(response) {
                // Compute a unique key for the POST request
                var key = getPostId(request);
                // Create a cache entry
                var entry = {
                    key: key,
                    response: serializeResponse(response),
                    timestamp: Date.now()
                };

                /* ... save entry to IndexedDB ... */

                // Return the (fresh) response
                return response;
            })
            .catch(function() {
                // If it does not work, return the cached response. If the cache does not
                // contain a response for our request, it will give us a 503-response
                var key = getPostId(request);
                var cachedResponse = /* query IndexedDB using the key */;
                return response;
            })
        );
    }
})

function getPostId(request) {
    /* ... compute a unique key for the request incl. it's body: e.g. serialize it to a string */
}

Voici le code complet pour ma solution spécifique utilisant Dexie.js comme IndexedDB-wrapper. Sentez-vous libre de l'utiliser!

3
A. Kabachnik

Si vous parlez de données de formulaire, vous pouvez alors intercepter l'événement fetch et lire les données de formulaire de la même manière que ci-dessous, puis enregistrer les données dans indexedDB.

//service-worker.js
self.addEventListener('fetch', function(event) {
      if(event.request.method === "POST"){
         var newObj = {};

               event.request.formData().then(formData => {

                for(var pair of formData.entries()) {
                  var key = pair[0];
                  var value =  pair[1];
                  newObj[key] = value;
                }

              }).then( ...save object in indexedDB... )
      }
})
0
Roman Gherta