Доступ к HTTP-заголовкам веб-страницы в JavaScript

Как получить доступ к заголовкам HTTP-ответов страницы через JavaScript?

Относится к этот вопрос, который был изменен, чтобы запрашивать доступ к двум конкретным заголовкам HTTP.

Related:
How do I access the HTTP request header fields via JavaScript?

@ user2284570 - Нет. этот вопрос касается заголовков отклик, а не заголовков запрос.

Quentin 05.12.2018 20:06

Хотя вы не можете подготовить любые заголовки ответа HTML в JS, вы может читаете заголовок Server-Timing, и вы можете передавать через него произвольные данные ключ-значение. См. мой ответ.

jakub.g 15.02.2021 19:20
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
429
2
656 504
18
Перейти к ответу Данный вопрос помечен как решенный

Ответы 18

Ответ принят как подходящий

К сожалению, не существует API, который предоставил бы вам заголовки HTTP-ответа для вашего начального запроса страницы. Это был исходный вопрос, размещенный здесь. Это тоже было неоднократно спрашивал, потому что некоторые люди хотели бы получить фактические заголовки ответа исходного запроса страницы, не отправляя другой.


Для запросов AJAX:

Если HTTP-запрос выполняется через AJAX, можно получить заголовки ответа с помощью метода getAllResponseHeaders(). Это часть API XMLHttpRequest. Чтобы увидеть, как это можно применить, ознакомьтесь с функцией fetchSimilarHeaders() ниже. Обратите внимание, что это решение проблемы, которое не будет надежным для некоторых приложений.

myXMLHttpRequest.getAllResponseHeaders();

Это не даст вам информации о заголовках HTTP-ответа исходного запроса страницы, но его можно использовать для обоснованного предположения о том, что это за заголовки. Подробнее об этом рассказывается далее.


Получение значений заголовка из запроса начальной страницы:

Этот вопрос впервые был задан несколько лет назад, в частности, как получить исходные заголовки HTTP-ответа для текущая страница (т.е. ту же страницу, внутри которой был запущен javascript). Это совсем другой вопрос, чем просто получение заголовков ответа на любой HTTP-запрос. Для исходного запроса страницы заголовки недоступны для javascript. Будет ли нужные вам значения заголовка надежно и достаточно согласованными, если вы снова запросите ту же страницу через AJAX, будет зависеть от вашего конкретного приложения.

Ниже приведены несколько советов по решению этой проблемы.


1. Запросы к ресурсам, которые в основном статичны

Если ответ в основном статический и не ожидается, что заголовки сильно изменятся между запросами, вы можете сделать запрос AJAX для той же страницы, на которой вы сейчас находитесь, и предположить, что это те же значения, которые были частью страницы. HTTP-ответ. Это может позволить вам получить доступ к нужным заголовкам с помощью красивого API XMLHttpRequest, описанного выше.

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

Этот подход будет проблематичным, если вам действительно придется полагаться на согласованность значений между запросами, поскольку вы не можете полностью гарантировать, что они одинаковы. Это будет зависеть от вашего конкретного приложения и от того, знаете ли вы, что нужное вам значение не будет меняться от одного запроса к другому.


2. Делать выводы

Есть некоторые свойства спецификации (объектная модель браузера), которую браузер определяет, просматривая заголовки. Некоторые из этих свойств напрямую отражают заголовки HTTP (например, для navigator.userAgent установлено значение поля заголовка HTTP User-Agent). Обнюхивая доступные свойства, вы можете найти то, что вам нужно, или некоторые подсказки, чтобы указать, что содержится в ответе HTTP.


3. Спрятать их

Если вы контролируете сторону сервера, вы можете получить доступ к любому заголовку, который вам нравится, при построении полного ответа. Значения могут быть переданы клиенту вместе со страницей, спрятаны в некоторой разметке или, возможно, во встроенной структуре JSON. Если вы хотите, чтобы каждый заголовок HTTP-запроса был доступен для вашего javascript, вы могли бы перебирать их на сервере и отправлять их обратно как скрытые значения в разметке. Вероятно, это не идеальный вариант для отправки значений заголовков таким образом, но вы, безусловно, можете сделать это для конкретного значения, которое вам нужно. Возможно, это решение тоже неэффективно, но оно сработает, если вам это нужно.

Как Google обнаруживает это, как я объяснил здесь: stackoverflow.com/questions/7191242/…

kamaci 25.08.2011 17:50

Обновление RE: запросы ajax были стандартной частью веб-разработки еще в 2008 году -_-

BlueRaja - Danny Pflughoeft 04.02.2012 02:02

Для тех, кому интересно, BOM расшифровывается как «объектная модель браузера». См. stackoverflow.com/questions/2213594/… для некоторой предыстории.

