Truy cập các tiêu đề HTTP của trang web bằng JavaScript


406

Làm cách nào để tôi truy cập các tiêu đề phản hồi HTTP của trang thông qua JavaScript?

Liên quan đến câu hỏi này , đã được sửa đổi để hỏi về việc truy cập hai tiêu đề HTTP cụ thể.

Liên quan:
Làm cách nào để tôi truy cập vào các trường tiêu đề yêu cầu HTTP thông qua JavaScript?


@ user2284570 - Không phải vậy. Câu hỏi này là về tiêu đề phản hồi , không phải tiêu đề yêu cầu .
Quentin

Câu trả lời:


365

Không thể đọc các tiêu đề hiện tại. Bạn có thể thực hiện một yêu cầu khác cho cùng một URL và đọc các tiêu đề của nó, nhưng không có gì đảm bảo rằng các tiêu đề chính xác bằng hiện tại.


Sử dụng mã JavaScript sau để nhận tất cả các tiêu đề HTTP bằng cách thực hiện getyêu cầu:

var req = new XMLHttpRequest();
req.open('GET', document.location, false);
req.send(null);
var headers = req.getAllResponseHeaders().toLowerCase();
alert(headers);

58
Saeed, có lẽ không tốt nhất cho tác giả câu hỏi .. Tôi đoán là vì nó không truy cập vào các tiêu đề của tài nguyên đã tải, nhưng đưa ra một yêu cầu mới .. rõ ràng anh ta biết rõ nhất, câu trả lời tốt nhất là gì và tự mình thực hiện
mykhal

18
Tùy thuộc vào tiêu đề của bạn sau khi bạn có thể muốn sử dụng động từ 'ĐẦU'.
scottrudy

17
Thực hiện một yêu cầu mới sẽ chỉ hoạt động nếu các giá trị phản hồi bạn cần được đảm bảo giống hệt nhau từ một yêu cầu tiếp theo. Nó sẽ phụ thuộc vào ứng dụng của bạn, vì vậy số dặm của bạn với cách tiếp cận như thế này sẽ thay đổi.
keparo

6
Bản hack này có thể hoạt động trong một số trường hợp, nhưng nó hoàn toàn không hoạt động nếu trang chứa tập lệnh được tạo để đáp ứng yêu cầu POST và không có ích gì nếu bạn đang cố xác định xem máy chủ có gặp lỗi không (HTTP 5XX) trong khi xử lý yêu cầu ban đầu.
đất sét

9
Câu trả lời này là sai lầm khủng khiếp. Câu trả lời đúng là "không thể". Hoặc để phù hợp với câu trả lời này "Không thể, nhưng đây là một hack để cố gắng mô phỏng nó mà có thể hoặc không thể hoạt động cho bạn".
Jan

301

Thật không may, không có API để cung cấp cho bạn tiêu đề phản hồi HTTP cho yêu cầu trang ban đầu của bạn. Đó là câu hỏi ban đầu được đăng ở đây. Nó cũng đã được hỏi nhiều lần , bởi vì một số người muốn nhận được các tiêu đề phản hồi thực tế của yêu cầu trang gốc mà không đưa ra một yêu cầu khác.


Đối với các yêu cầu AJAX:

Nếu một yêu cầu HTTP được thực hiện qua AJAX, có thể nhận được các tiêu đề phản hồi bằng getAllResponseHeaders()phương thức. Đây là một phần của API XMLHttpRequest. Để xem làm thế nào điều này có thể được áp dụng, hãy kiểm tra fetchSimilarHeaders()chức năng dưới đây. Lưu ý rằng đây là một cách giải quyết vấn đề không đáng tin cậy đối với một số ứng dụng.

myXMLHttpRequest.getAllResponseHeaders();

Điều này sẽ không cung cấp cho bạn thông tin về các tiêu đề phản hồi HTTP của yêu cầu trang gốc, nhưng nó có thể được sử dụng để đưa ra những phỏng đoán có giáo dục về những tiêu đề đó là gì. Thêm vào đó được mô tả tiếp theo.


Nhận giá trị tiêu đề từ Yêu cầu trang ban đầu:

Câu hỏi này lần đầu tiên được hỏi cách đây vài năm, hỏi cụ thể về cách lấy tiêu đề phản hồi HTTP gốc cho trang hiện tại (tức là cùng một trang bên trong mà javascript đang chạy). Đây là một câu hỏi hoàn toàn khác so với việc đơn giản là nhận các tiêu đề phản hồi cho bất kỳ yêu cầu HTTP nào. Đối với yêu cầu trang ban đầu, các tiêu đề không có sẵn cho javascript. Việc các giá trị tiêu đề bạn cần có đáng tin cậy và đủ nhất quán hay không nếu bạn yêu cầu lại cùng một trang thông qua AJAX sẽ tùy thuộc vào ứng dụng cụ thể của bạn.

