การเพิ่มส่วนหัวที่กำหนดเองในคำขอ 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 เป็น 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
Kevin Hakanson

มันเป็นปัญหา CORS เซิร์ฟเวอร์ไม่ได้กำหนดค่าให้ส่งคืนส่วนหัว Access-Control-Allow-Origin: หากคุณต้องการเขียนคำตอบพร้อมความคิดเห็นของคุณและรายละเอียดเล็กน้อยเกี่ยวกับ CORS ฉันจะยอมรับคำตอบของคุณ คำตอบด้านล่างจาก Dmitry Evseev และแก้ไขโดยคุณนั้นใกล้เคียง แต่ไม่ใช่ปัญหาที่แท้จริง
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

ฉันหมายถึงแท็บเครือข่ายของเครื่องมือสำหรับนักพัฒนาไม่ใช่ทรัพยากร - คำตอบการอัปเดต
Kevin Hakanson

ฉันเพิ่มข้อมูลเพิ่มเติมในคำถาม ดูเหมือนว่าส่วนหัวจะถูกเพิ่มในกรณีหนึ่ง แต่ไม่ใช่อีกกรณีหนึ่ง
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
    }
});

... และรับวิธีการโทรด้วยส่วนหัว:

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

คำตอบที่ดีที่สุด.
Yoda

9

หากคุณต้องการเพิ่มส่วนหัวที่กำหนดเองลงในคำขอทั้งหมดคุณสามารถเปลี่ยนค่าเริ่มต้นของ $ httpProvider เพื่อเพิ่มส่วนหัวนี้ได้เสมอ ...

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

คำขอทั้งหมดยกเว้นตัวเลือกนั่นคือ
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 หากคำขอเป็นที่ยอมรับก็จะส่งคำขอจริง หากคุณกำลังดำเนินการข้ามโดเมนคุณจะต้องจัดการกับมันไม่เช่นนั้นจะหาวิธีที่จะทำให้คำขอไม่ข้ามโดเมน นี่คือการออกแบบ

ซึ่งแตกต่างจากคำขอทั่วไป (ที่กล่าวถึงข้างต้น) คำขอ "preflighted" จะส่งคำขอ HTTP โดยวิธี OPTIONS ไปยังทรัพยากรในโดเมนอื่นก่อนเพื่อพิจารณาว่าคำขอจริงนั้นปลอดภัยที่จะส่งหรือไม่ คำขอข้ามไซต์จะมีการระบุไว้ล่วงหน้าเช่นนี้เนื่องจากอาจมีผลกระทบต่อข้อมูลผู้ใช้ โดยเฉพาะอย่างยิ่งคำขอจะถูกระบุไว้ล่วงหน้าหาก:

ใช้วิธีอื่นที่ไม่ใช่ GET, HEAD หรือ POST นอกจากนี้หากใช้ POST เพื่อส่งข้อมูลการร้องขอด้วย Content-Type อื่นที่ไม่ใช่ application / x-www-form-urlencoded, multipart / form-data หรือ text / plain เช่นหากคำขอ POST ส่งเพย์โหลด XML ไปยังเซิร์ฟเวอร์ โดยใช้แอปพลิเคชัน / xml หรือข้อความ / xml จากนั้นคำขอจะถูกระบุไว้ล่วงหน้า ตั้งค่าส่วนหัวที่กำหนดเองในคำขอ (เช่นคำขอใช้ส่วนหัวเช่น X-PINGOTHER)

อ้าง: AJAX ใน Chrome ส่ง OPTIONS แทน GET / POST / PUT / DELETE?


0

คุณกำลังเพิ่มส่วนหัวที่เซิร์ฟเวอร์ไม่อนุญาต

เช่น - เซิร์ฟเวอร์ของคุณได้รับการตั้งค่า CORS ให้อนุญาตเฉพาะส่วนหัวเหล่านี้เท่านั้น (ยอมรับ, การควบคุมแคช, pragma, ประเภทเนื้อหา, ที่มา)

และในคำขอ http ของคุณคุณกำลังเพิ่มสิ่งนี้

 headers: {
        'Authorization': 'Basic d2VudHdvcnRobWFuOkNoYW5nZV9tZQ==',
        'Accept': 'application/json',
        'x-testing': 'testingValue'
    }

จากนั้นเซิร์ฟเวอร์จะปฏิเสธคำขอนี้เนื่องจากไม่อนุญาต (การอนุญาตและการทดสอบ x)

นี่คือการกำหนดค่าฝั่งเซิร์ฟเวอร์

และไม่มีอะไรเกี่ยวข้องกับตัวเลือก HTTP มันเป็นเพียงแค่พรีไลต์ไปยังเซิร์ฟเวอร์ซึ่งมาจากโดเมนอื่นเพื่อตรวจสอบว่าเซิร์ฟเวอร์อนุญาตให้โทรจริงหรือไม่


-8

สำหรับฉันตัวอย่างข้อมูลอธิบายต่อไปนี้ใช้งานได้ บางทีคุณไม่ควรใช้'สำหรับชื่อส่วนหัว?

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

ฉันใช้$http.ajax()แม้ว่าฉันจะไม่คาดหวังว่ามันจะเป็นตัวเปลี่ยนเกม

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.