web-dev-qa-db-fra.com

Le POST sur une API externe lance CORS mais cela fonctionne à partir de Postman

J'utilise l'i mgur api pour télécharger des images via une application node js.

Je convertis des images en chaînes de base64 et les envoie via Postman fonctionne très bien.

J'utilise node-fetch pour passer des appels API.

const fetch = require('node-fetch')
...
async uploadImage(base64image) {
        try {
            const url = 'https://api.imgur.com/3/image'
            const res = await fetch(url,
                {
                    method: 'POST',
                    body: { image: base64image },
                    headers: {
                        'content-type': 'application/json',
                        'Authorization': 'Client-ID [my-client-id]',
                        'Access-Control-Allow-Headers': 'Content-Type, Authorization, Access-Control-Allow-Headers',
                        'Access-Control-Allow-Methods': 'POST',
                    }
                }
            )

            console.log(res)
        } catch(err) {
            console.log(err)
        }
    }

Erreur : accès à récupérer à ' https://api.imgur.com/3/image ' à partir de l'origine '- http: // localhost: 30 'a été bloqué par la stratégie CORS: le champ d'en-tête de demande Access-Control-Allow-Headers est non autorisé par Access-Control-Allow-Headers dans la réponse de contrôle en amont.

J'ai essayé de nombreux en-têtes 'Access-Control-Allow-xxx' mais aucun d'entre eux n'a fonctionné ..

Je suppose que ce doit être quelque chose de simple qui me manque. Je suis coincé là-dessus depuis des heures s'il vous plaît, aidez-moi.

4
Cristian G

C'est parce que Access-Control-Allow-Headers, Access-Control-Allow-Methods sont les en-têtes utilisés par le serveur. Le serveur ajoute l'en-tête par un middleware.

Maintenant, imaginez dans le serveur (dans cet exemple ci-dessous un serveur express) avec CORS activé ce type d'en-têtes (par défaut) sont définis:

app.use(function (req, res, next) {
    res.header('Access-Control-Allow-Origin', '*');
    res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS');
    res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization, Content-Length, X-Requested-With, Accept');
});

Et vous envoyez Access-Control-Allow-Headers du côté client, et le serveur voit cela comme un en-tête qui n'est pas sur liste blanche.

Donc, dans les en-têtes, utilisez-les:

headers: {
    'content-type': 'application/json',
    'Authorization': 'Client-ID [my-client-id]'
}

Cela devrait bien fonctionner.

Btw, je pense que cela fonctionne avec le facteur parce que:

  • Postman ne peut pas définir certains en-têtes si vous n'installez pas cette petite extension de capture de postman.
  • La sécurité du navigateur arrête les demandes d'origine croisées. Si vous désactivez la sécurité chrome, il fera très bien toute demande CORS.

En outre, selon this :

Je pense que cela pourrait être dû au fait que Chrome ne prend pas en charge localhost pour passer par le Access-Control-Allow-Origin - voir Chrome

Pour avoir Chrome envoyer Access-Control-Allow-Origin dans l'en-tête, alias juste votre hôte local dans votre fichier/etc/hosts vers un autre domaine, comme:

127.0.0.1   localhost yourdomain.com

Ensuite, si vous souhaitez accéder à votre script à l'aide de yourdomain.com au lieu de localhost, l'appel devrait réussir.

Remarque: je ne pense pas que le type de contenu devrait être application/json ça devrait être comme image/jpeg ou quelque chose. Ou peut-être ne pas inclure cet en-tête si cela ne fonctionne pas.

5
Aritra Chakraborty

Le navigateur restreint les requêtes HTTP au même domaine que votre page Web, vous ne pourrez donc pas accéder à imi api directement depuis le navigateur sans rencontrer le problème CORS.

Je convertis des images en chaînes de base64 et les envoie via Postman fonctionne très bien.

En effet, Postman n'est pas un navigateur et n'est donc pas limité par la politique CORS.

J'ai essayé de nombreux en-têtes "Access-Control-Allow-xxx" mais aucun d'entre eux n'a fonctionné ..

Ces en-têtes doivent être retournés par le serveur en réponse - dans votre cas par le serveur imgur. Vous ne pouvez pas les définir dans la demande du navigateur, cela ne fonctionnera donc jamais.

Erreur: l'accès à récupérer à ' https://api.imgur.com/3/image ' à partir de l'origine ' http: // localhost: 30 ' a été bloqué par Stratégie CORS: le champ d'en-tête de demande Access-Control-Allow-Headers n'est pas autorisé par Access-Control-Allow-Headers dans la réponse de contrôle en amont.

Solutions possibles à votre problème:

  1. Si vous avez accès à l'API backend, vous pouvez définir l'en-tête "Access-Control-Allow-Origin" sur le serveur et laisser votre application accéder à l'API - mais comme vous n'aurez pas accès au serveur Imgur - vous pouvez probablement '' t faire ça.

  2. Désactivez CORS dans le navigateur - vous pouvez utiliser un plugin comme: https://chrome.google.com/webstore/detail/allow-control-allow-origi/nlfbmbojpeacfghkpbjhddihlkkiljbi?hl=en . Cette solution de contournement devrait convenir au développement. Le plugin désactivera vos paramètres CORS et vous pourrez frapper imgur apis.

  3. La troisième solution utilise un proxy. Vous pouvez configurer un petit serveur de noeud à l'aide d'Express. Vous atteindrez alors votre propre serveur de noeud, qui à son tour atteindra l'api imgur. Comme le serveur de nœuds n'est pas un environnement de navigateur, il n'aura aucun problème CORS et vous pourrez accéder à l'API imgur de cette façon. C'est également la raison pour laquelle vous avez pu accéder à l'API de Postman sans aucun problème. Comme Postman n'est pas un environnement de navigateur, il n'est pas limité par la politique CORS.

2
Jatin Gupta