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


406

Як отримати доступ до заголовків відповідей HTTP сторінки через JavaScript?

Пов’язане з цим питанням , яке було змінено, щоб задати доступ до двох конкретних заголовків HTTP.

Пов’язано:
Як я можу отримати доступ до полів заголовка HTTP-запиту через JavaScript?


@ user2284570 - Це не так. це питання про відповідних заголовках, а НЕ запит заголовках.
Квентін

Відповіді:


365

Читати поточні заголовки неможливо. Ви можете зробити ще один запит на цю ж URL-адресу та прочитати її заголовки, але немає гарантії того, що заголовки точно рівні поточному.


Використовуйте наступний код JavaScript, щоб отримати всі заголовки HTTP, виконавши getзапит:

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

58
Саїд, можливо, не найкращий для автора питання .. Я думаю, це тому, що він не має доступу до заголовків завантаженого ресурсу, але робить новий запит .. очевидно, він знає найкраще, яка найкраща відповідь, і зробив це сам
mykhal

18
Залежно від того, який заголовок ви знаходитесь після, можливо, ви захочете використовувати дієслово "HEAD".
scottrudy

17
Здійснення нового запиту спрацює лише в тому випадку, якщо потрібні вам значення відповідей будуть ідентичними від одного запиту до іншого. Це залежатиме від вашої заявки, тому ваш пробіг при такому підході буде відрізнятися.
кепаро

6
Цей злом може працювати в деяких сценаріях, але він взагалі не буде працювати, якщо сторінка, що містить сценарій, була створена у відповідь на запит POST, і це не допоможе, якщо ви намагаєтеся визначити, чи виник сервер з помилкою (HTTP 5XX) під час обробки оригінального запиту.
кламація

9
Ця відповідь жахливо помилкова. Правильна відповідь - "це неможливо". Або підходити до цієї відповіді "Це неможливо, але ось хак спробувати імітувати її, яка може чи не може працювати для вас".
січня

301

На жаль, не існує 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. Зробіть умовиводи

Є деякі властивості BOM (Модель об’єкта браузера), які браузер визначає, переглядаючи заголовки. Деякі з цих властивостей безпосередньо відображають заголовки HTTP (наприклад navigator.userAgent, встановлюється значення User-Agentполя заголовка HTTP ). Обнюхуючи доступні властивості, ви зможете знайти те, що вам потрібно, або деякі підказки, щоб вказати, що містила відповідь HTTP.


3. Приховуйте їх

Якщо ви керуєте стороною сервера, ви можете отримати доступ до будь-якого заголовка, який вам подобається, коли будуєте повну відповідь. Значення можуть бути передані клієнту зі сторінкою, зафіксовані в якійсь розмітці або, можливо, в накресленій структурі JSON. Якщо ви хочете, щоб кожен заголовок HTTP-запиту був доступний вашому javascript, ви можете повторити їх на сервері та відправити їх назад як приховані значення в розмітці. Напевно, не ідеально відправляти значення заголовка таким чином, але ви, безумовно, можете це зробити для конкретного значення, яке вам потрібно. Це рішення, напевно, також неефективно, але воно зробить роботу, якщо вам це потрібно.


2
Як Google виявити , як ніби я пояснив тут: stackoverflow.com/questions/7191242 / ...
kamaci

RE оновлення: запити ajax були стандартною частиною веб-розробки ще в 2008 році -_-
BlueRaja - Danny Pflughoeft

5
BOM означає «Об’єктна модель браузера», для тих, хто цікавиться. Дивіться stackoverflow.com/questions/2213594/… для деякої інформації.
Myrne Stol

1
3) Ви також можете їх зберегти у заголовку файлів cookie. Тоді вам не потрібно буде змінювати розмітку документа.
skibulk

Існує простий спосіб отримати доступ до елементів заголовка відповідей, таких як елемент посилання: використовуйте приклад документа тут: gist.github.com/FunThomas424242/…
FunThomas424242

28

Використовуючи XmlHttpRequestви можете підтягнути поточну сторінку, а потім вивчити http заголовки відповіді.

Кращий випадок - це просто зробити HEADзапит, а потім вивчити заголовки.

Деякі приклади цього погляду див. На http://www.jibbering.com/2002/4/httprequest.html

Всього мої 2 копійки.


24

Рішення з сервісними працівниками

