web-dev-qa-db-fra.com

Faire des demandes d'API CORS avec create-react-app et webpack - pas d'express

J'essaie de faire des appels API sans désactiver CORS dans mon navigateur. L'application a été créée à l'aide de react-create-app. Il utilise webpack et webpackDevServer pour dev. Toutes les réponses que j'ai trouvées ici disent de mettre le code suivant dans mon webpack.config fichier.

devServer: {
      headers: {
        "Access-Control-Allow-Origin": "*",
        "Access-Control-Allow-Methods": "GET, POST, PUT, DELETE, PATCH, OPTIONS",
        "Access-Control-Allow-Headers": "X-Requested-With, content-type, Authorization"
      }
  }

Cependant, je l'ai essayé dans un certain nombre d'endroits différents et cela ne fonctionne pas.

Je continue à recevoir l'erreur:

Impossible de charger la ressource: le serveur a répondu avec un état de 500 ()

et

Échec du chargement ... La réponse à la demande de contrôle en amont ne réussit pas la vérification du contrôle d'accès: aucun en-tête 'Access-Control-Allow-Origin' n'est présent sur la ressource demandée. L'origine ' http: // localhost: 30 ' n'est donc pas autorisée à accéder. La réponse avait le code d'état HTTP 500.

J'ai également tenté de changer mes appels d'appels axios pour récupérer des appels

return fetch(process.env.REACT_APP_API_URL + "/prod/user", {
    mode: 'no-cors',
    credentials: 'include',
    method: "GET",
    headers: {
        "x-api-key": process.env.REACT_APP_API_KEY
    }
})
.then(response => {
   return response.json()
})
.then(resp => dispatch(receiveUsers(resp.data)))
.catch(error => {console.log(error)})

Cela m'a rapproché mais la console revient maintenant

Response {type: "opaque", url: "", redirected: false, status: 0, ok: false, …}

Comment contourner ce problème CORS? Merci d'avance pour votre aide!

En-têtes de réponse/demande

4
Tim

Le fait que vous voyez une réponse 500 à la demande OPTIONS de contrôle en amont me fait penser que la méthode de demande OPTIONS n'est peut-être tout simplement pas autorisée par le serveur Web.

Par défaut, de nombreux serveurs Web n'autorisent que HEAD, GET et POST, ce serait donc la première chose que je vérifierais.

Si cela n'aide pas, assurez-vous que les éléments ci-dessus webpack.config le code s'exécute pour toutes les demandes (c'est-à-dire pour les OPTIONS et GET/POST).

Si cela ne vous aide pas, publiez un ensemble complet d'en-têtes de demande et de réponse à la fois aux OPTIONS et à la demande GET, et voyons où nous allons.

1
roryhewitt

Je ne peux pas encore ajouter de commentaire, je vais donc le mettre comme réponse.

Si vous essayez d'accéder à une API servie par une autre application de nœud ou à partir d'un autre hôte. Vous pouvez configurer webpack-dev-server pour proxy cette demande au serveur réel.

Consultez le Créer React App Doc: Demandes d'API proxy en développement pour plus de détails.

3
loveky

la meilleure option est d'utiliser un proxy, surtout si vous utilisez des API externes ou plusieurs API. Installez simplement proxy-middleware Et créez le fichier src/setupProxy.js Et à l'intérieur du fichier, vous pouvez ajouter un code similaire à ceci:

const proxy = require('proxy-middleware');

module.exports = app => {
  // setup proxies
  // 1st api
  app.use("/etherscan", proxy("http://api.etherscan.io/api"));
  // 2nd api
  app.use("/cryptocompare", proxy("https://min-api.cryptocompare.com/data"));

  // Note: setupProxy is an express server so you can also override anything in the req or res before proxy them for example 
  app.use("/cryptocompare", (req,res,next) => {
     req.headers = { 
        ...req.headers,
        "my-header":"my header value"
     }
     return proxy("https://min-api.cryptocompare.com/data")(req,res,next);
  });

  app.use("/cryptocompare", proxy("https://min-api.cryptocompare.com/data"));


  // also it's better to use .env variables
  // const {REACT_APP_API_ETHERSCAN_PROXY, REACT_APP_API_ETHERSCAN_BASE_URL} = process.env;
  // app.use(REACT_APP_API_ETHERSCAN_PROXY, REACT_APP_API_ETHERSCAN_BASE_URL);      
};

Et pour votre API, il est également préférable que vous puissiez obtenir l'URL de base à partir de variables .env, par exemple:

const {REACT_APP_API_ETHERSCAN_PROXY, REACT_APP_API_ETHERSCAN_BASE_URL} = process.env;
const baseURL = REACT_APP_API_ETHERSCAN_PROXY || REACT_APP_API_ETHERSCAN_BASE_URL;

Conseil supplémentaire: au lieu de continuer à transmettre process.env.REACT_APP_API_URL et les en-têtes pour chaque appel d'API, vous pouvez jeter un œil à axios où vous pouvez créer une instance d'API avec des propriétés par défaut, par exemple:

const {
  REACT_APP_API_ETHERSCAN_PROXY, 
  REACT_APP_API_ETHERSCAN_BASE_URL,
  REACT_APP_API_TIMEOUT,
  REACT_APP_API_ETHERSCAN_KEY
} = process.env;

export const etherscanAPI = axios.create({
  "baseURL": REACT_APP_API_ETHERSCAN_PROXY || REACT_APP_API_ETHERSCAN_BASE_URL,
  "timeout": parseInt(REACT_APP_API_TIMEOUT),
  "headers": {
    "X-Requested-With": "XMLHttpRequest"
  },
  "params": {
    "apiKey": REACT_APP_API_ETHERSCAN_KEY
  }
});

puis etherscanAPI.get("/whatever")

1
Fareed Alnamrouti