Accès aux en-têtes HTTP de la page Web en JavaScript

406

Comment accéder aux en-têtes de réponse HTTP d'une page via JavaScript?

Lié à cette question , qui a été modifiée pour demander l'accès à deux en-têtes HTTP spécifiques.

Connexe:
Comment puis-je accéder aux champs d'en-tête de demande HTTP via JavaScript?

keparo
la source
@ user2284570 - Ce n'est pas le cas. cette question concerne les en- têtes de réponse , pas les en- têtes de demande .
Quentin

Réponses:

365

Il n'est pas possible de lire les en-têtes actuels. Vous pouvez faire une autre demande à la même URL et lire ses en-têtes, mais rien ne garantit que les en-têtes sont exactement égaux à l'actuel.


Utilisez le code JavaScript suivant pour obtenir tous les en-têtes HTTP en effectuant une getdemande:

var req = new XMLHttpRequest();
req.open('GET', document.location, false);
req.send(null);
var headers = req.getAllResponseHeaders().toLowerCase();
alert(headers);
Raja
la source
58
Saeed, peut-être pas le mieux pour l'auteur de la question .. Je suppose que c'est parce qu'il n'accède pas aux en-têtes des ressources chargées, mais fait une nouvelle demande .. évidemment, il connaît le mieux, quelle est la meilleure réponse, et l'a faite lui-même
mykhal
18
Selon l'en-tête que vous recherchez, vous pouvez utiliser le verbe «HEAD».
scottrudy
17
Faire une nouvelle demande ne fonctionnera que si les valeurs de réponse dont vous avez besoin sont garanties identiques d'une demande à l'autre. Cela dépendra de votre application, donc votre kilométrage avec une approche comme celle-ci variera.
keparo
6
Ce hack peut fonctionner dans certains scénarios, mais il ne fonctionnera pas du tout si la page contenant le script a été générée en réponse à une demande POST, et il n'aide pas si vous essayez de déterminer si le serveur a rencontré une erreur (HTTP 5XX) lors du traitement de la demande d'origine.
claymation
9
Cette réponse est horriblement fausse. La bonne réponse est "ce n'est pas possible". Ou pour adapter cette réponse "Ce n'est pas possible, mais voici un hack pour essayer de le simuler qui peut ou ne peut pas fonctionner du tout pour vous".
Jan
301

Malheureusement, il n'y a pas d'API pour vous donner les en-têtes de réponse HTTP pour votre demande de page initiale. C'était la question originale affichée ici. Il a également été demandé à plusieurs reprises , car certaines personnes souhaiteraient obtenir les en-têtes de réponse réels de la demande de page d'origine sans en émettre un autre.


Pour les demandes AJAX:

Si une requête HTTP est effectuée sur AJAX, il est possible d'obtenir les en-têtes de réponse avec la getAllResponseHeaders()méthode. Cela fait partie de l'API XMLHttpRequest. Pour voir comment cela peut être appliqué, consultez la fetchSimilarHeaders()fonction ci-dessous. Notez qu'il s'agit d'une solution de contournement au problème qui ne sera pas fiable pour certaines applications.

myXMLHttpRequest.getAllResponseHeaders();

Cela ne vous donnera pas d'informations sur les en-têtes de réponse HTTP de la demande de page d'origine, mais cela pourrait être utilisé pour faire des suppositions éclairées sur ce que ces en-têtes étaient. Plus d'informations à ce sujet sont décrites ci-dessous.


Obtention des valeurs d'en-tête à partir de la demande de page initiale:

Cette question a été posée pour la première fois il y a plusieurs années, demandant spécifiquement comment obtenir les en-têtes de réponse HTTP d'origine pour la page actuelle (c'est-à-dire la même page à l'intérieur de laquelle le javascript était en cours d'exécution). C'est une question très différente de la simple obtention des en-têtes de réponse pour toute requête HTTP. Pour la demande de page initiale, les en-têtes ne sont pas facilement disponibles en javascript. Si les valeurs d'en-tête dont vous avez besoin seront fiables et suffisamment cohérentes si vous demandez à nouveau la même page via AJAX, cela dépendra de votre application particulière.

