Hinzufügen eines benutzerdefinierten Headers zur HTTP-Anforderung mithilfe von angle.js

89

Ich bin ein Anfänger von angular.js und versuche, einer Anfrage einige Header hinzuzufügen:

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

Ich habe mir die gesamte Dokumentation angesehen, und dies scheint mir richtig zu sein.

Wenn ich eine lokale Datei für die URL in der verwende $http.get, wird auf der Registerkarte "Netzwerk" in Chrome die folgende HTTP-Anforderung angezeigt:

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

Wie Sie sehen können, wurden beide Header korrekt hinzugefügt. Aber wenn ich die URL in die $http.getoben gezeigte ändere (außer unter Verwendung der realen Adresse, nicht example.com), erhalte ich:

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

Der einzige Unterschied im Code zwischen diesen beiden besteht darin, dass zum einen die URL eine lokale Datei und zum anderen ein Remote-Server ist. Wenn Sie sich den zweiten Anforderungsheader ansehen, gibt es keinen Authentifizierungsheader, und der verwendet Acceptanscheinend einen Standard anstelle des angegebenen. Auch in der ersten Zeile steht jetzt OPTIONSstatt GET(obwohl Access-Control-Request-Methodist GET).

Haben Sie eine Idee, was mit dem obigen Code nicht stimmt oder wie Sie die zusätzlichen Header einbinden können, wenn Sie keine lokale Datei als Datenquelle verwenden?

Trentclowater
quelle
2
Dies sieht aus wie ein CORS-Problem - lesen Sie diese Diskussion durch, um Hintergrundinformationen zu erhalten: groups.google.com/forum/#!topic/angular/CSBMY6oXfqs
Kevin Hakanson
Es war in der Tat ein CORS-Problem. Der Server war nicht so konfiguriert, dass er den Header Access-Control-Allow-Origin: zurückgibt. Wenn Sie eine Antwort mit Ihrem Kommentar und ein paar Details zu CORS schreiben möchten, akzeptiere ich Ihre Antwort. Die Antwort von Dmitry Evseev unten und von Ihnen bearbeitet war nah, aber nicht wirklich das eigentliche Problem.
Trentclowater
1
Chrome prüft die Anforderung, nach CORS-Headern zu suchen, wenn die Anforderung domänenübergreifend ist. Überprüfen Sie meine Antwort.
Asim KT

Antworten:

66

Ich nahm, was Sie hatten, und fügte einen weiteren X-TestingHeader hinzu

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

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

Auf der Registerkarte "Chrome-Netzwerk" werden sie gesendet.

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

Sehen Sie sie nicht im Browser oder auf dem Server? Probieren Sie das Browser-Tool oder einen Debug-Proxy aus und sehen Sie, was gesendet wird.

Kevin Hakanson
quelle
Ich habe keinen Zugriff auf den Server und verwende im Browser Firefox, aber ich sehe die Header, die ich der ursprünglichen Frage oben hinzugefügt habe. Ich sehe nicht, wo Sie die Header auf der Registerkarte "Ressourcen" in Chrome anzeigen können.
Trentclowater
Entschuldigung, ich habe Ihrer Antwort eine Bearbeitung hinzugefügt, die in meine ursprüngliche Frage aufgenommen werden sollte.
Trentclowater
Ich meinte die Registerkarte Netzwerk der Entwicklertools, nicht Ressourcen - Updates Antwort
Kevin Hakanson
Ich habe der Frage weitere Informationen hinzugefügt. Es sieht so aus, als würden die Header in einem Fall hinzugefügt, in einem anderen jedoch nicht.
Trentclowater
21

Grundlegende Authentifizierung mithilfe der HTTP-POST-Methode:

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

... und GET-Methodenaufruf mit Header:

$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
    }
});
Ajay Kumar
quelle
Die beste Antwort.
Yoda
9

Wenn Sie Ihre benutzerdefinierten Header zu ALLEN Anforderungen hinzufügen möchten, können Sie die Standardeinstellungen für $ httpProvider ändern, um diesen Header immer hinzuzufügen.