Sau đây là một vài gợi ý để giải quyết vấn đề đó.


1. Yêu cầu về Tài nguyên chủ yếu là tĩnh

Nếu phản hồi chủ yếu là tĩnh và các tiêu đề dự kiến ​​sẽ không thay đổi nhiều giữa các yêu cầu, bạn có thể thực hiện yêu cầu AJAX cho cùng một trang mà bạn hiện đang truy cập và cho rằng chúng là cùng một giá trị là một phần của trang Phản hồi HTTP. Điều này có thể cho phép bạn truy cập các tiêu đề bạn cần bằng cách sử dụng API XMLHttpRequest đẹp được mô tả ở trên.

function fetchSimilarHeaders (callback) {
    var request = new XMLHttpRequest();
    request.onreadystatechange = function () {
        if (request.readyState === XMLHttpRequest.DONE) {
            //
            // The following headers may often be similar
            // to those of the original page request...
            //
            if (callback && typeof callback === 'function') {
                callback(request.getAllResponseHeaders());
            }
        }
    };

    //
    // Re-request the same page (document.location)
    // We hope to get the same or similar response headers to those which 
    // came with the current page, but we have no guarantee.
    // Since we are only after the headers, a HEAD request may be sufficient.
    //
    request.open('HEAD', document.location, true);
    request.send(null);
}

Cách tiếp cận này sẽ có vấn đề nếu bạn thực sự phải dựa vào các giá trị nhất quán giữa các yêu cầu, vì bạn không thể hoàn toàn đảm bảo rằng chúng giống nhau. Nó sẽ phụ thuộc vào ứng dụng cụ thể của bạn và liệu bạn có biết rằng giá trị bạn cần là thứ sẽ không thay đổi từ yêu cầu này sang yêu cầu tiếp theo.


2. Suy luận

một số thuộc tính BOM (Mô hình đối tượng trình duyệt) mà trình duyệt xác định bằng cách xem các tiêu đề. Một số thuộc tính này phản ánh trực tiếp các tiêu đề HTTP (ví dụ: navigator.userAgentđược đặt thành giá trị của trường User-Agenttiêu đề HTTP ). Bằng cách đánh hơi xung quanh các thuộc tính có sẵn, bạn có thể tìm thấy những gì bạn cần hoặc một số manh mối để cho biết phản hồi HTTP chứa gì.


3. Stash chúng

Nếu bạn kiểm soát phía máy chủ, bạn có thể truy cập bất kỳ tiêu đề nào bạn muốn khi bạn tạo phản hồi đầy đủ. Các giá trị có thể được chuyển đến máy khách với trang, được lưu trong một số đánh dấu hoặc có thể trong cấu trúc JSON được nội tuyến. Nếu bạn muốn có mọi tiêu đề yêu cầu HTTP có sẵn cho javascript của mình, bạn có thể lặp qua chúng trên máy chủ và gửi lại chúng dưới dạng các giá trị ẩn trong đánh dấu. Có thể không lý tưởng để gửi các giá trị tiêu đề theo cách này, nhưng bạn chắc chắn có thể làm điều đó cho giá trị cụ thể mà bạn cần. Giải pháp này được cho là không hiệu quả, nhưng nó sẽ thực hiện công việc nếu bạn cần nó.


2
Làm thế nào Google phát hiện ra nó như tôi đã giải thích ở đây: stackoverflow.com/questions/7191242/ trên
kamaci

Cập nhật RE: các yêu cầu ajax là một phần tiêu chuẩn của cách phát triển web từ năm 2008 cũng như -_-
BlueRaja - Danny Pflughoeft

5
BOM là viết tắt của "Model Object Browser", dành cho những ai thắc mắc. Xem stackoverflow.com/questions/2213594/ cho một số nền.
Myrne Stol

1
3) bạn cũng có thể bỏ chúng trong tiêu đề cookie http. Sau đó, bạn sẽ không cần phải thay đổi đánh dấu tài liệu.
skibulk

Có một cách đơn giản để truy cập các phần tử tiêu đề phản hồi, chẳng hạn như phần tử liên kết: sử dụng ví dụ tài liệu ở đây: gist.github.com/FunThomas424242/ Kẻ
FunThomas424242

28

