Добавление настраиваемого заголовка в 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, я вижу следующий HTTP-запрос на вкладке сети в 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

Как видите, оба заголовка добавлены правильно. Но когда я меняю 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-адрес является удаленным сервером. Если вы посмотрите на второй заголовок запроса, там нет заголовка Authentication, и 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'
      };
}]);
Кораем
источник
Запросы ALL, кроме OPTIONS
Rocco
хороший пример. можно ли это использовать для кеширования токена для перенаправления страниц?
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, который вы запрашиваете.

В OPTIONS клиент проверяет, разрешает ли сервер запросы 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, отправляющий ОПЦИИ вместо GET / POST / PUT / DELETE?

Асим КТ
источник
-8

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

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

Я использую $http.ajax(), хотя не ожидал, что это изменит правила игры.

ЛукашБахман
источник