app.config(['$httpProvider', function ($httpProvider) {
    $httpProvider.defaults.headers.common = { 
        'Authorization': 'Basic d2VudHdvcnRobWFuOkNoYW5nZV9tZQ==',
        'Accept': 'application/json;odata=verbose'
      };
}]);
Korayem
quelle
ALLE außer OPTIONEN Anfragen, die ist
Rocco
schönes Beispiel. Kann dies verwendet werden, um Token für die Umleitung von Seiten zwischenzuspeichern?
Martian2049
7

Mein Vorschlag ist, eine Funktionsaufrufeinstellung wie diese in die Funktion einzufügen und den dafür geeigneten Header zu überprüfen. Ich bin sicher, es wird definitiv funktionieren. es funktioniert perfekt für mich.

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 || {}
    };
}

Rufen Sie dann Ihre Daten so auf

    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);
Riad Ul Islam
quelle
2

Was Sie für die OPTIONS-Anfrage sehen, ist in Ordnung. Autorisierungsheader werden darin nicht angezeigt.

Damit die grundlegende Authentifizierung funktioniert, müssen Sie Folgendes hinzufügen: withCredentials = true;zu Ihrem var config.

Aus der AngularJS $ http-Dokumentation :

withCredentials - {boolean}- ob das withCredentials Flag für das XHR-Objekt gesetzt werden soll. Weitere Informationen finden Sie unter Anfragen mit Anmeldeinformationen .

Dmitry Evseev
quelle
1

Und wie lautet die Antwort vom Server? Es sollte eine 204 antworten und dann wirklich das GET senden, das Sie anfordern.

In den OPTIONEN prüft der Client, ob der Server CORS-Anforderungen zulässt. Wenn Sie etwas anderes als einen 204 erhalten, sollten Sie Ihren Server so konfigurieren, dass die richtigen Allow-Origin-Header gesendet werden.

Die Art und Weise, wie Sie Header hinzufügen, ist die richtige Vorgehensweise.

Ghostbar
quelle
1

Chrome prüft vorab die Anfrage, nach CORS-Headern zu suchen. Wenn die Anfrage akzeptabel ist, wird die eigentliche Anfrage gesendet. Wenn Sie diese domänenübergreifende Aktion ausführen, müssen Sie sich lediglich damit befassen oder einen Weg finden, die Anfrage nicht domänenübergreifend zu gestalten. Dies ist beabsichtigt.

Im Gegensatz zu einfachen Anforderungen (siehe oben) senden "Preflighted" -Anforderungen zuerst eine HTTP-Anforderung mit der OPTIONS-Methode an die Ressource in der anderen Domäne, um festzustellen, ob die tatsächliche Anforderung sicher zu senden ist. Standortübergreifende Anforderungen werden auf diese Weise vorab ausgeführt, da sie Auswirkungen auf Benutzerdaten haben können. Insbesondere wird eine Anfrage vorab geflogen, wenn:

Es werden andere Methoden als GET, HEAD oder POST verwendet. Wenn POST zum Senden von Anforderungsdaten mit einem anderen Inhaltstyp als application / x-www-form-urlencoded, multipart / form-data oder text / plain verwendet wird, z. B. wenn die POST-Anforderung eine XML-Nutzlast an den Server sendet Wenn Sie application / xml oder text / xml verwenden, wird die Anforderung vorab ausgeführt. Es werden benutzerdefinierte Header in der Anforderung festgelegt (z. B. verwendet die Anforderung einen Header wie X-PINGOTHER).

Ref: AJAX in Chrome sendet OPTIONEN anstelle von GET / POST / PUT / DELETE?

Asim KT
quelle
-8

Für mich hat das folgende erklärende Snippet funktioniert. Vielleicht sollten Sie nicht 'für den Headernamen verwenden?

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

Ich benutze $http.ajax(), obwohl ich nicht erwarten würde, dass dies ein Game Changer ist.

ŁukaszBachman
quelle