Myrne Stol 28.03.2013 22:47

3) вы также можете спрятать их в заголовке http cookie. Тогда вам не нужно будет менять разметку документа.

skibulk 26.11.2014 05:51

Есть простой способ получить доступ к элементам заголовка ответа, таким как элемент ссылки: используйте здесь пример документа: gist.github.com/FunThomas424242/…

Huluvu424242 24.05.2015 19:21

Если ваша страница отображается с использованием html-шаблонов и вы управляете серверным кодом, вы можете спрятать переменные в скрытый div, который javascript может считывать в переменную. <div id = 'myvar' class = 'hide'> {{myvar}} </div>

intotecho 17.02.2016 00:14

URL-адрес @ Huluvu424242 выдает 404

Kumar 12.08.2020 06:53

@Kumar - спасибо за подсказку. Я сменил пользователя для развертываний. Итак, ссылка теперь: gist.github.com/Huluvu424242/…

Huluvu424242 25.08.2020 11:50

Просто добавьте к этому. Теперь вы можете сделать это с помощью функции fetch (), которая поддерживается в Chrome, Edge и Firefox. stevemiller.dev/2019/…

sproketboy 19.11.2020 16:46

Другой способ отправить информацию заголовка в JavaScript - это файлы cookie. Сервер может извлекать любые данные из заголовков запроса и отправлять их обратно в заголовке ответа Set-Cookie, а файлы cookie можно читать в JavaScript. Однако, как говорит Кепаро, лучше сделать это только для одного или двух заголовков, а не для всех.

Этот подход по-прежнему требует, чтобы вы контролировали сервер для вашего JS. Независимо от того, как вы передаете эту информацию, ваш код внезапно стал некэшируемым. Почему бы просто не создать API для этого конкретного запроса, чтобы не повредить запрос на исходный актив?

MST 04.07.2016 20:00

Если мы говорим о заголовках Запрос, вы можете создавать свои собственные заголовки при выполнении XmlHttpRequests.

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

вы не сможете изменить заголовок запроса в Mozilla по соображениям безопасности. mxr.mozilla.org/mozilla1.8.0/source/extensions/xmlextras/bas‌ e /…

user121196 13.08.2009 00:07

Вы должны вызвать open () перед использованием метода setRequestHeader (). developer.mozilla.org/en/…

XP1 09.08.2011 14:00

В исходном вопросе Access - это получение заголовков, а не установка заголовков.

Timo Tijhof 12.02.2016 18:32

Используя XmlHttpRequest, вы можете открыть текущую страницу, а затем изучить http-заголовки ответа.

В лучшем случае просто выполните запрос HEAD, а затем изучите заголовки.

Некоторые примеры этого можно найти в http://www.jibbering.com/2002/4/httprequest.html.

Только мои 2 цента.

Именно то, о чем я думал

FooBar 08.12.2020 20:56

Используя mootools, вы можете использовать this.xhr.getAllResponseHeaders ()

Это старый вопрос. Не уверен, когда поддержка стала более широкой, но getAllResponseHeaders() и getResponseHeader() теперь кажутся довольно стандартными: http://www.w3schools.com/xml/dom_http.asp

getAllResponseHeaders () и getResponseHeader () - это методы объекта XMLHttpRequest. Т.е. для запросов ajax. Вы не можете использовать эти методы для просмотра заголовков начальной страницы - это то, что, я думаю, действительно задавал исходный вопрос.

asgeo1 18.04.2011 02:08

Невозможно прочитать текущие заголовки. Вы можете сделать еще один запрос к тому же URL-адресу и прочитать его заголовки, но нет гарантии, что заголовки в точности равны текущему.


Используйте следующий код JavaScript, чтобы получить все заголовки HTTP, выполнив запрос get:

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

Саид, может быть, не лучший вариант для автора вопроса ... Я думаю, это потому, что он не обращается к заголовкам загруженного ресурса, а делает новый запрос ... очевидно, он знает лучше всех, какой лучший ответ, и сделал его сам

mykhal 28.07.2011 14:22

Я бы подумал о том, чтобы пометить это, чтобы модератор мог правильно отметить. Отвечает на проблему, как указано.

thesmart 28.12.2011 08:41

В зависимости от того, какой заголовок вы идете после, вы можете использовать глагол «HEAD».

scottrudy 02.03.2012 02:39

Я считаю, что заголовки файлов cookie опущены.

Olivier Lalonde 26.04.2013 01:28

можете ли вы изменить заголовок ответа, чтобы браузер действовал определенным образом

Muhammad Umer 10.07.2013 22:30

