Aggiunta di un'intestazione personalizzata alla richiesta HTTP utilizzando angular.js


89

Sono un principiante di angular.js e sto cercando di aggiungere alcune intestazioni a una richiesta:

   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 esaminato tutta la documentazione e mi sembra che dovrebbe essere corretta.

Quando utilizzo un file locale per l'URL in $http.get, vedo la seguente richiesta HTTP nella 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 puoi vedere, entrambe le intestazioni sono state aggiunte correttamente. Ma quando cambio l'URL con quello mostrato $http.getsopra (eccetto per l'utilizzo dell'indirizzo reale, non di example.com), 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 di codice tra questi due è che per il primo l'URL è un file locale e per il secondo l'URL è un server remoto. Se guardi la seconda intestazione della richiesta, non è presente alcuna intestazione di autenticazione e Acceptsembra che stia utilizzando un'impostazione predefinita invece di quella specificata. Inoltre, la prima riga ora dice OPTIONSinvece di GET(sebbene Access-Control-Request-Methodsia GET).

Qualche idea su cosa c'è di sbagliato nel codice precedente o su come ottenere le intestazioni aggiuntive incluse utilizzando quando non si utilizza un file locale come origine dati?


2
Sembra un problema CORS: leggi questa discussione per qualche informazione di base: groups.google.com/forum/#!topic/angular/CSBMY6oXfqs
Kevin Hakanson

Era davvero 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 di seguito da Dmitry Evseev e modificata da te era vicina, ma non proprio il problema reale.
trentclowater

1
Chrome esegue il preflight della richiesta per cercare le intestazioni CORS se la richiesta è interdominio. Controlla la mia risposta.
Asim KT

Risposte:


66

Ho preso quello che avevi e ho aggiunto un'altra X-Testingintestazione

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

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

E nella scheda Rete di Chrome, vedo che vengono 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 guarda cosa viene inviato.


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

Mi spiace, ho aggiunto una modifica alla tua risposta che doveva essere inserita nella mia domanda originale.
trentclowater

Intendevo la scheda di rete degli strumenti per sviluppatori, non le risorse - risposta agli aggiornamenti
Kevin Hakanson

Ho aggiunto ulteriori informazioni alla domanda. Sembra che le intestazioni vengano aggiunte in un caso, ma non in un altro.
trentclowater

21

Autenticazione di base utilizzando il 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 al metodo con 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
    }
});

La migliore risposta.
Yoda

9

Se desideri aggiungere le tue intestazioni personalizzate a TUTTE le richieste, puoi modificare le impostazioni predefinite su $ httpProvider per aggiungere sempre questa intestazione ...

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

TUTTI tranne OPZIONI richiedono che è
Rocco

bell'esempio. può essere utilizzato per memorizzare nella cache il token per il reindirizzamento delle pagine?
Martian2049

7

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

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 chiama i tuoi dati in questo modo

    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);

2

Quello che vedi per la richiesta OPZIONI va bene. Le intestazioni di autorizzazione non sono esposte in esso.

Ma affinché l'autenticazione di base funzioni è necessario aggiungere: withCredentials = true;al filevar config .

Dalla documentazione di AngularJS $ http :

withCredentials - {boolean}- se impostare il withCredentials flag sull'oggetto XHR. Vedere richieste con credenziali per ulteriori informazioni.


1

E qual è la risposta dal server? Dovrebbe rispondere a 204 e quindi inviare realmente il GET richiesto.

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

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


1

Chrome sta eseguendo il preflight della richiesta per cercare le intestazioni CORS. Se la richiesta è accettabile, invierà la richiesta reale. Se stai facendo questo cross-domain, dovrai semplicemente occupartene o trovare un modo per rendere la richiesta non cross-domain. Questo è in base alla progettazione.

A differenza delle richieste semplici (discusse sopra), le richieste "preflight" inviano prima una richiesta HTTP mediante il metodo OPTIONS alla risorsa sull'altro dominio, al fine di determinare se la richiesta effettiva è sicura da inviare. Le richieste cross-site vengono sottoposte a preflight in questo modo poiché potrebbero avere implicazioni sui dati dell'utente. In particolare, viene eseguito il preflight di una richiesta se:

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

Rif: AJAX in Chrome che invia OPZIONI invece di GET / POST / PUT / DELETE?


-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 possa cambiare le regole del gioco.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.