Dodanie niestandardowego nagłówka do żądania HTTP przy użyciu angular.js.

89

Jestem nowicjuszem w angular.js i próbuję dodać kilka nagłówków do żądania:

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

Przejrzałem całą dokumentację i wydaje mi się, że powinna być poprawna.

Kiedy używam lokalnego pliku jako adresu URL w $http.get, widzę następujące żądanie HTTP na karcie sieci w 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

Jak widać, oba nagłówki zostały poprawnie dodane. Ale kiedy zmieniam adres URL na pokazany $http.getpowyżej (z wyjątkiem użycia prawdziwego adresu, a nie example.com), otrzymuję:

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

Jedyna różnica w kodzie między tymi dwoma jest taka, że ​​po pierwsze adres URL jest plikiem lokalnym, a po drugie adres URL jest serwerem zdalnym. Jeśli spojrzysz na drugi nagłówek żądania, nie ma nagłówka Authentication i Acceptwygląda na to, że używa domyślnego zamiast określonego. Ponadto pierwsza linia mówi teraz OPTIONSzamiast GET(chociaż Access-Control-Request-Methodjest GET).

Masz jakiś pomysł, co jest nie tak z powyższym kodem lub jak uzyskać dodatkowe nagłówki dołączone, gdy nie używasz pliku lokalnego jako źródła danych?

trentclowater
źródło
2
To wygląda na problem z CORS - przeczytaj tę dyskusję, aby uzyskać pewne tło: groups.google.com/forum/#!topic/angular/CSBMY6oXfqs
Kevin Hakanson
To rzeczywiście była kwestia CORS. Serwer nie został skonfigurowany do zwracania nagłówka Access-Control-Allow-Origin:. Jeśli chcesz napisać odpowiedź z komentarzem i trochę szczegółami na temat CORS, przyjmuję twoją odpowiedź. Poniższa odpowiedź od Dmitrija Evseeva i zredagowana przez Ciebie była bliska, ale tak naprawdę nie był to rzeczywisty problem.
trentclowater
1
Chrome wstępnie sprawdza żądanie wyszukania nagłówków CORS, jeśli żądanie dotyczy wielu domen. Sprawdź moją odpowiedź.
Asim KT

Odpowiedzi:

66

Wziąłem to, co miałeś i dodałem kolejny X-Testingnagłówek

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

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

A na karcie sieci Chrome widzę, że są wysyłane.

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

Nie widzisz ich w przeglądarce lub na serwerze? Wypróbuj narzędzia przeglądarki lub serwer proxy do debugowania i zobacz, co jest wysyłane.

Kevin Hakanson
źródło
Nie mam dostępu do serwera, aw przeglądarce używam Firefoksa, ale widzę nagłówki, które dodałem do pierwotnego pytania powyżej. Nie widzę, gdzie możesz wyświetlić nagłówki na karcie zasobów w Chrome.
trentclowater
Przepraszamy, dodałem zmianę do Twojej odpowiedzi, która miała znaleźć się w moim pierwotnym pytaniu.
trentclowater
Chodziło mi kartę sieciową z narzędzi programistycznych, a nie środków - aktualizacje odpowiedzieć
Kevin Håkanson
Dodałem więcej informacji do pytania. Wygląda na to, że nagłówki zostały dodane w jednym przypadku, ale nie w innym.
trentclowater
21

Uwierzytelnianie podstawowe metodą 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
    }
});

... i wywołanie metody GET z nagłówkiem:

$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
źródło
Najlepsza odpowiedź.
Yoda,
9

Jeśli chcesz dodać własne nagłówki do WSZYSTKICH żądań, możesz zmienić ustawienia domyślne w $ httpProvider, aby zawsze dodawać ten nagłówek…

app.config(['$httpProvider', function ($httpProvider) {
    $httpProvider.defaults.headers.common = { 
        'Authorization': 'Basic d2VudHdvcnRobWFuOkNoYW5nZV9tZQ==',
        'Accept': 'application/json;odata=verbose'
      };
}]);
Korayem
źródło
WSZYSTKIE oprócz OPCJI żądają
Rocco
niezły przykład. czy można to wykorzystać do buforowania tokena do przekierowywania stron?
Martian2049,
7

moją sugestią będzie dodanie ustawień wywołania funkcji, takich jak to, wewnątrz funkcji sprawdź nagłówek, który jest dla niej odpowiedni. Jestem pewien, że to na pewno zadziała. to dla mnie doskonale działa.

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

następnie zadzwoń do swoich danych w ten sposób

    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);
Rijad Ul Islam
źródło
2

To, co widzisz dla żądania OPCJI, jest w porządku. Nagłówki autoryzacji nie są w nim ujawniane.

Ale aby podstawowa autoryzacja działała, musisz dodać: withCredentials = true;do swojego var config.

Z dokumentacji AngularJS $ http :

withCredentials - {boolean}- czy ustawić withCredentials flagę w obiekcie XHR. Aby uzyskać więcej informacji, zobacz prośby z poświadczeniami .

Dmitry Evseev
źródło
1

A jaka jest odpowiedź z serwera? Powinien odpowiedzieć na 204, a następnie naprawdę wysłać żądanie GET.

W OPCJACH klient sprawdza, czy serwer zezwala na żądania CORS. Jeśli daje coś innego niż 204, powinieneś skonfigurować serwer, aby wysyłał prawidłowe nagłówki Allow-Origin.

Sposób, w jaki dodajesz nagłówki, to właściwy sposób.

ghostbar
źródło
1

Chrome wstępnie sprawdza żądanie wyszukania nagłówków CORS. Jeśli żądanie zostanie zaakceptowane, wyśle ​​prawdziwe żądanie. Jeśli robisz to w wielu domenach, będziesz musiał po prostu sobie z tym poradzić lub znaleźć sposób, aby żądanie nie było międzydomenowe. Jest to zgodne z projektem.

W przeciwieństwie do prostych żądań (omówionych powyżej), żądania „preflighted” najpierw wysyłają żądanie HTTP metodą OPTIONS do zasobu w innej domenie, aby określić, czy rzeczywiste żądanie jest bezpieczne do wysłania. Żądania między witrynami są wstępnie analizowane w ten sposób, ponieważ mogą mieć wpływ na dane użytkownika. W szczególności wniosek jest wstępnie sprawdzany, jeśli:

Używa metod innych niż GET, HEAD lub POST. Ponadto, jeśli POST jest używany do wysyłania danych żądania z typem zawartości innym niż application / x-www-form-urlencoded, multipart / form-data lub text / plain, np. Jeśli żądanie POST wysyła ładunek XML do serwera przy użyciu application / xml lub text / xml, żądanie jest wstępnie sprawdzane. Ustawia niestandardowe nagłówki w żądaniu (np. Żądanie używa nagłówka, takiego jak X-PINGOTHER)

Ref: AJAX w Chrome wysyła OPCJE zamiast GET / POST / PUT / DELETE?

Asim KT
źródło
-8

Dla mnie zadziałał następujący fragment wyjaśniający. Być może nie powinieneś używać 'nazwy nagłówka?

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

Używam $http.ajax(), chociaż nie spodziewałbym się, że to zmieni grę.

Łukasz Bachman
źródło