Додавання власного заголовка до HTTP-запиту за допомогою angular.js


89

Я новачок у 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);

Я переглянув всю документацію, і мені здається, це має бути правильно.

Коли я використовую локальний файл для URL-адреси в $http.get, на вкладці мережі в Chrome я бачу такий запит HTTP:

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

Як бачите, обидва заголовки були додані правильно. Але коли я зміню URL-адресу на вказану $http.getвище (за винятком використання реальної адреси, а не example.com), я отримую:

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

Єдина різниця в коді між цими двома полягає в тому, що для першого URL-адреса є локальним файлом, а для другого URL-адресою є віддалений сервер. Якщо ви подивитесь на другий заголовок запиту, заголовок автентифікації відсутній, і, Acceptсхоже, використовується за замовчуванням замість вказаного. Крім того, перший рядок тепер пише OPTIONSзамість GET(хоча Access-Control-Request-Methodє GET).

Будь-яка ідея, що не так із наведеним вище кодом, або як отримати включені додаткові заголовки, якщо не використовувати локальний файл як джерело даних?


2
Це виглядає як проблема CORS - прочитайте цю дискусію, щоб ознайомитись із деякими передісторіями: groups.google.com/forum/#!topic/angular/CSBMY6oXfqs
Кевін Хакансон,

Це справді було питання CORS. Сервер не налаштовано на повернення заголовка Access-Control-Allow-Origin:. Якщо ви хочете написати відповідь із вашим коментарем та трохи деталей щодо CORS, я прийму вашу відповідь. Відповідь нижче від Дмитра Євсєєва та відредагована вами була близькою, але насправді не справжньою проблемою.
trentclowater

1
Chrome здійснює попередню обробку запиту на пошук заголовків CORS, якщо запит є міждоменним. Перевірте мою відповідь.
Asim KT

Відповіді:


66

Я взяв те, що у вас було, і додав ще один X-Testingзаголовок

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

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

А на вкладці мережі Chrome я бачу, як їх надсилають.

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

Ви не бачите їх у браузері чи на сервері? Спробуйте інструмент браузера або проксі-сервер для налагодження і подивіться, що надсилається.


У мене немає доступу до сервера, і в браузері я використовую Firefox, але я бачу заголовки, які я додав до вихідного запитання вище. Я не бачу, де ви можете переглядати заголовки на вкладці ресурсу в Chrome.
trentclowater

Вибачте, я додав до вашої відповіді редагування, яке було призначено для мого початкового запитання.
trentclowater

Я мав на увазі мережеву вкладку інструментів розробника, а не ресурси - відповідь на оновлення
Кевін Хакансон,

До запитання я додав більше інформації. Схоже, заголовки додаються в одному випадку, але не в іншому.
trentclowater

21

Базова автентифікація за допомогою методу 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
    }
});

... та виклик методу GET із заголовком:

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

Найкраща відповідь.
Йода,

9

Якщо ви хочете додати власні заголовки до ВСІХ запитів, ви можете змінити за замовчуванням на $ httpProvider, щоб завжди додавати цей заголовок…

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

ВСІ, крім ВАРІАНТІВ запити, тобто
Рокко

гарний приклад. чи можна це використовувати для кешування маркера для перенаправлення сторінок?
Martian2049

7

моя пропозиція буде додати такі налаштування виклику функції всередині функції перевірити заголовок, який для неї підходить. Я впевнений, що це точно спрацює. це прекрасно працює для мене.

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

тоді зателефонуйте своїм даним так

    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

Те, що ви бачите для запиту OPTIONS, чудово. Заголовки авторизації в ньому не виставляються.

Але для того, щоб базовий авторитет працював, вам потрібно додати: withCredentials = true;до вашого var config.

З документації AngularJS $ http :

withCredentials - {boolean}- чи потрібно встановлювати withCredentials прапор на об'єкт XHR. Перегляньте запити з обліковими даними для отримання додаткової інформації.


1

А яка відповідь від сервера? Він повинен відповісти 204, а потім дійсно надіслати GET, який ви вимагаєте.

У ВАРІАНТАХ клієнт перевіряє, чи дозволяє сервер запити CORS. Якщо це дає щось інше, ніж 204, вам слід налаштувати сервер на надсилання правильних заголовків Allow-Origin.

Спосіб додавання заголовків - це правильний спосіб це зробити.


1

Chrome попередньо висуває запит на пошук заголовків CORS. Якщо запит прийнятний, він надішле реальний запит. Якщо ви робите цей міждомен, вам просто доведеться з ним розібратися, інакше знайти спосіб зробити запит не міждоменним. Це за задумом.

На відміну від простих запитів (про які йшлося вище), "попередньо відбиті" запити спочатку надсилають запит HTTP методом OPTIONS до ресурсу в іншому домені, щоб визначити, чи справжній запит безпечний для відправки. Міжсайтові запити попередньо висвічуються таким чином, оскільки вони можуть мати наслідки для даних користувачів. Зокрема, запит попередньо висвічується, якщо:

Він використовує інші методи, окрім GET, HEAD або POST. Крім того, якщо POST використовується для надсилання даних запиту з Content-Type, відмінним від application / x-www-form-urlencoded, multipart / form-data або text / plain, наприклад, якщо запит POST надсилає на сервер XML-корисне навантаження використовуючи application / xml або text / xml, тоді запит попередньо висвічується. Він встановлює власні заголовки у запиті (наприклад, запит використовує такий заголовок, як X-PINGOTHER)

Посилання: AJAX у Chrome надсилає OPTIONS замість GET / POST / PUT / DELETE?


-8

Для мене працював наступний пояснювальний фрагмент. Можливо, вам не слід використовувати 'назву заголовка?

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

Я використовую $http.ajax(), хоча я би не сподівався, що це змінить гру.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.