2013-03-24 13 views
85

Sono un novizio di angular.js, e sto cercando di aggiungere alcune intestazioni a una richiesta:Aggiunta di un'intestazione personalizzata a richiesta HTTP utilizzando angular.js

var config = {headers: { 
      'Authorization': 'Basic d2VudHdvcnRobWFuOkNoYW5nZV9tZQ==', 
      'Accept': 'application/json;odata=verbose' 
     } 
    }; 

    $http.get('https://www.example.com/ApplicationData.svc/Malls(1)/Retailers', config).success(successCallback).error(errorCallback); 

Ho guardato tutta la documentazione e mi sembra che dovrebbe essere corretto.

Quando uso un file locale per l'URL nella $http.get, vedo la seguente richiesta HTTP della scheda di rete in Chrome:

GET /app/data/offers.json HTTP/1.1 
Host: www.example.com 
Connection: keep-alive 
Cache-Control: max-age=0 
If-None-Match: "0f0abc9026855b5938797878a03e6889" 
Authorization: Basic Y2hhZHN0b25lbWFuOkNoYW5nZV9tZQ== 
Accept: application/json;odata=verbose 
X-Requested-With: XMLHttpRequest 
If-Modified-Since: Sun, 24 Mar 2013 15:58:55 GMT 
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.22 (KHTML, like Gecko) Chrome/25.0.1364.172 Safari/537.22 
X-Testing: Testing 
Referer: http://www.example.com/app/index.html 
Accept-Encoding: gzip,deflate,sdch 
Accept-Language: en-US,en;q=0.8 
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3 

Come si può vedere, sia delle intestazioni sono stati aggiunti correttamente. Ma quando cambio l'URL a quella mostrata nella $http.get sopra (ad eccezione utilizzando l'indirizzo reale, non example.com), allora ottengo:

OPTIONS /ApplicationData.svc/Malls(1) HTTP/1.1 
Host: www.datahost.net 
Connection: keep-alive 
Access-Control-Request-Method: GET 
Origin: http://mpon.site44.com 
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.22 (KHTML, like Gecko) Chrome/25.0.1364.172 Safari/537.22 
Access-Control-Request-Headers: accept, origin, x-requested-with, authorization, x-testing 
Accept: */* 
Referer: http://mpon.site44.com/app/index.html 
Accept-Encoding: gzip,deflate,sdch 
Accept-Language: en-US,en;q=0.8 
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3 

L'unica differenza nel codice tra questi due è uno è per il primo l'URL è un file locale e per il secondo l'URL è un server remoto. Se si guarda la seconda intestazione della richiesta, non esiste un'intestazione di autenticazione e il Accept sembra utilizzare un valore predefinito anziché quello specificato. Inoltre, la prima riga ora indica OPTIONS anziché GET (sebbene Access-Control-Request-Method sia GET).

Qualche idea di cosa non funziona nel codice precedente o di come includere le intestazioni aggiuntive quando non si utilizza un file locale come origine dati?

+2

Questo appare come un problema CORS - prendere una lettura attraverso questa discussione per alcuni retroscena : https://groups.google.com/forum/#!topic/angular/CSBMY6oXfqs –

+0

Si è trattato di un problema CORS. Il server non è stato configurato per restituire l'intestazione Access-Control-Allow-Origin :. Se vuoi scrivere una risposta con il tuo commento e un po 'di dettagli su CORS, accetterò la tua risposta. La risposta che segue di Dmitry Evseev e pubblicata da te era vicina, ma non il vero problema. – trentclowater

+1

Chrome esegue il preflight della richiesta per cercare le intestazioni CORS se la richiesta è di dominio incrociato. Controlla la mia risposta. –

risposta

-8

Per me il seguente frammento esplicativo ha funzionato. Forse non dovresti usare ' per il nome dell'intestazione?

{ 
    headers: { 
     Authorization: "Basic " + getAuthDigest(), 
     Accept: "text/plain" 
    } 
} 

sto usando $http.ajax(), anche se non mi aspetto che per essere un punto di svolta.

60

ho preso quello che aveva, e ha aggiunto un altro colpo di testa X-Testing

var config = {headers: { 
     'Authorization': 'Basic d2VudHdvcnRobWFuOkNoYW5nZV9tZQ==', 
     'Accept': 'application/json;odata=verbose', 
     "X-Testing" : "testing" 
    } 
}; 

$http.get("/test", config); 

e nella scheda di rete Chrome, li vedo inviati.

GET /test HTTP/1.1 
Host: localhost:3000 
Connection: keep-alive 
Accept: application/json;odata=verbose 
X-Requested-With: XMLHttpRequest 
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_3) AppleWebKit/537.22 (KHTML, like Gecko) Chrome/25.0.1364.172 Safari/537.22 
Authorization: Basic d2VudHdvcnRobWFuOkNoYW5nZV9tZQ== 
X-Testing: testing 
Referer: http://localhost:3000/ 
Accept-Encoding: gzip,deflate,sdch 
Accept-Language: en-US,en;q=0.8 
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3 

Non li vedi dal browser o sul server? Prova gli strumenti del browser o un proxy di debug e vedi cosa viene inviato.

+0

Non ho accesso al server, e sul browser sto usando Firefox, ma vedo le intestazioni che ho aggiunto alla domanda originale sopra.Non vedo dove è possibile visualizzare le intestazioni nella scheda delle risorse in Chrome. – trentclowater

+0

Spiacente, ho aggiunto una modifica alla tua risposta che intendeva rispondere alla mia domanda iniziale. – trentclowater

+0

Intendevo la scheda di rete degli strumenti di sviluppo, non le risorse - aggiornamenti risposta –

2

Quello che vedi per la richiesta OPZIONI va bene. Le intestazioni di autorizzazione non sono esposte al suo interno.

Ma per far funzionare l'autenticazione di base è necessario aggiungere: withCredentials = true; al numero var config.

Dalle AngularJS $http documentation:

withCredentials - {boolean} - se per impostare il flag withCredentials sull'oggetto XHR. Vedi requests with credentials per ulteriori informazioni .

1

E qual è la risposta dal server? Dovrebbe rispondere a 204 e quindi inviare veramente il GET che stai richiedendo.

Nelle OPZIONI il client sta verificando se il server consente le richieste CORS. Se ti dà qualcosa di diverso da un 204 allora dovresti configurare il tuo server per inviare le intestazioni Allow-Origin corrette.

Il modo in cui si aggiungono le intestazioni è il modo giusto per farlo.

7

il mio suggerimento sarà aggiungere una funzione impostazioni di chiamata come questa all'interno della funzione controllare l'intestazione che è appropriato per esso. Sono sicuro che funzionerà sicuramente. funziona perfettamente per me

function getSettings(requestData) { 
    return { 
     url: requestData.url, 
     dataType: requestData.dataType || "json", 
     data: requestData.data || {}, 
     headers: requestData.headers || { 
      "accept": "application/json; charset=utf-8", 
      'Authorization': 'Bearer ' + requestData.token 
     }, 
     async: requestData.async || "false", 
     cache: requestData.cache || "false", 
     success: requestData.success || {}, 
     error: requestData.error || {}, 
     complete: requestData.complete || {}, 
     fail: requestData.fail || {} 
    }; 
} 

quindi chiamare i vostri dati come questo

var requestData = { 
     url: 'API end point', 
     data: Your Request Data, 
     token: Your Token 
    }; 

    var settings = getSettings(requestData); 
    settings.method = "POST"; //("Your request type") 
    return $http(settings); 
7

Se si desidera aggiungere le intestazioni personalizzate a tutte le richieste, è possibile modificare le impostazioni di default su $ httpProvider per aggiungere sempre questa intestazione ...

app.config(['$httpProvider', function ($httpProvider) { 
    $httpProvider.defaults.headers.common = { 
     'Authorization': 'Basic d2VudHdvcnRobWFuOkNoYW5nZV9tZQ==', 
     'Accept': 'application/json;odata=verbose' 
     }; 
}]); 
+0

TUTTE ma le richieste di OPZIONI che è un esempio piacevole – Rocco

+0

. può essere usato per memorizzare nella cache token per reindirizzare le pagine? – Martian2049

17

Autenticazione di base tramite metodo HTTP POST:

$http({ 
    method: 'POST', 
    url: '/API/authenticate', 
    data: 'username=' + username + '&password=' + password + '&email=' + email, 
    headers: { 
     "Content-Type": "application/x-www-form-urlencoded", 
     "X-Login-Ajax-call": 'true' 
    } 
}).then(function(response) { 
    if (response.data == 'ok') { 
     // success 
    } else { 
     // failed 
    } 
}); 

... e GET chiamata di metodo con l'intestazione:

$http({ 
    method: 'GET', 
    url: '/books', 
    headers: { 
     'Authorization': 'Basic d2VudHdvcnRobWFuOkNoYW5nZV9tZQ==', 
     'Accept': 'application/json', 
     "X-Login-Ajax-call": 'true' 
    } 
}).then(function(response) { 
    if (response.data == 'ok') { 
     // success 
    } else { 
     // failed 
    } 
}); 
1

Chrome si verifica preliminare la richiesta di cercare le intestazioni CORS. Se la richiesta è accettabile, invierà la richiesta reale. Se stai facendo questo cross-domain, dovrai semplicemente gestirlo o trovare un modo per rendere la richiesta non-cross-domain. Questo è di design.

A differenza di semplici richieste (di cui sopra), "preflight" le richieste di primo inviare una richiesta HTTP con il metodo OPTIONS per la risorsa dall'altra dominio, al fine di determinare se la richiesta effettiva è sicuro inviare . Le richieste cross-site sono verificate in questo modo poiché potrebbero avere implicazioni sui dati utente. In particolare, una richiesta è preflight se:

Utilizza metodi diversi da GET, HEAD o POST. Inoltre, se il POST viene utilizzato per inviare i dati di richiesta con un Content-Type diverso da application/x-www-form-urlencoded, multipart/form-data o text/plain, ad es. se la richiesta POST invia un payload XML al server utilizzando application/xml o text/xml, quindi la richiesta viene preflight. Essa stabilisce intestazioni personalizzate nella richiesta (ad esempio, la richiesta utilizza un colpo di testa, come X-PINGOTHER)

Rif: AJAX in Chrome sending OPTIONS instead of GET/POST/PUT/DELETE?

Problemi correlati