Sử dụng XmlHttpRequestbạn có thể kéo lên trang hiện tại và sau đó kiểm tra các tiêu đề http của phản hồi.

Trường hợp tốt nhất là chỉ cần làm một HEADyêu cầu và sau đó kiểm tra các tiêu đề.

Đối với một số ví dụ về việc này, hãy xem http://www.jibbering.com/2002/4/httprequest.html

Chỉ cần 2 xu của tôi.


24

Một giải pháp với nhân viên phục vụ

Nhân viên dịch vụ có thể truy cập thông tin mạng, bao gồm các tiêu đề. Phần tốt là nó hoạt động trên bất kỳ loại yêu cầu nào, không chỉ XMLHttpRequest.

Làm thế nào nó hoạt động:

  1. Thêm một nhân viên dịch vụ trên trang web của bạn.
  2. Xem mọi yêu cầu được gửi đi.
  3. Làm cho nhân viên phục vụ fetchyêu cầu với respondWithchức năng.
  4. Khi phản hồi đến, đọc các tiêu đề.
  5. Gửi các tiêu đề từ nhân viên dịch vụ đến trang có postMessagechức năng.

Ví dụ làm việc:

Nhân viên dịch vụ hơi phức tạp để hiểu, vì vậy tôi đã xây dựng một thư viện nhỏ thực hiện tất cả điều này. Nó có sẵn trên github: https://github.com/gmetais/sw-get-headers .

Hạn chế:

  • trang web cần phải có trên HTTPS
  • trình duyệt cần hỗ trợ API Công nhân dịch vụ
  • các chính sách cùng tên miền / tên miền chéo đang hoạt động, giống như trên XMLHttpRequest

12

Đối với những người đang tìm cách phân tích tất cả các tiêu đề HTTP thành một đối tượng có thể được truy cập dưới dạng từ điển headers["content-type"], tôi đã tạo một hàm parseHttpHeaders:

function parseHttpHeaders(httpHeaders) {
    return httpHeaders.split("\n")
     .map(x=>x.split(/: */,2))
     .filter(x=>x[0])
     .reduce((ac, x)=>{ac[x[0]] = x[1];return ac;}, {});
}

var req = new XMLHttpRequest();
req.open('GET', document.location, false);
req.send(null);
var headers = parseHttpHeaders(req.getAllResponseHeaders());
// Now we can do:  headers["content-type"]

10

Một cách khác để gửi thông tin tiêu đề đến JavaScript sẽ thông qua cookie. Máy chủ có thể trích xuất bất kỳ dữ liệu nào nó cần từ các tiêu đề yêu cầu và gửi lại chúng trong Set-Cookietiêu đề phản hồi - và cookie có thể được đọc bằng JavaScript. Tuy nhiên, như keparo nói, tốt nhất là làm điều này chỉ với một hoặc hai tiêu đề, thay vì cho tất cả chúng.


1
Cách tiếp cận này vẫn yêu cầu bạn kiểm soát máy chủ cho JS của mình. Bất kể bạn truyền đạt thông tin đó như thế nào, mã của bạn đột nhiên không thể truy cập được. Tại sao không tạo API cho yêu cầu cụ thể đó để tránh làm hỏng yêu cầu đối với tài sản ban đầu?
MST

5

Nếu chúng ta đang nói về các tiêu đề Yêu cầu , bạn có thể tạo các tiêu đề của riêng mình khi thực hiện XmlHttpRequests.

var request = new XMLHttpRequest();
request.setRequestHeader("X-Requested-With", "XMLHttpRequest");
request.open("GET", path, true);
request.send(null);

bạn sẽ không thể sửa đổi tiêu đề yêu cầu trong mozilla vì lý do bảo mật. mxr.mozilla.org/mozilla1.8.0/source/extensions/xmlextras/base/ Kẻ
user121196

1
Bạn phải gọi open () trước khi sử dụng phương thức setRequestHeader (). developer.mozilla.org/en/
Kẻ

1
Truy cập, trong câu hỏi ban đầu, là về việc nhận các tiêu đề, không đặt tiêu đề.
Timo Tijhof

4

Bạn không thể truy cập các tiêu đề http, nhưng một số thông tin được cung cấp trong chúng có sẵn trong DOM. Ví dụ: nếu bạn muốn xem người giới thiệu http (sic), hãy sử dụng document.referrer. Có thể có những cái khác như thế này cho các tiêu đề http khác. Hãy thử googling điều cụ thể mà bạn muốn, như "javascript giới thiệu http".