Voici quelques suggestions pour contourner ce problème.


1. Demandes de ressources largement statiques

Si la réponse est en grande partie statique et que les en-têtes ne devraient pas changer beaucoup entre les demandes, vous pouvez faire une demande AJAX pour la même page sur laquelle vous êtes actuellement et supposer que ce sont les mêmes valeurs qui faisaient partie des pages. Réponse HTTP. Cela pourrait vous permettre d'accéder aux en-têtes dont vous avez besoin en utilisant la belle API XMLHttpRequest décrite ci-dessus.

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

Cette approche sera problématique si vous devez vraiment vous fier aux valeurs cohérentes entre les demandes, car vous ne pouvez pas garantir qu'elles sont identiques. Cela dépendra de votre application spécifique et si vous savez que la valeur dont vous avez besoin est quelque chose qui ne changera pas d'une demande à l'autre.


2. Faire des inférences

Il existe certaines propriétés de nomenclature (Browser Object Model) que le navigateur détermine en regardant les en-têtes. Certaines de ces propriétés reflètent directement les en-têtes HTTP (par exemple, navigator.userAgentsont définies sur la valeur du User-Agentchamp d'en-tête HTTP ). En reniflant les propriétés disponibles, vous pourrez peut-être trouver ce dont vous avez besoin, ou quelques indices pour indiquer le contenu de la réponse HTTP.


3. Cachez-les

Si vous contrôlez le côté serveur, vous pouvez accéder à tout en-tête que vous aimez pendant que vous construisez la réponse complète. Les valeurs peuvent être transmises au client avec la page, stockées dans un balisage ou peut-être dans une structure JSON intégrée. Si vous souhaitez que chaque en-tête de requête HTTP soit disponible pour votre javascript, vous pouvez les parcourir sur le serveur et les renvoyer en tant que valeurs masquées dans le balisage. Ce n'est probablement pas idéal pour envoyer des valeurs d'en-tête de cette façon, mais vous pouvez certainement le faire pour la valeur spécifique dont vous avez besoin. Cette solution est sans doute inefficace aussi, mais elle ferait l'affaire si vous en aviez besoin.

keparo
la source
2
Comment Google le détecte comme je l'ai expliqué ici: stackoverflow.com/questions/7191242/…
kamaci
Mise à jour RE: les demandes ajax faisaient également partie du développement Web en 2008 -_-
BlueRaja - Danny Pflughoeft
5
BOM signifie "Browser Object Model", pour ceux qui se demandent. Voir stackoverflow.com/questions/2213594/… pour plus d'informations.
Myrne Stol
1
3) vous pouvez également les cacher dans l'en-tête du cookie http. Ensuite, vous n'auriez pas besoin de modifier le balisage du document.
skibulk
Il existe un moyen simple d'accéder aux éléments d'en-tête de réponse tels que l'élément de lien: utilisez l'exemple de document ici: gist.github.com/FunThomas424242/…
FunThomas424242
28

À l'aide de, XmlHttpRequestvous pouvez afficher la page en cours, puis examiner les en-têtes http de la réponse.

Le meilleur cas est de simplement faire une HEADdemande, puis d'examiner les en-têtes.

Pour quelques exemples de cela, consultez http://www.jibbering.com/2002/4/httprequest.html

Juste mes 2 cents.

Allain Lalonde
la source
24

Une solution avec Service Workers

Les employés de service peuvent accéder aux informations du réseau, y compris les en-têtes. La bonne partie est qu'il fonctionne sur tout type de demande, pas seulement sur XMLHttpRequest.

