web-dev-qa-db-fra.com

Aucun en-tête 'Access-Control-Allow-Origin' n'est présent sur la ressource demandée, lors de la tentative d'obtention des données d'un REST API

J'essaie d'extraire des données de l'API REST de HP Alm. Cela fonctionne plutôt bien avec un petit script curl - je récupère mes données.

Maintenant, faire cela avec JavaScript, fetch et ES6 (plus ou moins) semble être un problème plus important. Je continue à recevoir ce message d'erreur:

L'API d'extraction ne peut pas être chargée. La réponse à la demande de contrôle en amont ne le fait pas passer le contrôle de contrôle d'accès: aucun en-tête 'Access-Control-Allow-Origin' n'est présent sur la ressource demandée. Origin ' http://127.0.0.1:3000 ' est donc pas autorisé l'accès. La réponse avait le code d'état HTTP 501 . Si une réponse opaque répond à vos besoins, définissez le mode de la demande sur 'no-cors' pour récupérer la ressource avec CORS désactivé.

Je comprends que c'est parce que j'essaye d'extraire ces données de mon hôte local et que la solution devrait utiliser CORS. Maintenant, je pensais l'avoir fait, mais d'une manière ou d'une autre, cela ignore ce que j'écris dans l'en-tête ou le problème est autre chose? 

Alors, y a-t-il un problème de mise en œuvre? Est-ce que je me trompe? Je ne peux malheureusement pas vérifier les journaux du serveur. Je suis vraiment un peu coincé ici.

function performSignIn() {

  let headers = new Headers();

  headers.append('Content-Type', 'application/json');
  headers.append('Accept', 'application/json');

  headers.append('Access-Control-Allow-Origin', 'http://localhost:3000');
  headers.append('Access-Control-Allow-Credentials', 'true');

  headers.append('GET', 'POST', 'OPTIONS');

  headers.append('Authorization', 'Basic ' + base64.encode(username + ":" + password));

  fetch(sign_in, {
      //mode: 'no-cors',
      credentials: 'include',
      method: 'POST',
      headers: headers
    })
    .then(response => response.json())
    .then(json => console.log(json))
    .catch(error => console.log('Authorization failed : ' + error.message));
}

J'utilise Chrome. J'ai également essayé d'utiliser ce plug-in Chrome CORS, mais je reçois un autre message d'erreur:

La valeur de l'en-tête 'Access-Control-Allow-Origin' dans la réponse ne doit pas être le caractère générique '*' lorsque le mode d'identification de la demande est 'comprendre'. Origin ' http://127.0.0.1:3000 ' n'est donc pas autorisé accès. Le mode des informations d'identification des demandes initiées par le XMLHttpRequest est contrôlé par l'attribut withCredentials.

183
daniel.lozynski

Cette erreur se produit lorsque l'URL du client et l'URL du serveur ne correspondent pas, y compris le numéro de port. Dans ce cas, vous devez activer votre service pour CORS, qui est un partage de ressources inter-origines.

Si vous hébergez un service Spring REST, vous pouvez le trouver dans l'article de blog Prise en charge de CORS dans Spring Framework.

Si vous hébergez un service utilisant un serveur Node.js, alors

  1. Arrêtez le serveur Node.js.
  2. npm installer cors
  3. Ajouter les lignes suivantes à votre server.js

    var cors = require('cors')
    
    app.use(cors()) // Use this after the variable declaration
    
39
Rakesh

Le problème est dû au fait que vous avez ajouté le code suivant en tant qu’en-tête requête dans votre interface utilisateur:

headers.append('Access-Control-Allow-Origin', 'http://localhost:3000');
headers.append('Access-Control-Allow-Credentials', 'true');

Ces en-têtes appartiennent à réponse, pas à une requête. Donc, remove eux, y compris la ligne: 

headers.append('GET', 'POST', 'OPTIONS');