Создание нового запроса будет работать только в том случае, если необходимые вам значения ответа будут идентичны от одного запроса к другому. Это будет зависеть от вашего приложения, поэтому ваш опыт при таком подходе будет отличаться.

keparo 17.08.2013 06:21

Этот взлом может сработать в некоторых сценариях, но он не будет работать вообще, если страница, содержащая сценарий, была сгенерирована в ответ на запрос POST, и не поможет, если вы пытаетесь определить, обнаружил ли сервер ошибку. (HTTP 5XX) при обработке исходного запроса.

claymation 23.10.2014 16:04

Также есть GetResponseHeader('headerName'), если вас интересует только значение одного заголовка, что, на мой взгляд, является наиболее распространенным вариантом использования.

BlueRaja - Danny Pflughoeft 14.01.2015 19:16

Этот ответ ужасно неверен. Правильный ответ - «это невозможно». Или, чтобы соответствовать этому ответу: «Это невозможно, но вот хак, чтобы попытаться смоделировать это, которое может или не может работать для вас вообще».

Jan 04.09.2015 19:37

Я видел людей, которые просили разъяснений по этому и связанным с ним вопросам ... * почему * браузер не может получить доступ к текущим заголовкам страниц? Есть ли где-нибудь спецификация браузера, в которой сказано «нет» и, возможно, объясняется причина?

jabits 08.06.2018 01:26

Вы не можете получить доступ к заголовкам http, но некоторая информация, представленная в них, доступна в DOM. Например, если вы хотите увидеть http referer (sic), используйте document.referrer. Для других заголовков http могут быть и другие подобные. Попробуйте поискать в Google конкретную вещь, например "http referer javascript".

Я знаю, что это должно быть очевидно, но я продолжал искать такие вещи, как «http headers javascript», когда все, что мне действительно нужно, это реферер, и не получил никаких полезных результатов. Не знаю, как я не понял, что могу задать более конкретный запрос.

Я только что протестировал, и у меня это работает с использованием Chrome версии 28.0.1500.95.

Мне нужно было загрузить файл и прочитать имя файла. Имя файла указано в заголовке, поэтому я сделал следующее:

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.info("++++++ reading headers ++++++++");
        var headers = xhr.getAllResponseHeaders();
        console.info(headers);
        console.info("++++++ reading headers end ++++++++");

    }
};

Выход:

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