Comment ça fonctionne:

  1. Ajoutez un technicien sur votre site Web.
  2. Regardez chaque demande envoyée.
  3. Faites la fetchdemande au travailleur du service avec la respondWithfonction.
  4. Lorsque la réponse arrive, lisez les en-têtes.
  5. Envoyez les en-têtes de l'agent de service à la page avec la postMessagefonction.

Exemple de travail:

Les employés de service sont un peu compliqués à comprendre, j'ai donc construit une petite bibliothèque qui fait tout cela. Il est disponible sur github: https://github.com/gmetais/sw-get-headers .

Limites:

  • le site Web doit être sur HTTPS
  • le navigateur doit prendre en charge l' API Service Workers
  • les politiques de même domaine / inter-domaines sont en action, tout comme sur XMLHttpRequest
Gaël Métais
la source
12

Pour ceux qui recherchent un moyen d'analyser tous les en-têtes HTTP dans un objet accessible en tant que dictionnaire headers["content-type"], j'ai créé une fonction 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"]
Diego
la source
10

Une autre façon d'envoyer des informations d'en-tête à JavaScript serait d'utiliser des cookies. Le serveur peut extraire toutes les données dont il a besoin des en-têtes de demande et les renvoyer dans un en- Set-Cookietête de réponse - et les cookies peuvent être lus en JavaScript. Comme le dit keparo, il est préférable de le faire pour un ou deux en-têtes plutôt que pour tous.

sauver la tour d'horloge
la source
1
Cette approche nécessite toujours que vous contrôliez le serveur de votre JS. Quelle que soit la façon dont vous communiquez ces informations, votre code est soudainement devenu impossible à mettre en cache. Pourquoi ne pas simplement créer une API pour cette demande spécifique afin d'éviter de corrompre la demande de l'actif d'origine?
MST le
5

Si nous parlons d'en- têtes de demande , vous pouvez créer vos propres en-têtes lors de l'exécution de XmlHttpRequests.

var request = new XMLHttpRequest();
request.setRequestHeader("X-Requested-With", "XMLHttpRequest");
request.open("GET", path, true);
request.send(null);
Leo
la source
vous ne pourrez pas modifier l'en-tête de la demande dans mozilla pour des raisons de sécurité. mxr.mozilla.org/mozilla1.8.0/source/extensions/xmlextras/base/…
user121196
1
Vous devez appeler open () avant d'utiliser la méthode setRequestHeader (). developer.mozilla.org/en/…
XP1
1
L'accès, dans la question d'origine, concerne l'obtention d'en-têtes et non la définition d'en-têtes.
Timo Tijhof
4

Vous ne pouvez pas accéder aux en-têtes http, mais certaines des informations qui y sont fournies sont disponibles dans le DOM. Par exemple, si vous souhaitez voir le référent http (sic), utilisez document.referrer. Il peut y en avoir d'autres pour d'autres en-têtes http. Essayez de googler la chose spécifique que vous voulez, comme "http referer javascript".

Je sais que cela devrait être évident, mais j'ai continué à chercher des trucs comme "http headers javascript" alors que tout ce que je voulais était le référent, et je n'ai pas obtenu de résultats utiles. Je ne sais pas comment je n'ai pas réalisé que je pouvais faire une requête plus spécifique.

David Winiecki
la source
4

Comme beaucoup de gens, j'ai creusé le filet sans vraie réponse :(

