AngularJS: OPCIONES de comprobación preliminar de la llamada anterior de $http.solicitud post

Estoy usando AngularJS v1.2.4.

Tuve un problema con Angular envío de una comprobación preliminar de las OPCIONES de llamada (Chrome se muestra las OPCIONES de llamada como «cancelado») y lo resolvió con:

$httpProvider.defaults.useXDomain = true;
delete $httpProvider.defaults.headers.common['X-Requested-With'];

Que trabajado toda mi $recurso de llamadas, y todo era bueno.

Ahora estoy tratando de implementación de la autenticación, y una página de inicio de sesión que envía una petición POST a mi servidor con las credenciales del usuario. Estoy viendo el problema que se enfrenta antes, pero $recursos llamadas todavía están trabajando bien.

Lo que es realmente frustrante es que el problema ocurre de forma intermitente, voy a cambiar un par de opciones que rodea los encabezados, entonces voy a trabajar un poco, y dejar de trabajar de nuevo sin ningún cambio de código.

Mi servidor está configurado para CORS y funciona bien con curl, y otros RESTO de los clientes. He aquí un ejemplo:

curl -X OPTIONS -ik 'https://localhost:3001/authenticate' -H "Origin: https://localhost:8001"
HTTP/1.1 200 OK
content-type: application/json; charset=utf-8
content-length: 2
cache-control: no-cache
access-control-allow-origin: *
access-control-max-age: 86400
access-control-allow-methods: GET, HEAD, POST, PUT, DELETE, OPTIONS
access-control-allow-headers: Authorization, Content-Type, If-None-Match, Access-Control-Allow-Headers, Content-Type
access-control-expose-headers: WWW-Authenticate, Server-Authorization
set-cookie: session=Fe26.2**94705d49717d1273197ae86ce6661775627d7c6066547b757118c90c056e393b*2KYqhATojPoQhpB2OwhDwg*W9GsJjK-F-UPqIIHTBHHZx1RXipo0zvr97_LtTLMscRkKqLqr8H6WiGd2kczVwL5M25FBlB1su0JZllq2QB-9w**5510263d744a9d5dc879a89b314f6379d17a39610d70017d60acef01fa63ec10*pkC9zEOJTY_skGhb4corYRGkUNGJUr8m5O1US2YhaRE; Secure; Path=/
Date: Wed, 18 Dec 2013 23:35:56 GMT
Connection: keep-alive

Aquí el $http.post de llamada:

var authRequest = $http.post('https://' + $location.host() + ':3001/authenticate', {email: email, password: password});

Cuando la llamada de mi aplicación funciona, esta es la forma en la solicitud de OPCIONES parece:

AngularJS: OPCIONES de comprobación preliminar de la llamada anterior de $http.solicitud post

Cuando no funciona, esta es la solicitud de OPCIONES:

AngularJS: OPCIONES de comprobación preliminar de la llamada anterior de $http.solicitud post

Se ve como un montón de encabezado de atributos falta. Alguien ha encontrado con un problema similar?

Edición:

Solo para aclarar, cuando no funciona, la petición no llega nunca al servidor inmediatamente abortado en el navegador.

AngularJS: OPCIONES de comprobación preliminar de la llamada anterior de $http.solicitud post

En Firebug, los encabezados de solicitud son:

OPTIONS /authenticate HTTP/1.1
Host: localhost:3001
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:25.0) Gecko/20100101 Firefox/25.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.91,en-GB;q=0.82,fr-FR;q=0.73,fr;q=0.64,utf-8;q=0.55,utf;q=0.45,de-DE;q=0.36,de;q=0.27,en-sg;q=0.18,en-ca;q=0.09
Accept-Encoding: gzip, deflate
Origin: https://localhost:8001
Access-Control-Request-Method: POST
Access-Control-Request-Headers: content-type
Proxy-Authorization: Basic cGF0cmljZUB6b25nLmNvbTpjaGFuZ2VtZQ==
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache

AngularJS: OPCIONES de comprobación preliminar de la llamada anterior de $http.solicitud post

Actualización:

He eliminado la posibilidad de un problema con el servidor, creo que, con el cambio de host para un servidor de inexistente. Aún viendo el comportamiento de la misma.

El siguiente código:

App.services.factory('AuthService', function ($http, $location, $q) {

    var currentUser;

    return {
        authenticate: function (email, password) {

            //promise to return
            var deferred = $q.defer();

            var authRequest = $http.post('https://this.does.not.exist.com:3001/authenticate', {email: email, password: password});

            authRequest.success(function (data, status, header, config) {
                currentUser = data;
                console.log('currentUser in service set to:');
                console.log(currentUser);
                //resolve promise
                deferred.resolve();
            });

            authRequest.error(function (data, status, header, config) {
                console.log('authentication error');
                console.log(status);
                console.log(data);
                console.log(header);
                console.log(config);

                //reject promise
                deferred.reject('authentication failed..');
            });

            return deferred.promise;
        },
        isAuthenticated: function () {
            return currentUser !== undefined;
        }
    };
});

