Thêm tiêu đề tùy chỉnh vào yêu cầu HTTP bằng cách sử dụng angle.js


89

Tôi là người mới làm quen với angle.js và tôi đang cố gắng thêm một số tiêu đề vào một yêu cầu:

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

Tôi đã xem tất cả các tài liệu, và điều này đối với tôi dường như là đúng.

Khi tôi sử dụng tệp cục bộ cho URL trong $http.get, tôi thấy yêu cầu HTTP sau trên tab mạng trong 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

Như bạn có thể thấy, cả hai tiêu đề đã được thêm chính xác. Nhưng khi tôi thay đổi URL thành URL được hiển thị ở $http.gettrên (ngoại trừ sử dụng địa chỉ thực, không phải example.com), thì tôi nhận được:

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

Sự khác biệt duy nhất về mã giữa hai mã này là đối với URL đầu tiên là một tệp cục bộ và đối với URL thứ hai là một máy chủ từ xa. Nếu bạn nhìn vào tiêu đề Yêu cầu thứ hai, không có tiêu đề Xác thực và tiêu đề này Acceptdường như đang sử dụng mặc định thay vì được chỉ định. Ngoài ra, dòng đầu tiên hiện OPTIONSthay vì GET(mặc dù Access-Control-Request-MethodGET).

Bất kỳ ý tưởng nào sai với mã trên hoặc làm thế nào để lấy các tiêu đề bổ sung được bao gồm khi không sử dụng tệp cục bộ làm nguồn dữ liệu?


2
Đây trông giống như một vấn đề CORS - hãy đọc thông qua thảo luận này đối với một số nền: groups.google.com/forum/#!topic/angular/CSBMY6oXfqs
Kevin Hakanson

Đó thực sự là một vấn đề CORS. Máy chủ không được định cấu hình để trả về tiêu đề Access-Control-Allow-Origin:. Nếu bạn muốn viết câu trả lời kèm theo nhận xét của mình và một chút chi tiết về CORS, tôi sẽ chấp nhận câu trả lời của bạn. Câu trả lời dưới đây từ Dmitry Evseev và được bạn chỉnh sửa gần đúng, nhưng không thực sự là vấn đề thực tế.
trentclowater

1
Chrome đang đánh dấu trước yêu cầu tìm kiếm các tiêu đề CORS nếu yêu cầu là miền chéo. Kiểm tra câu trả lời của tôi.
Asim KT

Câu trả lời:


66

Tôi đã lấy những gì bạn có và thêm một X-Testingtiêu đề khác

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

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

Và trong tab mạng Chrome, tôi thấy chúng đang được gửi.

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

Bạn không nhìn thấy chúng từ trình duyệt hoặc trên máy chủ? Hãy thử công cụ trình duyệt hoặc proxy gỡ lỗi và xem những gì đang được gửi đi.


Tôi không có quyền truy cập vào máy chủ và trên trình duyệt, tôi đang sử dụng Firefox, nhưng tôi thấy các tiêu đề mà tôi đã thêm vào câu hỏi ban đầu ở trên. Tôi không biết bạn có thể xem tiêu đề ở đâu trên tab tài nguyên trong Chrome.
trentclowater

Xin lỗi, tôi đã thêm một chỉnh sửa cho câu trả lời của bạn, nghĩa là có trong câu hỏi ban đầu của tôi.
trentclowater

Ý tôi là tab mạng của các công cụ dành cho nhà phát triển, không phải tài nguyên - câu trả lời cập nhật
Kevin

Tôi đã thêm thông tin vào câu hỏi. Có vẻ như các tiêu đề được thêm vào một trường hợp này, nhưng không phải trường hợp khác.
trentclowater

21

Xác thực cơ bản bằng phương thức 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
    }
});

... và lệnh gọi phương thức GET với tiêu đề:

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

Câu trả lời tốt nhất.
Yoda

9

