2013-06-25 14 views
16

ho una base di installazione del servizio AngularJS in questo modo:AngularJS: inviare dati a REST API esterno

app.factory('User', function($resource) { 
return $resource('http://api.mysite.com/user/:action:id/:attr', {}, { 
    history: { 
     method: 'GET', 
     params: { 
      attr: 'history' 
     } 
    }, 
    update: { 
     method: 'POST', 
     params: { 
      name: 'test' 
     } 
    } 
}); 
}); 

e lo uso come questo:

User.history({id: 'testID'}, function(data) { 
    console.log('got history'); 
    console.log(data); 
}); 
User.update({id: 'me'}, function(data) { 
    console.log('updated'); 
    console.log(data); 
}); 

Problema uno: User.update(), nonostante abbia il metodo impostato su POST, continua a inviare OPZIONI come metodo di richiesta.

Sebbene gli strumenti di Chrome Dev riportino l'intestazione della richiesta Access-Control-Request-Method: anche POST viene inviato (non è sicuro se ciò significa qualcosa).

Problema due: Continuo a ricevere un errore con CORS, pur avendo queste intestazioni fissati nel codice API:

header('Access-Control-Allow-Origin: *'); 
header("Access-Control-Allow-Methods: PUT, GET, POST, DELETE, OPTIONS"); 

Questo problema mostra solo se se fare una richiesta non-GET.

Qual è il modo corretto di gestirlo? Ho anche esaminato JSONP, ma essendo questa una API RESTful, non sono sicuro di come aggirare i problemi con il solo supporto GET.

risposta

14

I tuoi due problemi sono in realtà un problema. La richiesta OPTIONS fa parte del processo CORS. Per le richieste POST, il browser invia prima una chiamata OPTIONS e il server risponde se è possibile eseguirlo.

Se la richiesta OPZIONI non riesce, Angular/Chrome mostra il motivo nella console. Per esempio:

OPTIONS https://*** Request header field Content-Type is not allowed by Access-Control-Allow-Headers. angular.min.js:106 

XMLHttpRequest cannot load https://***. Request header field Content-Type is not allowed by Access-Control-Allow-Headers. 

probabilmente È necessario impostare Access-Control-Lasciare intestazioni sul server, troppo:

header('Access-Control-Allow-Headers: Content-Type, x-xsrf-token') 

x-xrsf-token è per angolare' per prevenire CSRF. Potrebbe essere necessario aggiungere più intestazioni, a seconda di ciò che si invia dal client.

Ecco una guida molto buona sul CORS: https://developer.mozilla.org/en-US/docs/HTTP/Access_control_CORS

+0

Il browser che inviava la richiesta OPZIONI quindi la richiesta POST era dove il mio problema era. Il server non è stato configurato per rispondere alle OPZIONI iniziali. Non ho avuto bisogno di fare nulla con x-xsrf-token però. Utilizzato il codice da qui per gestire tutte le intestazioni necessarie: http://stackoverflow.com/questions/13293157/backbone-slim-php-access-control-allow-headers-can-get-information-cant/13530329#13530329 –

+1

questo era esattamente il mio problema grazie. Se usi node/express, segui le istruzioni "abilita pre-volo" qui per ottenere il funzionamento di cors: https://github.com/troygoode/node-cors/ – JasonS

7

In AngularJS per rendere CORS di lavoro si hanno anche per sovrascrivere le impostazioni predefinite del angolare httpProvider:

var myApp = angular.module('myApp', [ 
    'myAppApiService']); 

myApp.config(['$httpProvider', function($httpProvider) { 
     $httpProvider.defaults.useXDomain = true; 
     delete $httpProvider.defaults.headers.common['X-Requested-With']; 
    } 
]); 

Basta impostare useXDomain a true non è abbastanza. Le richieste AJAX sono anche inviate con l'intestazione X-Requested-With, che le indica come AJAX. La rimozione dell'intestazione è necessaria, quindi il server non rifiuta la richiesta in entrata .

Nota: Rispondere funziona solo per AngularJS anziani versione precedente alla 1.2. Con 1.2 e sopra non devi fare nulla per abilitare CORS.

+6

Questo in realtà non era necessario, in quanto ho accesso al server API e aggiunta 'header ('Access-Control-Allow-Headers: X-Requested-With');' che presumo risolve il problema di cui stai parlando. –

+0

Buon consiglio. Non ero a conoscenza dell'impostazione dell'intestazione di intestazione consenti. Grazie. –

+0

forse dovevi farlo con vecchie versioni angolari, ma so che in 1.2.x angolare, non hai bisogno di farlo. Seguendo @ la risposta di Narretz funziona per me. – JasonS

0

Meglio risolvere questo problema sul server. Su apache puoi risolverlo in questo modo in un file .htaccess. Questa è una fonte di dolore per lo sviluppo angolare e può essere risolta in modo angolare ma probabilmente non è il modo migliore per farlo.

Header set Access-Control-Allow-Origin "*" 
Header add Access-Control-Allow-Headers "origin, x-requested-with, content-type" 
Header add Access-Control-Allow-Methods "PUT, GET, POST, DELETE, OPTIONS"