Problema CORS en Angular 2 y PHP

publicado por: Anonymous

Tengo un servidor REST para consultas a una base de datos corriendo en PHP, el cual vía GET se pueden consultar varios datos en formato JSON.

Anteriormente existía un cliente en otro servidor escrito en Javascript + JQuery, por lo que necesitaba usar CORS para conectarme a dicho servidor. En ese momento solo hacía falta agregar las siguientes líneas a la página PHP:

<?php
header("Access-Control-Allow-Origin: *");  
header("Content-Type: application/json");

Ahora estoy migrando el cliente a Angular2, pero resulta que al intentar conectarme al mismo servidor rechaza las peticiones CORS.

En principio creo que es del lado del servidor más que del cliente, pero ¿por qué si antes funcionaba ahora dejó de funcionar para Angular2?.

Las peticiones angular son de este tipo:

let headers = new Headers({ 'Content-Type': 'application/json' });
let options = new RequestOptions({ headers: headers });
let url = this.apiHost + '/servicios/';
return this.http.get(url, options).map(response => response.json());

solución

El problema que estás sufriendo es porque la especificación de CORS indica que en las solicitudes simples deben cumplirse las siguientes condiciones:

  • Los únicos métodos aceptados son:

    • GET
    • HEAD
    • POST
  • Aparte de los encabezados establecidos automáticamente por el agente usuario (ej. Connection, User-Agent,etc.), los únicos encabezados que están permitidos para establecer manualmente son:

    • Accept
    • Accept-Language
    • Content-Language
    • Content-Type
  • Los únicos valores permitidos del encabezado Content-Type son:

    • application/x-www-form-urlencoded
    • multipart/form-data
    • text/plain

Las aplicaciones desarrolladas con jQuery cumplen estas condiciones, pero las desarrolladas con Angular no ya que $http cambia la cabecera Content-type a application/json:

The $http service will automatically add certain HTTP headers to all requests. These defaults can be fully configured by accessing the $httpProvider.defaults.headers configuration object, which currently contains this default configuration:

  • $httpProvider.defaults.headers.common (headers that are common for all requests):

    • Accept: application/json, text/plain, */*
  • $httpProvider.defaults.headers.post: (header defaults for POST requests)

    • Content-Type: application/json
  • $httpProvider.defaults.headers.put (header defaults for PUT requests)

    • Content-Type: application/json

En castellano:

El servicio $http agregará automáticamente algunas cabeceras HTTP a todas las peticiones. Pueden ser completamente configuradas a través del objeto de configuración $httpProvider.defaults.headers, que actualmente contiene esta configuración por defecto:

  • $httpProvider.defaults.headers.common (cabeceras comunes para todas las peticiones):

    • Accept: application/json, text/plain, */*
  • $httpProvider.defaults.headers.post: (cabecera por defecto para las peticiones POST)

    • Content-Type: application/json
  • $httpProvider.defaults.headers.put (cabecera por defecto para las peticiones PUT)

    • Content-Type: application/json

Así que, como mínimo, debes agregar esto a tu código PHP para que permita dicho cambio realizado por Angular:

<?php
header('Access-Control-Allow-Headers: Content-Type');

Autorizando explícitamente la cabecera Content-Type se podrá usar cualquier valor más allá de los permitidos inicialmente (application/x-www-form-urlencoded, multipart/form-data y text/plain).

Respondido por: Anonymous

Leave a Reply

Your email address will not be published. Required fields are marked *