Nếu bạn muốn thêm tiêu đề tùy chỉnh của mình vào TẤT CẢ yêu cầu, bạn có thể thay đổi giá trị mặc định trên $ httpProvider để luôn thêm tiêu đề này…

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

TẤT CẢ trừ các yêu cầu TÙY CHỌN
Rocco

ví dụ tốt đẹp. điều này có thể được sử dụng để lưu mã thông báo bộ nhớ cache để chuyển hướng các trang không?
Martian2049,

7

đề xuất của tôi sẽ là thêm một cài đặt cuộc gọi hàm như thế này bên trong hàm, hãy kiểm tra tiêu đề phù hợp với nó. Tôi chắc chắn rằng nó chắc chắn sẽ hoạt động. nó hoàn toàn làm việc cho tôi.

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

sau đó gọi dữ liệu của bạn như thế này

    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

Những gì bạn thấy cho yêu cầu OPTIONS đều ổn. Tiêu đề ủy quyền không được hiển thị trong đó.

Nhưng để auth cơ bản hoạt động, bạn cần thêm: withCredentials = true;vào của bạn var config.

Từ tài liệu AngularJS $ http :

withCredentials - {boolean}- có đặt withCredentials cờ trên đối tượng XHR hay không. Xem các yêu cầu với thông tin xác thực để biết thêm thông tin.


1

Và câu trả lời từ máy chủ là gì? Nó sẽ trả lời 204 và sau đó thực sự gửi GET mà bạn đang yêu cầu.

Trong TÙY CHỌN, máy khách đang kiểm tra xem máy chủ có cho phép yêu cầu CORS hay không. Nếu nó cung cấp cho bạn một cái gì đó khác với 204 thì bạn nên định cấu hình máy chủ của mình để gửi các tiêu đề Allow-Origin chính xác.

Cách bạn thêm tiêu đề là cách làm đúng.


1

Chrome đang đánh dấu trước yêu cầu tìm kiếm các tiêu đề CORS. Nếu yêu cầu được chấp nhận, nó sẽ gửi yêu cầu thực sự. Nếu bạn đang thực hiện điều này giữa nhiều miền, bạn sẽ phải đối phó với nó hoặc tìm cách khác để thực hiện yêu cầu không liên miền. Đây là do thiết kế.

Không giống như các yêu cầu đơn giản (đã thảo luận ở trên), các yêu cầu "preflighted" trước tiên gửi một yêu cầu HTTP theo phương thức OPTIONS tới tài nguyên trên miền khác, để xác định xem yêu cầu thực sự có an toàn để gửi hay không. Yêu cầu trên nhiều trang web được đánh dấu trước như thế này vì chúng có thể có liên quan đến dữ liệu người dùng. Đặc biệt, một yêu cầu được đánh dấu trước nếu:

Nó sử dụng các phương thức khác ngoài GET, HEAD hoặc POST. Ngoài ra, nếu POST được sử dụng để gửi dữ liệu yêu cầu với Loại nội dung không phải là application / x-www-form-urlencoded, multiart / form-data, hoặc văn bản / đơn giản, ví dụ: nếu yêu cầu POST gửi tải trọng XML đến máy chủ sử dụng ứng dụng / xml hoặc văn bản / xml, sau đó yêu cầu được đánh dấu trước. Nó đặt tiêu đề tùy chỉnh trong yêu cầu (ví dụ: yêu cầu sử dụng tiêu đề như X-PINGOTHER)

Tham khảo: AJAX trong Chrome gửi TÙY CHỌN thay vì GET / POST / PUT / DELETE?


-8

Đối với tôi, đoạn mã giải thích sau đây đã hoạt động. Có lẽ bạn không nên sử dụng 'cho tên tiêu đề?

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

Tôi đang sử dụng $http.ajax(), mặc dù tôi không mong đợi điều đó sẽ thay đổi cuộc chơi.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.