Працівники служби можуть отримати доступ до мережевої інформації, яка включає заголовки. Гарна частина полягає в тому, що він працює на будь-який запит, а не тільки на XMLHttpRequest.

Як це працює:

  1. Додайте сервісного працівника на свій веб-сайт.
  2. Дивіться кожен надісланий запит.
  3. Зробіть сервісний працівник fetchзапит за допомогою respondWithфункції.
  4. Коли відповідь надійде, прочитайте заголовки.
  5. Надішліть заголовки від сервісного працівника на сторінку з postMessageфункцією.

Робочий приклад:

Сервісні працівники трохи складні для розуміння, тому я побудував невелику бібліотеку, яка все це робить. Він доступний на github: https://github.com/gmetais/sw-get-headers .

Обмеження:

  • веб-сайт повинен бути на HTTPS
  • браузер повинен підтримувати API службових службовців
  • такі ж домени / міждоменні політики діють, як і в XMLHttpRequest

12

Для тих, хто шукає спосіб проаналізувати всі заголовки 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"]

10

Ще один спосіб надіслати інформацію заголовка в JavaScript - це через cookie-файли. Сервер може витягти будь-які потрібні вам дані із заголовків запитів і відправити їх назад у Set-Cookieзаголовок відповіді - а файли cookie можна прочитати в JavaScript. Як каже кепаро, однак, найкраще це робити лише для одного чи двох заголовків, а не для всіх.


1
Цей підхід все ще вимагає керування сервером для вашого JS. Незалежно від того, як ви передаєте цю інформацію, ваш код несподівано зробив неможливим. Чому б просто не зробити API для цього конкретного запиту, щоб уникнути пошкодження запиту на початковий актив?
MST

5

Якщо ми говоримо про Запити заголовків, ви можете створити власні заголовки під час виконання 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/base/…
користувач121196

1
Ви повинні зателефонувати open (), перш ніж використовувати метод setRequestHeader (). developer.mozilla.org/uk/…
XP1

1
Доступ, в оригінальному питанні, стосується отримання заголовків, а не встановлення заголовків.
Тімо Тіхоф

4

Ви не можете отримати доступ до заголовків http, але частина наданої в них інформації доступна в DOM. Наприклад, якщо ви хочете побачити http referer (sic), використовуйте document.referrer. Можуть бути й інші подібні для інших заголовків http. Спробуйте googling конкретні речі, які ви хочете, наприклад, "http referer javascript".

Я знаю, що це повинно бути очевидним, але я постійно шукав такі речі, як "http заголовки javascript", коли все, що я дуже хотів, був реферером, і не отримав корисних результатів. Я не знаю, як я не розумів, що можу зробити більш конкретний запит.


4

Як і багато людей, я копав мережу, не маючи реальної відповіді :(

Я все-таки знайшов обхід, який міг би допомогти іншим. У моєму випадку я повністю контролюю свій веб-сервер. Насправді це частина моєї заявки (див. Кінцеву посилання). Мені легко додати сценарій до моєї відповіді на 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


3

Використовуючи mootools, ви можете використовувати this.xhr.getAllResponseHeaders ()


3

Я щойно тестував, і це працює для мене за допомогою версії 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.log("++++++ reading headers ++++++++");
        var headers = xhr.getAllResponseHeaders();
        console.log(headers);
        console.log("++++++ 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

2

Це мій сценарій, щоб отримати всі заголовки відповідей:

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:

введіть тут опис зображення


2

Щоб заголовки були зручнішими (покращення відповіді Раджі ):

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

Посилання Аллана Лалонди зробила мій день. Просто додайте сюди простий робочий 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>

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


Інший спосіб
- більш сучасний fetch()API
https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch
per caniuse.com , який підтримується Firefox 40, Chrome 42, Edge 14, Safari 11
Робочий приклад код:

<!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

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


50
getAllResponseHeaders () та getResponseHeader () - це методи об'єкта XMLHttpRequest. Тобто для запитів на ajax. Ви не можете використовувати ці методи для перегляду заголовків початкової сторінки - саме так, на мою думку, справді було задано оригінальне питання.
asgeo1

-1

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

Наприклад, у Express виражають такі роботи:

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


Питання - це заголовки відповідей , а не заголовки запитів.
Квентін

-1

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


1
Питання - про читання заголовків відповідей . Він зазначає заголовки запитів лише в контексті можливого пов'язаного питання.
Квентін
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.