Tôi biết điều này là hiển nhiên, nhưng tôi vẫn tiếp tục tìm kiếm những thứ như "javascript tiêu đề" khi tất cả những gì tôi thực sự muốn là người giới thiệu và không nhận được bất kỳ kết quả hữu ích nào. Tôi không biết làm thế nào tôi không nhận ra tôi có thể thực hiện một truy vấn cụ thể hơn.


4

Giống như nhiều người tôi đã đào mạng mà không có câu trả lời thực sự :(

Tuy nhiên, tôi đã tìm ra một đường vòng có thể giúp đỡ người khác. Trong trường hợp của tôi, tôi hoàn toàn kiểm soát máy chủ web của mình. Trong thực tế, nó là một phần của ứng dụng của tôi (xem tài liệu tham khảo cuối). Thật dễ dàng cho tôi để thêm một tập lệnh vào phản hồi http của tôi. Tôi đã sửa đổi máy chủ httpd của mình để thêm một tập lệnh nhỏ trong mỗi trang html. Tôi chỉ đẩy thêm một dòng 'js script' ngay sau khi xây dựng tiêu đề của mình, nó đặt một biến hiện có từ tài liệu của tôi trong trình duyệt của tôi [Tôi chọn vị trí], nhưng có thể có bất kỳ tùy chọn nào khác. Trong khi máy chủ của tôi được viết bằng nodejs, tôi không nghi ngờ rằng kỹ thuật tương tự có thể được sử dụng từ PHP hoặc người khác.

  case ".html":
    response.setHeader("Content-Type", "text/html");
    response.write ("<script>location['GPSD_HTTP_AJAX']=true</script>")
    // process the real contend of my page

Bây giờ mọi trang html được tải từ máy chủ của tôi, có tập lệnh này được trình duyệt thực thi tại quầy lễ tân. Sau đó tôi có thể dễ dàng kiểm tra từ JavaScript nếu biến tồn tại hay không. Trong usecase của tôi, tôi cần biết liệu tôi nên sử dụng hồ sơ JSON hoặc JSON-P để tránh sự cố CORS, nhưng kỹ thuật tương tự có thể được sử dụng cho các mục đích khác [ví dụ: chọn giữa máy chủ phát triển / sản xuất, lấy từ máy chủ REST / API chìa khóa, v.v ....]

Trên trình duyệt, bạn chỉ cần kiểm tra biến trực tiếp từ JavaScript như trong ví dụ của tôi, nơi tôi sử dụng nó để chọn hồ sơ Json / JQuery của mình

 // Select direct Ajax/Json profile if using GpsdTracking/HttpAjax server otherwise use JsonP
  var corsbypass = true;  
  if (location['GPSD_HTTP_AJAX']) corsbypass = false;

  if (corsbypass) { // Json & html served from two different web servers
    var gpsdApi = "http://localhost:4080/geojson.rest?jsoncallback=?";
  } else { // Json & html served from same web server [no ?jsoncallback=]
    var gpsdApi = "geojson.rest?";
  }
  var gpsdRqt = 
      {key   :123456789 // user authentication key
      ,cmd   :'list'    // rest command
      ,group :'all'     // group to retreive
      ,round : true     // ask server to round numbers
   };
   $.getJSON(gpsdApi,gpsdRqt, DevListCB);

Dành cho những ai muốn kiểm tra mã của tôi: https://www.npmjs.org/package/gypetracking


3

Sử dụng mootools, bạn có thể sử dụng this.xhr.get ALLResponseHeaders ()


3

Tôi vừa mới thử nghiệm và điều này hoạt động với tôi bằng Chrome Phiên bản 28.0.1500.95.

Tôi cần tải tập tin và đọc tên tập tin. Tên tệp nằm trong tiêu đề nên tôi đã làm như sau:

var xhr = new XMLHttpRequest(); 
xhr.open('POST', url, true); 
xhr.responseType = "blob";
xhr.onreadystatechange = function () { 
    if (xhr.readyState == 4) {
        success(xhr.response); // the function to proccess the response

        console.log("++++++ reading headers ++++++++");
        var headers = xhr.getAllResponseHeaders();
        console.log(headers);
        console.log("++++++ reading headers end ++++++++");

    }
};

Đầu ra:

Date: Fri, 16 Aug 2013 16:21:33 GMT
Content-Disposition: attachment;filename=testFileName.doc
Content-Length: 20
Server: Apache-Coyote/1.1
Content-Type: application/octet-stream

2

Đây là kịch bản của tôi để có được tất cả các tiêu đề phản hồi:

var url = "< URL >";

var req = new XMLHttpRequest();
req.open('HEAD', url, false);
req.send(null);
var headers = req.getAllResponseHeaders();

//Show alert with response headers.
alert(headers);

Có kết quả là các tiêu đề phản ứng.

nhập mô tả hình ảnh ở đây

Đây là một thử nghiệm so sánh bằng Hurl.it:

nhập mô tả hình ảnh ở đây


2

Để có được các tiêu đề như một đối tượng dễ xử lý hơn (cải thiện câu trả lời của Raja ):

var req = new XMLHttpRequest();
req.open('GET', document.location, false);
req.send(null);
var headers = req.getAllResponseHeaders().toLowerCase();
headers = headers.split(/\n|\r|\r\n/g).reduce(function(a, b) {
    if (b.length) {
        var [ key, value ] = b.split(': ');
        a[key] = value;
    }
    return a;
}, {});
console.log(headers);

2

Liên kết của Allain Lalonde làm cho ngày của tôi. Chỉ cần thêm một số mã html làm việc đơn giản ở đây.
Hoạt động với mọi trình duyệt hợp lý từ độ tuổi cộng với IE9 + và Presto-Opera 12.

<!DOCTYPE html>
<title>(XHR) Show all response headers</title>

<h1>All Response Headers with XHR</h1>
<script>
 var X= new XMLHttpRequest();
 X.open("HEAD", location);
 X.send();
 X.onload= function() { 
   document.body.appendChild(document.createElement("pre")).textContent= X.getAllResponseHeaders();
 }
</script>

Lưu ý: Bạn nhận được các tiêu đề của yêu cầu thứ hai, kết quả có thể khác với yêu cầu ban đầu.


Một cách khác
là hiện đại hơn fetch()API
https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch
mỗi caniuse.com nó được hỗ trợ bởi trình duyệt Firefox 40, Chrome 42, Edge 14, Safari 11
ví dụ làm việc mã:

<!DOCTYPE html>
<title>fetch() all Response Headers</title>

<h1>All Response Headers with fetch()</h1>
<script>
 var x= "";
 if(window.fetch)
    fetch(location, {method:'HEAD'})
    .then(function(r) {
       r.headers.forEach(
          function(Value, Header) { x= x + Header + "\n" + Value + "\n\n"; }
       );
    })
    .then(function() {
       document.body.appendChild(document.createElement("pre")).textContent= x;
    });
 else
   document.write("This does not work in your browser - no support for fetch API");
</script>

0

Đây là một câu hỏi cũ. Bạn không chắc chắn khi hỗ trợ đã trở nên rộng hơn, nhưng getAllResponseHeaders()getResponseHeader()xuất hiện đến nay là khá chuẩn: http://www.w3schools.com/xml/dom_http.asp


50
getAllResponseHeaders () và getResponseHeader () là các phương thức của đối tượng XMLHttpRequest. Tức là cho các yêu cầu ajax. Bạn không thể sử dụng các phương pháp đó để xem các tiêu đề của trang ban đầu - đó là điều tôi nghĩ rằng câu hỏi ban đầu thực sự đang hỏi.
asgeo1

-1

Như đã được đề cập, nếu bạn kiểm soát phía máy chủ thì có thể gửi các tiêu đề yêu cầu ban đầu trở lại máy khách trong phản hồi ban đầu.

Trong Express, ví dụ, các công việc sau:

app.get('/somepage', (req, res) => { res.render('somepage.hbs', {headers: req.headers}); }) Các tiêu đề sau đó có sẵn trong mẫu, do đó có thể được ẩn một cách trực quan nhưng được bao gồm trong đánh dấu và được đọc bởi javascript của khách hàng.


Câu hỏi là hỏi về tiêu đề phản hồi , không yêu cầu tiêu đề.
Quentin

-1

Tôi nghĩ rằng câu hỏi đã đi sai hướng, Nếu bạn muốn lấy tiêu đề Yêu cầu từ JQuery / JavaScript, câu trả lời chỉ đơn giản là Không. Các giải pháp khác là tạo trang aspx hoặc trang jsp thì chúng ta có thể dễ dàng truy cập vào tiêu đề yêu cầu. Nhận tất cả các yêu cầu trong trang aspx và đưa vào một phiên / cookie sau đó bạn có thể truy cập các cookie trong trang JavaScript ..


1
Câu hỏi là hỏi về việc đọc các tiêu đề phản hồi . Nó đề cập đến các tiêu đề yêu cầu chỉ trong bối cảnh của câu hỏi có thể liên quan.
Quentin
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.