Menambahkan tajuk khusus ke permintaan HTTP menggunakan angular.js

89

Saya seorang pemula di angular.js, dan saya mencoba menambahkan beberapa header ke sebuah permintaan:

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

Saya telah melihat semua dokumentasi, dan menurut saya ini sepertinya benar.

Ketika saya menggunakan file lokal untuk URL di $http.get, saya melihat permintaan HTTP berikut pada tab jaringan di 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

Seperti yang Anda lihat, kedua header telah ditambahkan dengan benar. Tetapi ketika saya mengubah URL seperti yang ditunjukkan di $http.getatas (kecuali menggunakan alamat sebenarnya, bukan example.com), maka saya mendapatkan:

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

Satu-satunya perbedaan kode di antara keduanya adalah yang pertama URL-nya adalah file lokal, dan yang kedua URL-nya adalah server jarak jauh. Jika Anda melihat header Permintaan kedua, tidak ada header Otentikasi, dan Accepttampaknya menggunakan default, bukan yang ditentukan. Juga, baris pertama sekarang mengatakan OPTIONSalih-alih GET(meskipun Access-Control-Request-Methodada GET).

Adakah yang tahu apa yang salah dengan kode di atas, atau bagaimana cara memasukkan header tambahan saat tidak menggunakan file lokal sebagai sumber data?

trentclowater.dll
sumber
2
Sepertinya ini masalah CORS - baca diskusi ini untuk mengetahui beberapa latar belakang: groups.google.com/forum/#!topic/angular/CSBMY6oXfqs
Kevin Hakanson
Itu memang masalah CORS. Server tidak dikonfigurasi untuk mengembalikan header Access-Control-Allow-Origin :. Jika Anda ingin menulis jawaban dengan komentar Anda dan sedikit detail tentang CORS, saya akan menerima jawaban Anda. Jawaban di bawah ini dari Dmitry Evseev dan diedit oleh Anda sudah dekat, tetapi sebenarnya bukan masalah sebenarnya.
trentclowater
1
Chrome melakukan pra-penerbangan permintaan untuk mencari header CORS jika permintaan lintas domain. Periksa jawaban saya.
Asim KT

Jawaban:

66

Saya mengambil apa yang Anda miliki, dan menambahkan X-Testingheader lain

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

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

Dan di tab jaringan Chrome, saya melihat pesan tersebut dikirim.

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

Apakah Anda tidak melihatnya dari browser, atau di server? Coba perkakas browser atau proxy debug dan lihat apa yang dikirim.

Kevin Hakanson
sumber
Saya tidak memiliki akses ke server, dan di browser saya menggunakan Firefox, tetapi saya melihat header yang saya tambahkan ke pertanyaan asli di atas. Saya tidak melihat di mana Anda dapat melihat header pada tab sumber daya di Chrome.
trentclowater
Maaf, saya menambahkan hasil edit pada jawaban Anda yang seharusnya ada pada pertanyaan awal saya.
trentclowater
Maksud saya tab jaringan alat pengembang, bukan sumber daya - jawaban pembaruan
Kevin Hakanson
Saya menambahkan lebih banyak informasi ke pertanyaan. Sepertinya tajuk ditambahkan dalam satu kasus, tetapi tidak pada kasus lain.
trentclowater
21

Otentikasi dasar menggunakan metode 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
    }
});

... dan panggilan metode GET dengan 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
sumber
Jawaban terbaik.
Yoda
9

Jika Anda ingin menambahkan tajuk khusus ke SEMUA permintaan, Anda dapat mengubah bawaan pada $ httpProvider untuk selalu menambahkan tajuk ini…

app.config(['$httpProvider', function ($httpProvider) {
    $httpProvider.defaults.headers.common = { 
        'Authorization': 'Basic d2VudHdvcnRobWFuOkNoYW5nZV9tZQ==',
        'Accept': 'application/json;odata=verbose'
      };
}]);
Korayem
sumber
SEMUA kecuali PILIHAN permintaan yaitu
Rocco
contoh yang bagus. dapatkah ini digunakan untuk menyimpan token untuk mengalihkan halaman?
Martian2049
7

Saran saya akan menambahkan pengaturan panggilan fungsi seperti ini di dalam fungsi periksa header yang sesuai untuk itu. Saya yakin ini pasti akan berhasil. itu bekerja dengan sempurna untuk saya.

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

lalu panggil data Anda seperti ini

    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);
Riyadh Ul Islam
sumber
2

Apa yang Anda lihat untuk permintaan OPTIONS baik-baik saja. Header otorisasi tidak ditampilkan di dalamnya.

Tetapi agar autentikasi dasar berfungsi, Anda perlu menambahkan: withCredentials = true;ke file var config.

Dari dokumentasi AngularJS $ http :

withCredentials - {boolean}- apakah akan menyetel withCredentials bendera pada objek XHR. Lihat permintaan dengan kredensial untuk informasi lebih lanjut.

Dmitry Evseev
sumber
1

Dan apa jawaban dari server? Ini harus membalas 204 dan kemudian benar-benar mengirim GET yang Anda minta.

Dalam OPSI klien memeriksa apakah server mengizinkan permintaan CORS. Jika itu memberi Anda sesuatu yang berbeda dari 204 maka Anda harus mengkonfigurasi server Anda untuk mengirim header Allow-Origin yang benar.

Cara Anda menambahkan tajuk adalah cara yang tepat untuk melakukannya.

ghostbar
sumber
1

Chrome melakukan pra-penerbangan permintaan untuk mencari header CORS. Jika permintaan diterima, permintaan sebenarnya akan dikirim. Jika Anda melakukan ini lintas-domain, Anda hanya perlu menanganinya atau mencari cara untuk membuat permintaan non-lintas-domain. Ini memang disengaja.

Tidak seperti permintaan sederhana (dibahas di atas), permintaan "preflighted" pertama-tama mengirim permintaan HTTP dengan metode OPTIONS ke sumber daya di domain lain, untuk menentukan apakah permintaan sebenarnya aman untuk dikirim. Permintaan lintas situs diatur sebelumnya seperti ini karena mungkin berdampak pada data pengguna. Secara khusus, permintaan dipraflight jika:

Ini menggunakan metode selain GET, HEAD atau POST. Selain itu, jika POST digunakan untuk mengirim data permintaan dengan Jenis Konten selain application / x-www-form-urlencoded, multipart / form-data, atau text / plain, misalnya jika permintaan POST mengirimkan payload XML ke server menggunakan application / xml atau text / xml, maka permintaan tersebut akan dikirim sebelumnya. Ini menetapkan tajuk khusus dalam permintaan (misalnya, permintaan menggunakan tajuk seperti X-PINGOTHER)

Ref: AJAX di Chrome mengirimkan OPTIONS alih-alih GET / POST / PUT / DELETE?

Asim KT
sumber
-8

Bagi saya, cuplikan penjelasan berikut berhasil. Mungkin sebaiknya Anda tidak menggunakan 'untuk nama header?

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

Saya menggunakan $http.ajax(), meskipun saya tidak berharap itu menjadi pengubah permainan.

ŁukaszBachman
sumber