y HTTP Config:

App.config(['$httpProvider', function ($httpProvider) {

    $httpProvider.defaults.useXDomain = true;
    //$httpProvider.defaults.headers.common = {};

    console.log('logging out headers');
    console.log($httpProvider.defaults);
    console.log($httpProvider.defaults.headers.common);
    console.log($httpProvider.defaults.headers.post);
    console.log($httpProvider.defaults.headers.put);
    console.log($httpProvider.defaults.headers.patch);
    console.log('end logging out headers');

    $httpProvider.defaults.headers.common = {Accept: "application/json, text/plain, */*"};
    $httpProvider.defaults.headers.post = {"Content-Type": "application/json;charset=utf-8"};

    console.log('after: logging out headers');
    console.log($httpProvider.defaults.headers.common);
    console.log($httpProvider.defaults.headers.post);
    console.log($httpProvider.defaults.headers.put);
    console.log($httpProvider.defaults.headers.patch);
    console.log('after: end logging out headers');

    $httpProvider.interceptors.push(function ($location, $injector) {
        return {
            'request': function (config) {

                console.log('in request interceptor!');

                var path = $location.path();
                console.log('request: ' + path);

                //injected manually to get around circular dependency problem.
                var AuthService = $injector.get('AuthService');
                console.log(AuthService);
                console.log(config);

                if (!AuthService.isAuthenticated() && $location.path() != '/login') {
                    console.log('user is not logged in.');
                    $location.path('/login');
                }

                //add headers
                console.log(config.headers);
                return config;
            }
        };
    });
}]);
  • ¿estás seguro que tu script/aplicación no está enviando doble petición? sync (formulario de envío) + solicitud asincrónica a la misma url?
  • ¿puede aclarar por favor? estoy bastante seguro de que es sólo una única solicitud, aunque.
  • Usar firebug para la depuración de CORS problemas. Chrome tiene un problema conocido y no se mostrará toda la información disponible. code.google.com/p/chromium/issues/…
  • lo mismo en Firebug. He editado mi pregunta para reflejar eso.
InformationsquelleAutor shaunlim | 2013-12-19

3 Kommentare

  1. 13

    Esto se siente como que podría estar relacionado con el hecho de que usted está golpeando un https extremo en el localhost. Eso significa que usted está probablemente con algún tipo de certificado SSL auto-firmado, lo cual puede significar que Chrome considera que no son de confianza.

    Yo primero tratar de ir directamente a el /autenticar extremo y ver si Chrome le da una advertencia acerca de un certificado no es de confianza. A ver si la aceptación de que la advertencia de que funciona.

    De lo contrario, posiblemente mientras estás probando localmente puede golpear sólo un http extremo y ver si eso soluciona las cosas?

    • Hola Michael, gracias por la respuesta! El HTTPS problema podría ser una posibilidad, pero también soy el acceso HTTPS extremos (en el mismo servidor) utilizando el $objeto de recursos en otras partes de mi aplicación y todo parece bien allí. Te voy a dar tus sugerencias a ir mañana por la mañana de todos modos.
    • He visitado el ‘/autenticar’ extremo en Chrome, y no hubo ninguna advertencia acerca de un certificado no es de confianza, probablemente aceptado en algún momento antes de que esto cuando comienzo a desarrollar la app.
    • También, parece que funciona bien cuando tengo que cambiar a llamada a $http.obtener, y tienen un correspondiente GET /autenticar extremo en el servidor.
    • He observado el mismo comportamiento con la mi $recursos. Desde que se envía una solicitud POST o PUT desde localhost (por lo menos), Chrome empezar con una solicitud de OPCIONES. No sé por qué (probablemente para realizar algunos controles de seguridad antes), pero que es la forma en que funciona.
  2. 9

    Un enorme agradecimiento a Michael Cox para que me apunta en la dirección correcta. Acepto su respuesta, ya que me llevó a la solución, pero aquí hay más detalles:

    Mirando hacia el https problema, he encontrado:

    Mi problema era ligeramente diferente, aunque. Todavía no estaba trabajando, después he seguido las instrucciones en el enlace de arriba. He leído el chrome «que no son de confianza» mensaje cuidadosamente y fue algo así como «usted está tratando de acceder a mylocalhost.com pero el servidor está representando a sí mismo como «.

    Resulta que mi prisa creado certificado autofirmado fue «server.crt» cuando debería ser «mylocalhost.crt»

  3. 7

    No se puede tener allow-credentials junto con Access-Control-Allow-Origin: *.

    Nota importante: cuando se responde a una solicitud de credenciales de servidor, debe especificar un dominio, y no se puede utilizar comodines.

    Con respecto a las peticiones GET, que no necesitan de comprobaciones etc si no tienen cabeceras especiales.

    Fuente: Mozilla Developer Network. (Mejor CORS enlace en la web!)

Kommentieren Sie den Artikel

Bitte geben Sie Ihren Kommentar ein!
Bitte geben Sie hier Ihren Namen ein

Pruebas en línea