Как и многие люди, я копался в сети без реального ответа :(

Тем не менее, я нашел обходной путь, который может помочь другим. В моем случае я полностью контролирую свой веб-сервер. Фактически это часть моего приложения (см. Конец ссылки). Мне легко добавить скрипт в свой HTTP-ответ. Я модифицировал свой httpd-сервер, чтобы вставлять небольшой скрипт в каждую HTML-страницу. Я только добавляю дополнительную строку 'js script' сразу после создания моего заголовка, которая устанавливает существующую переменную из моего документа в моем браузере [я выбираю местоположение], но возможен любой другой вариант. Хотя мой сервер написан на nodejs, я не сомневаюсь, что тот же метод можно использовать в PHP или других.

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

Теперь все html-страницы, загруженные с моего сервера, выполняются браузером при приеме. Затем я могу легко проверить с помощью JavaScript, существует ли переменная или нет. В моем случае мне нужно знать, следует ли использовать профиль JSON или JSON-P, чтобы избежать проблемы CORS, но тот же метод можно использовать для других целей [например: выбор между сервером разработки / производства, получение с сервера REST / API ключ и т.д ....]

В браузере вам просто нужно проверить переменную прямо из JavaScript, как в моем примере, где я использую ее для выбора своего профиля Json / JQuery.

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

Для тех, кто когда-нибудь захочет проверить мой код: https://www.npmjs.org/package/gpsdtracking

Решение с Service Workers

Сервисные работники могут получить доступ к сетевой информации, включая заголовки. Хорошо то, что он работает с любым запросом, а не только с XMLHttpRequest.

Как это работает:

  1. Добавьте сервисного работника на свой сайт.
  2. Следите за каждым отправляемым запросом.
  3. Сделайте запрос сервисному работнику fetch с помощью функции respondWith.
  4. Когда придет ответ, прочтите заголовки.
  5. Отправьте заголовки от сервис-воркера на страницу с функцией postMessage.

Рабочий пример:

Сервис-воркеры немного сложны для понимания, поэтому я создал небольшую библиотеку, которая делает все это. Он доступен на github: https://github.com/gmetais/sw-get-headers.

Ограничения:

  • сайт должен быть на HTTPS
  • браузер должен поддерживать API Сервисные работники
  • действуют те же доменные / междоменные политики, как и в XMLHttpRequest

Для тех, кто ищет способ преобразовать все заголовки HTTP в объект, к которому можно получить доступ как словарь headers["content-type"], я создал функцию 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"]

Это мой сценарий для получения всех заголовков ответов:

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

Получив в результате заголовки ответа.

Это сравнительный тест с использованием Hurl.it:

Как уже упоминалось, если вы контролируете серверную часть, тогда должна быть возможность отправить первоначальные заголовки запроса обратно клиенту в первоначальном ответе.

В Express, например, работает следующее:

app.get('/somepage', (req, res) => { res.render('somepage.hbs', {headers: req.headers}); }) Заголовки становятся доступными в шаблоне, поэтому их можно скрыть визуально, но включить в разметку и прочитать клиентским javascript.

Вопрос касается заголовков отклик, а не заголовков запросов.

Quentin 05.12.2018 20:07

Чтобы получить заголовки как более удобный объект (улучшение Ответ раджи):

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.info(headers);

Я думаю, вопрос задан неверно, Если вы хотите получить заголовок запроса из JQuery / JavaScript, ответ будет просто Нет. Другие решения - создать страницу aspx или страницу jsp, тогда мы сможем легко получить доступ к заголовку запроса. Возьмите весь запрос на странице aspx и поместите в сеанс / файлы cookie, после чего вы сможете получить доступ к файлам cookie на странице JavaScript ..

Вопрос в том, чтобы прочитать заголовки отклик. Заголовки запроса упоминаются только в контексте, возможно, связанного вопроса.

Quentin 05.12.2018 20:05

Ссылка Аллена Лалонда сделала мой день лучше. Просто добавьте сюда простой рабочий HTML-код.
Работает с любым разумным браузером с давних времен, плюс IE9 + и 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>

Примечание: вы получаете заголовки второго запроса, результат может отличаться от исходного запроса.


Другой путь
is the more modern fetch() API
https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch
Per caniuse.com it's supported by Firefox 40, Chrome 42, Edge 14, Safari 11
Working example code:
<!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>

Ответ на дополнительный HTTP-вызов без

Хотя в целом не может читать произвольные заголовки HTTP-ответа HTML-навигации верхнего уровня, если вы управляете сервером (или промежуточными ящиками в пути) и хотите предоставить JavaScript некоторую информацию, которую нельзя легко раскрыть другим способом чем через заголовок:

Вы можете использовать заголовок Server-Timing для предоставления произвольных данных "ключ-значение", и он будет доступен для чтения JavaScript.

(* в поддерживаемых браузерах: Firefox 61, Chrome 65, Edge 79; Safari еще нет с 2021.02; нет IE)

Пример:

server-timing: key;desc = "value"
server-timing: key1;desc = "value1"
server-timing: key2;desc = "value2"
  • или используйте его компактную версию, в которой вы представляете несколько фрагментов данных в одном заголовке, разделенных запятыми.
server-timing: key1;desc = "value1", key2;desc = "value2"

Пример того, как Википедия использует этот заголовок для предоставления информации о попаданиях / промахах в кеш:

Usage of server-timing response header on Wikipedia

Пример кода (необходимо учитывать отсутствие поддержки браузеров в Safari и IE):

if (window.performance && performance.getEntriesByType) { // avoid error in Safari 10, IE9- and other old browsers
    let navTiming = performance.getEntriesByType('navigation')
    if (navTiming.length > 0) { // still not supported as of Safari 14...
        let serverTiming = navTiming[0].serverTiming
        if (serverTiming && serverTiming.length > 0) {
            for (let i=0; i<serverTiming.length; i++) {
                console.info(`${serverTiming[i].name} = ${serverTiming[i].description}`)
            }
        }
    }
}

Это регистрирует cache = hit-front в поддерживаемых браузерах.

Заметки:

  • как упоминалось в MDN, API поддерживается только по HTTPS
  • если ваш JS обслуживается из другого домена, вам необходимо добавить заголовок ответа Время-Разрешить-Происхождение, чтобы данные были доступны для чтения в JS (Timing-Allow-Origin: * или Timing-Allow-Origin: https://www.example.com)
  • Заголовки Server-Timing поддерживают также поле dur (заголовок), читаемое как duration на стороне JS, но это необязательно и по умолчанию используется 0 в JS, если не передано
  • относительно поддержки Safari: см. ошибка 1 и ошибка 2
  • Вы можете узнать больше о синхронизации сервера в это сообщение в блоге
  • Обратите внимание, что буферы записей производительности могут быть очищены JS на странице (через вызов API) или браузером, если страница выдает слишком много вызовов для подресурсов. По этой причине вам следует как можно скорее захватить данные и / или использовать вместо них PerformanceObserver API. Подробнее см. Сообщение блога.

Другие вопросы по теме