web-dev-qa-db-fra.com

Angular2 Headers

Lorsque j'appelle un serveur sans en-têtes, il fonctionne et le serveur renvoie json:

this.http.get(url)

mais quand j'ajoute en-tête:

var headers = new Headers({'x-id': '1'});
this.http.get(url, {'headers': headers})

le navigateur renvoie une erreur:

XMLHttpRequest cannot load http://domain/api/v1/. Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:3000' is therefore not allowed access.

J'ai également essayé d'ajouter l'en-tête Origin - Erreur de navigateur: Refused to set unsafe header "Origin"

Et en-tête Access-Control-Allow-Origin - pas d'effet


Sur le serveur (Laravel), j'ai créé le middleware Cors.php:

<?php

namespace App\Http\Middleware;

use Closure;

class Cors {
    public function handle($request, Closure $next)
    {
        return $next($request)
            ->header('Access-Control-Allow-Origin', 'http://localhost:3000')
            ->header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS')
            ->header('Access-Control-Allow-Headers', 'x-id');
    }
}

Je suis nouveau dans les demandes angular2 et CORS, je ne sais pas quoi faire.

  • Angular: 2.0.0-beta.0 
  • Laravel: 5.0 
  • Navigateur: Google Chrome
15
Shaddow

Une demande de contrôle en amont avec CORS signifie qu'une demande HTTP d'OPTIONS est exécutée avant la demande réelle. Vous passez d'une simple requête à une autre puisque vous ajoutez un en-tête personnalisé dans le cas d'une méthode GET. Ce lien pourrait vous aider à comprendre ce qui se passe: http://restlet.com/blog/2015/12/15/understanding-and-using-cors/ .

Pour votre information, l'en-tête Origin est automatiquement ajouté par le navigateur lors de l'exécution d'une requête interdomaine.

Je pense que votre problème est dans l'en-tête Access-Control-Allow-Origin. Vous devez définir l'hôte qui passe l'appel et non l'adresse du serveur. Vous devriez plutôt avoir ceci (si votre application Angular2 s'exécute sur localhost:8080):

return $next($request)
        ->header('Access-Control-Allow-Origin', 'http://localhost:8080')
        ->header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS')
        ->header('Access-Control-Allow-Headers', 'x-id');

J'espère que ça vous aidera, Thierry

7
Thierry Templier

J'ai eu le même problème dans mon application Angular2. Le problème, comme déjà indiqué, est qu'avant chaque demande faite par le client, une demande de contrôle en amont est envoyée au serveur.

Ce type de requête a pour typeOPTIONS, et il incombe au serveur de renvoyer une réponse preflight avec l’état 200 et les en-têtes définis pour accepter les demandes de ce client.

Voici ma solution (avec express):

// Domain you wish to allow
res.setHeader('Access-Control-Allow-Origin', 'http://localhost:3000');

// Request methods you wish to allow
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE');

// Request headers you wish to allow
res.setHeader('Access-Control-Allow-Headers', 'YOUR-CUSTOM-HEADERS-HERE');

// Set to true if you need the website to include cookies in  requests
res.setHeader('Access-Control-Allow-Credentials', true);

// Check if Preflight Request
if (req.method === 'OPTIONS') {
    res.status(200);
        res.end();
}
else {
    // Pass to next layer of middleware
    next();
}

De cette manière, le client sera autorisé et vous pourrez définir vos en-têtes personnalisés dans toutes les demandes. Dans votre cas, vous devrez définir x-id dans l'option Access-Control-Allow-Headers .

6
Matteo Tosi

J'ai développé une application angular2 avec un back-end c# web api et j'ai également rencontré un problème avec les paramètres cors

Le vrai problème ne s’est pas avéré être les paramètres cors, mais plutôt les données envoyées à l’API (js date date to c # datetime type ne s’alignait pas correctement). Cependant, dans votre cas, est-il absolument essentiel de passer l'identifiant x-id dans l'en-tête plutôt que comme paramètre de la requête? Par exemple, vous pourriez faire quelque chose comme ça: 

getYourDataType(id: number): Observable<YourDataType> {
    return this.http.get(url + '/' + id.toString())
        .map((response: Response) => <YourDataType>response.json());

D'après mes recherches après avoir traité ce problème, il semblerait que angular essaie de trouver le point de terminaison que vous essayez d'atteindre, échoue, puis suppose que la raison doit être due à quelque chose qui ne va pas avec les paramètres cors, plutôt que les données côté client.

Vous avez dit que l'API renvoie des données lorsque vous ne définissez aucun en-tête dans votre demande. Par conséquent, si le passage d'un en-tête à un paramètre ne fonctionne pas, vous pouvez essayer d'inspecter la demande à l'aide d'un outil comme fiddler ou de l'onglet réseau de Chrome. dev et voyez si, angulairement, chaque requête est construite comme vous le souhaitez. Ou en comparant les résultats en construisant manuellement une requête dans Fiddler, il pourrait être très éclairant de savoir ce qui se passe exactement pour vous donner cette réponse inattendue. 

Quoi qu'il en soit, il est assez difficile de déterminer qu'il existe un problème avec vos données, plutôt que les paramètres cors. Angular vous incite-t-il à chercher une solution totalement fausse pour tenter de résoudre un problème très simple. J'espère que cela aide quelqu'un.

1
OrbitalSloth

Dans votre cas, le serveur doit répondre à la requête de contrôle en amont avec les en-têtes suivants:

Access-Control-Allow-Origin: *

Méthodes X-Custom-HeaderAccess-Control-Allow: GET, POST, PUT, DELETE

En-têtes de contrôle d'accès autorisés : x-id

Notez que pour l'en-tête Access-Control-Allow-Origin HTTP, il est recommandé de définir le domaine dans lequel l'application angular2 est hébergée explicitement au lieu de *, qui n'est nécessaire que pour les API publiques non contrôlées. tous les consommateurs! 

Je vous recommande fortement de lire l'article suivant sur CORS: 

http://www.html5rocks.com/en/tutorials/cors/

1
Daniel Gartmann

Essayez de suivre le code, cela devrait fonctionner

let headers = new Headers();
headers.append('Accept', 'application/json');
headers.append('Content-Type', 'application/json');
headers.append('x-id','1');
this.http.get(url, {'headers': headers}).subscribe(
  response => {...},
  error => {...}
);
0
Akhilesh Kumar

le problème est que vous devez également définir les en-têtes autorisés. C'est pourquoi ça ne marche pas. Pour que cela fonctionne avec une simple requête http angular2, vous devez ajouter les en-têtes suivants:

    header('Access-Control-Allow-Origin: *');
    header("Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept"); // In your case also add x-id or what you are also using. 
    header('Access-Control-Allow-Methods: POST, PUT, DELETE, GET, OPTIONS');
0
G.T.