J'ai néanmoins découvert un contournement qui pourrait aider les autres. Dans mon cas, je contrôle entièrement mon serveur Web. En fait, cela fait partie de ma candidature (voir référence de fin). Il m'est facile d'ajouter un script à ma réponse http. J'ai modifié mon serveur httpd pour injecter un petit script dans toutes les pages html. Je ne pousse qu'une ligne de «script js» supplémentaire juste après ma construction d'en-tête, qui définit une variable existante de mon document dans mon navigateur [je choisis l'emplacement], mais toute autre option est possible. Bien que mon serveur soit écrit en nodejs, je ne doute pas que la même technique puisse être utilisée à partir de PHP ou d'autres.

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

Maintenant, toutes les pages html chargées depuis mon serveur, ont ce script exécuté par le navigateur à la réception. Je peux ensuite facilement vérifier à partir de JavaScript si la variable existe ou non. Dans mon cas d'utilisation, je dois savoir si je dois utiliser le profil JSON ou JSON-P pour éviter le problème CORS, mais la même technique peut être utilisée à d'autres fins [par exemple: choisir entre le serveur de développement / production, obtenir du serveur un REST / API clé, etc ....]

Sur le navigateur, il vous suffit de vérifier la variable directement à partir de JavaScript comme dans mon exemple, où je l'utilise pour sélectionner mon profil 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);

Pour qui souhaite vérifier mon code: https://www.npmjs.org/package/gpsdtracking

Fulup
la source
3

En utilisant mootools, vous pouvez utiliser this.xhr.getAllResponseHeaders ()


la source
3

Je viens de tester, et cela fonctionne pour moi en utilisant Chrome Version 28.0.1500.95.

J'avais besoin de télécharger un fichier et de lire le nom du fichier. Le nom du fichier est dans l'en-tête, j'ai donc fait ce qui suit:

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

    }
};

Production:

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
rushmore
la source
2

Voici mon script pour obtenir tous les en-têtes de réponse:

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

Ayant comme résultat les en-têtes de réponse.

entrez la description de l'image ici

Il s'agit d'un test de comparaison utilisant Hurl.it:

entrez la description de l'image ici

Jorgesys
la source
2

Pour obtenir les en-têtes comme un objet plus pratique (amélioration de la réponse de 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);
shaedrich
la source
2

Le lien d'Allain Lalonde a fait ma journée. Ajout d'un simple code html fonctionnel ici.
Fonctionne avec n'importe quel navigateur raisonnable depuis des âges plus IE9 + et 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>

Remarque: Vous obtenez des en-têtes d'une deuxième demande, le résultat peut différer de la demande initiale.


Une autre façon
est l' fetch()API plus moderne
https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch
Per caniuse.com prise en charge par Firefox 40, Chrome 42, Edge 14, Safari 11
Exemple de travail 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>
jj
la source
0

C'est une vieille question. Je ne sais pas quand le soutien est devenu plus large, mais getAllResponseHeaders()et getResponseHeader()semble être maintenant assez standard: http://www.w3schools.com/xml/dom_http.asp

dlo
la source
50
getAllResponseHeaders () et getResponseHeader () sont des méthodes de l'objet XMLHttpRequest. C'est à dire pour les demandes ajax. Vous ne pouvez pas utiliser ces méthodes pour afficher les en-têtes de la page initiale - ce que je pense que la question d'origine posait vraiment.
asgeo1
-1

Comme cela a déjà été mentionné, si vous contrôlez le côté serveur, il devrait être possible de renvoyer les en-têtes de demande initiaux au client dans la réponse initiale.

Dans Express, par exemple, les travaux suivants:

app.get('/somepage', (req, res) => { res.render('somepage.hbs', {headers: req.headers}); }) Les en-têtes sont ensuite disponibles dans le modèle, ils peuvent donc être masqués visuellement mais inclus dans le balisage et lus par javascript côté client.

Ollie Williams
la source
La question concerne les en- têtes de réponse , pas les en-têtes de demande.
Quentin
-1

Je pense que la question a mal tourné.Si vous souhaitez prendre l'en-tête Request de JQuery / JavaScript, la réponse est simplement non. Les autres solutions sont de créer une page aspx ou une page jsp, nous pouvons facilement accéder à l'en-tête de la demande. Prenez toute la demande dans la page aspx et placez dans une session / cookies alors vous pouvez accéder aux cookies dans la page JavaScript.

santhos jery
la source
1
La question porte sur la lecture des en- têtes de réponse . Il ne mentionne les en-têtes de demande que dans le contexte de la question éventuellement liée.
Quentin