Votre demande avait 'Content-Type: application/json', ce qui a déclenché ce qu'on appelle le contrôle en amont de CORS. Cela a causé le navigateur a envoyé la demande avec la méthode OPTIONS. Voir CORS preflight pour des informations détaillées. 
Par conséquent, dans votre back-end, vous devez gérer cette demande de contrôle en amont en renvoyant les en-têtes de réponse, notamment:

Access-Control-Allow-Origin : http://localhost:3000
Access-Control-Allow-Credentials : true
Access-Control-Allow-Methods : GET, POST, OPTIONS
Access-Control-Allow-Headers : Origin, Content-Type, Accept

Bien entendu, la syntaxe réelle dépend du langage de programmation que vous utilisez pour votre back-end.

Dans votre front-end, ça devrait être comme ça:

function performSignIn() {
    let headers = new Headers();

    headers.append('Content-Type', 'application/json');
    headers.append('Accept', 'application/json');
    headers.append('Authorization', 'Basic ' + base64.encode(username + ":" +  password));
    headers.append('Origin','http://localhost:3000');

    fetch(sign_in, {
        mode: 'cors',
        credentials: 'include',
        method: 'POST',
        headers: headers
    })
    .then(response => response.json())
    .then(json => console.log(json))
    .catch(error => console.log('Authorization failed : ' + error.message));
}
1
Lex Soft

Utiliser dataType: 'jsonp' a fonctionné pour moi.

   async function get_ajax_data(){
       var _reprojected_lat_lng = await $.ajax({
                                type: 'GET',
                                dataType: 'jsonp',
                                data: {},
                                url: _reprojection_url,
                                error: function (jqXHR, textStatus, errorThrown) {
                                    console.log(jqXHR)
                                },
                                success: function (data) {
                                    console.log(data);

                                    // note: data is already json type, you
                                    //       just specify dataType: jsonp
                                    return data;
                                }
                            });


 } // function               
0
hoogw

Enlève ça:

credentials: 'include',
0
Nalan Madheswaran

Dans mon cas, le serveur Web a empêché la méthode "OPTIONS"

Vérifiez votre serveur Web pour la méthode des options

J'utilise "webtier"

/www/webtier/domains/[domainname]/config/fmwconfig/components/OHS/VCWeb1/httpd.conf

<IfModule mod_rewrite.c>
  RewriteEngine on
  RewriteCond %{REQUEST_METHOD} ^OPTIONS
  RewriteRule .* . [F]
</IfModule>

changer à

<IfModule mod_rewrite.c>
  RewriteEngine off
  RewriteCond %{REQUEST_METHOD} ^OPTIONS
  RewriteRule .* . [F]
</IfModule>
0
Juneho Nam

Juste mes deux cents ... en ce qui concerne Comment utiliser un proxy CORS pour contourner les problèmes "Pas d’en-tête de contrôle d’accès-Autoriser-Origine"

Pour ceux d'entre vous qui travaillent avec php sur le backend, déployer un "proxy CORS" est aussi simple que:

  1. créez un fichier nommé 'no-cors.php' avec le contenu suivant:

    $ URL = $ _GET ['url']; echo json_encode (file_get_contents ($ URL)); mourir();

  2. sur votre front, faites quelque chose comme:

    fetch (' https://example.com/no-cors.php ' + '? url =' + url) .then (response => {/Réponse de traitement/})

0
Yair Levy

Je travaillais avec Spring REST et je l'ai résolu en ajoutant les AllowedMethods au WebMvcConfigurer.

@Value( "${app.allow.origins}" )
    private String allowOrigins;    
@Bean
public WebMvcConfigurer corsConfigurer() {
            System.out.println("allow Origin: "+allowOrigins);
            return new WebMvcConfigurerAdapter() {
                @Override
                public void addCorsMappings(CorsRegistry registry) {
                    registry.addMapping("/**")
                    //.allowedOrigins("http://localhost")
                    .allowedOrigins(allowOrigins)
                    .allowedMethods("PUT", "DELETE","GET", "POST");
                }
            };
        }
0
Jorge Dominguez