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.
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
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 .
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.
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:
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 => {...}
);
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');