Warum können Hyperlinks in der HTML \ DOM-Spezifikation keinen Akzeptanzheader festlegen?

10

Der AcceptHeader des Clients teilt dem Server mit, welche Art von Daten er als Antwort auf seine Anfrage akzeptiert. Wir können diesen Header in asynchronen HTTP-Aufrufen in Javascript setzen, aber nicht in HTML.

Betrachten Sie beispielsweise einen Link wie <a href="https://softwareengineering.stackexchange.com/some/resource">Get as CSV</a>. Wenn ein Attribut wie accept="text/csv"zulässig wäre und der Browser dies interpretierte, um einen Accept: text/csvHeader mit dieser Anforderung zu senden , könnte der Server auf die Semantik der Anforderung reagieren. Ohne sie können wir einen Link wie erstellen <a href="https://softwareengineering.stackexchange.com/some/resource?format=csv">Get as CSV</a>, und der Server muss stattdessen auf den beliebigen Abfragezeichenfolgenparameter antworten.

Was sind die technischen und historischen Gründe für die HTML \ DOM-Spezifikation, die das Setzen eines AcceptHeaders durch Markup nicht zulässt?

Andy Hunt
quelle
2
Web ist eine Legacy-Plattform, die durch Angst vor Veränderungen und ein langsames Standardkomitee behindert wird: wtfhtmlcss.com wtfjs.com
Den

Antworten:

9

Weil die Header nicht Teil der URL sind. Die URL sollte die Ressource selbst identifizieren und eindeutig tun. Die Accept(und die nützlicheren Accept-Encoding) Header sollten die Semantik der Anforderung nicht beeinflussen. Sie sollten die Fähigkeiten des Clients angeben, damit der Server die Antwort entsprechend formatieren kann.

Wenn Sie einen HTTP-Aufruf über JavaScript ausführen, ist Ihr JavaScript-Code der Client und kann daher Header festlegen. Für HTML-Links ist der Browser jedoch der Client und kann daher auswählen.

Wenn Sie einem Benutzer CSV bereitstellen möchten, sollte die verknüpfte Ressource im Allgemeinen ein festes Format haben. Stellen Sie sich vor, der Benutzer tut es

Copy Link Address

$ wgetPasteEnter

Das ist aus verschiedenen Gründen eine legitime Sache für sie. Und weil der Link ihnen CSV versprochen hat, werden sie das erwarten. Aber das wget bekommt kein anderes Attribut des Links. Nur die URL. Daher sollten die Informationen in der URL verschlüsselt sein.

Tatsächlich gibt es nicht viele Verwendungszwecke für AcceptHeader, da die meisten Ressourcen nur ihr Format haben und in einem anderen nicht viel Sinn machen. Das Accept-Encodingist nützlich; Wenn der Client dies sagt Accept-Encoding: gzip,deflate, bedeutet dies, dass der Client eine transparente Dekomprimierung durchführen kann. Die einzige Verwendung, an die ich denken könnte, Acceptsind Bild- und Videoformate, z. B. als Alternative für Browser, die say image/svg+xmloder nicht unterstützen video/webm. Außer Browser scheinen nicht wirklich zu werben, welche Medienformate sie unterstützen, so dass es nicht funktioniert. Und HTML entschied sich ohnehin für die Implementierung eines anderen, etwas flexibleren Mechanismus. Und nur wenige andere Arten von Daten haben mehrere weit verbreitete alternative Formate zur Auswahl.

Jan Hudec
quelle
Bei Audio und Video gibt es außerdem die Tags audiound video. Dieses Problem wird nun (hoffentlich) so weit gemildert, dass es behoben werden kann. Nun, für HTML5-kompatible Browser.
Parthian Shot
@ParthianShot: Stimmt. Ich mache keine Web-Apps, deshalb habe ich mich nicht daran erinnert, wie es funktioniert. Es ist anscheinend besser geeignet, dem Kunden eine Liste zur Auswahl zu stellen (die normalerweise kurz ist), als den Kunden alle von ihm unterstützten Dinge auflisten zu lassen.
Jan Hudec
Die URL sollte die Ressource identifizieren. Genau aus diesem Grund wollte ich Parameter als Header hinzufügen, die nützlich sind, um Benutzerdaten zu verfolgen, z. B. wo er sich beim Klicken befand oder ob er zuvor von irgendwoher umgeleitet wurde. Gibt es dann eine bessere Möglichkeit? diese?
Santiago Aristi
3

Da in der Accept:Kopfzeile angegeben werden soll, welche Arten von Dokumenten der Browser des Benutzers korrekt verarbeiten kann, handelt es sich nicht um Informationen, über die Sie als Autor der Webseite verfügen.

Der Grund, warum das HTTP-Protokoll einen Accept: -Header bereitstellt, besteht darin, die Auswahl eines geeigneten Dateityps zu ermöglichen, wenn dasselbe Dokument in mehr als einer Form verfügbar ist. Nehmen wir zum Beispiel an, ich verlinke auf ein Bild. Mein Browser kann möglicherweise JPEG- oder Tiff-Bilder anzeigen, jedoch möglicherweise kein RAW-Bild. Der Browser würde dies anzeigen, indem er die folgenden Header mit einer Bildanforderung sendet:

Accept: image/jpeg,image/tiff

Wenn der Server nun ein bestimmtes Bild als RAW oder TIFF bereitstellen kann, antwortet er mit einer TIFF-Version des Bildes (und legt den Content-Type:Header so fest, dass er den von ihm ausgewählten Typ angibt).

Was würde es für den Autor der Webseite bedeuten, die vom Browser gesendeten Auswahlmöglichkeiten zu überschreiben? Wenn ich ein hypothetisches accept="image/raw"Attribut hinzufügen würde, könnte der Browser immer noch kein Rohbild anzeigen - aber der Server würde es senden.

jimwise
quelle
Bingo. Die App kann nicht entscheiden, welche MIME-Typen der Browser akzeptiert.
Svidgen
2

Ein URI soll eine Ressource identifizieren .

Ressource bezieht sich auf das tatsächlich abgerufene Objekt. Auf einer Website ist das normalerweise eine Seite . In einer REST-API ist dies normalerweise eine Entität - Person, Profil, Widget, Foto usw.

HTTP - Header der Server Dinge über die sagen Client - sie nicht selbst, etwas über die Ressource beschreiben oder irgendeine Hilfe bereitzustellen , in der diese Ressource zu lokalisieren.

Zum Beispiel:

  • Accept-Encoding teilt dem Server mit, dass der Client bestimmte Inhalte konvertieren oder dekomprimieren kann.
  • Accept-Language teilt dem Server mit, dass sich der Client in einem bestimmten Gebietsschema befindet, und bevorzugt Inhalte in diesem Gebietsschema.
  • Authorization teilt dem Server mit, dass der Client glaubt, berechtigt zu sein, auf eine geschützte Ressource zuzugreifen.

Ein gemeinsames Thema bei den meisten dieser Anforderungsheader ist, dass der Server nicht verpflichtet ist , diese zu berücksichtigen. Ein Accept-Encodingvon gzipgarantiert nicht, dass die Antwort komprimiert wird. Ein Accept-Languagevon ur-PKwird wahrscheinlich ignoriert, wenn eine US-Site aufgerufen wird, es sei denn, sie unterstützen Urdu ausdrücklich. Der Server behält sich das Recht vor, den AuthorizationHeader zu überprüfen und trotzdem einen 401 oder 403 zurückzugeben, wenn ihm das, was er sieht, nicht gefällt.

Keiner dieser Header soll wesentlich ändern, welche Ressource der Server als Antwort bereitstellt. Der AcceptHeader ist nicht anders. Wenn ein Client angibt application/xmlund der Server nur unterstützt application/json, sendet der Server JSON zurück - nicht XML. Noch wichtiger ist, dass der AcceptHeader mehrere Typen angeben kann . In diesem Fall kann der Server nach Belieben (oder keinem von ihnen) zurückgeben. Wie Sie sich vielleicht vorstellen können, kann dies leicht zu undefiniertem Verhalten für den Benutzer führen, aber lassen Sie uns dies für den Moment ignorieren.

Die Absicht eines Hyperlinks ist es , auf eine Seite zu verlinken - Seite ist eine bestimmte Art von Ressource. Oder Sie könnten in der lockeren Definition der einfachen Verknüpfung mit einer Ressource gerechtfertigt sein, selbst wenn diese Ressource etwas anderes als eine Seite (möglicherweise ein Bild oder ein Datensatz) ist. Was es jedoch definitiv nicht tun soll, ist die Verknüpfung mit einer bestimmten Darstellung einer Ressource. Das ist für den Client und den Server zu verhandeln und der Server letztendlich zu entscheiden.

Accept-Languageist ein offensichtliches Beispiel dafür, warum es problematisch sein kann, Hyperlinks die Steuerung von Headern zu erlauben. Es macht nicht wirklich Sinn, wenn man darüber nachdenkt. Jeder Benutzer steuert seine eigene Sprachpräferenz. Es ist im Betriebssystem und / oder im Browser konfiguriert. Der Browser sollte immer den gleichen Accept-Language Header senden , unabhängig davon, welche Seite besucht wird. Wenn der Server diese Sprache unterstützt, ist das großartig. Wenn nicht, antwortet es mit der Sprache, die es für am nächsten hält.

Wenn dies durch Hyperlinks geändert werden könnte, könnten eingehende Links Sie im Wesentlichen in die chinesischsprachige Version der Website zwingen, selbst wenn Ihr Browser und Ihr Betriebssystem nicht für die Unterstützung dieser Sprache konfiguriert sind. Das macht keinen Sinn. Wenn die Site Englisch unterstützt und Ihr Browser Englisch ist, sollte er auf Englisch antworten, unabhängig davon, was der Hyperlink sagt.

Wenn Ihr Browser weiß, wie XML als strukturierte Daten angezeigt wird, und nach XSLs suchen kann, um es hübsch aussehen zu lassen, aber nicht wirklich weiß, was mit JSON zu tun ist, außer es als einfachen Text auszugeben und sie dann zu zwingen JSON-Inhalte über einen Link (wenn so etwas möglich wäre) sind ein aggressiv benutzerfeindliches Verhalten. Der Browser sollte immer derjenige sein, der sagt: "Ich weiß, wie man X anzeigt, aber nicht Y, also würde ich es wirklich vorziehen, wenn Sie mir X geben würden."

Ich kann verstehen, warum Sie vielleicht denken, dass es logisch ist, dem Benutzer eines Browsers zu erlauben , diese Entscheidung außer Kraft zu setzen. Aber die Wahrheit ist, dass Sie an ein paar winzige Randfälle denken, wie das Herunterladen eines Berichts; In 99% der Fälle, in denen diese Auswahl besteht, ist der Benutzer nicht qualifiziert oder verfügt nicht über ausreichende Informationen, um sie zu treffen.

Stellen Sie sich vor, Ihre Eltern oder Großeltern werden eine Datei herunterladen und aufgefordert, Text / CSV oder Text / Klartext zu wählen. Kennen sie wahrscheinlich den Unterschied? Ich weiß nichts über deine, aber meine kann oft nicht einmal den Unterschied zwischen einem Werbebanner und einer Fehlermeldung erkennen, sodass sie diese Wahl auf keinen Fall intelligent treffen können. Auf der anderen Seite könnte es einen Hoffnungsschimmer geben, wenn sie separate Links zum Herunterladen einer "Excel-Arbeitsmappe" oder "Nur Text" erhalten - für sie handelt es sich tatsächlich um separate Ressourcen , nicht nur um eine unterschiedliche Darstellung derselben Ressource, und Die URIs sollten dies widerspiegeln.

Man kann sich nicht darauf verlassen, dass der Benutzer versteht, dass diese beiden Dinge tatsächlich dieselbe Ressource sind, aber unterschiedliche Darstellungen. Und ohne alles an der heutigen Funktionsweise des Webs zu ändern, können wir nichts davon annehmen, was sie mit diesem Hyperlink machen werden. Sie können klicken oder mit der rechten Maustaste klicken -> "Speichern unter" oder sie können sie kopieren und in ihre Adressleiste einfügen, oder sie verwenden möglicherweise einen Download-Manager oder sie verwenden weiterhin IE6 oder sie Möglicherweise verwenden Sie ein Tablet oder ein mobiles Gerät einer anderen Marke mit einem proprietären Browser. In vielen dieser Fälle erhalten sie nicht den gewünschten Inhalt, da sie entweder den Teil des deklarierten Hyperlinks verlieren Der Inhaltstyp oder der Browser unterstützen ihn nicht.

Könnte die HTML-Spezifikation vor 40 Jahren so konzipiert worden sein, dass sie ein Attribut vom Typ Inhalt in Hyperlinks unterstützt? Vielleicht gab es, wie ich in den ersten Absätzen beschrieben habe, starke Gründe dagegen, insbesondere in einer Zeit, in der Bandbreite und Serverressourcen knapp waren und die Idee bestand, denselben Bericht in mehreren Formaten (oder offen gesagt) herunterladen zu können , überhaupt einen Bericht herunterzuladen) war ehrlich gesagt niemandem in den Sinn gekommen. Aber in der heutigen Welt wäre es sicherlich verrückt, so etwas in die Spezifikation aufzunehmen. Dies würde die Abwärtskompatibilität vollständig beeinträchtigen und zu dem gefürchteten "undefinierten Verhalten" in jedem vorhandenen Browser führen.

Aaronaught
quelle
Wenn ein Client application / xml angibt und der Server nur application / json unterstützt, sendet der Server JSON zurück - nicht XML. Wofür ist dann der 406-HTTP-Fehler? So zitieren Sie rfc2616: Wenn ein Accept-Header-Feld vorhanden ist und der Server keine Antwort senden kann, die gemäß dem kombinierten Accept-
Jules Randolph
Was es jedoch definitiv nicht tun soll, ist die Verknüpfung mit einer bestimmten Darstellung einer Ressource. Das ist für den Client und den Server zu verhandeln und der Server letztendlich zu entscheiden. → Und wenn der Anwendungsdesigner an der Verhandlung teilnehmen möchte? Gibt es eine Referenz, in der behauptet wird, dass der Benutzeragent, dh der Client, sein muss und nur der Webbrowser ? Ich würde mich freuen, wenn Sie mir helfen könnten, dies zu verstehen.
Jules Randolph
0

Die primäre Antwort ist, dass ein Link auf einer Webseite als Webseite gerendert werden soll. Wenn der Webserver einen anderen Typ als eine renderbare Seite zurückgibt (Bild, heruntergeladene Datei usw.), wird der Inhalt möglicherweise vom Browser gerendert oder nicht (er wird möglicherweise als Datei gespeichert).

Es gibt keine Möglichkeit, einen Link auf einer Webseite, der zu einer CSS-Datei oder einer JavaScript-Datei usw. führt, in einem Browser ordnungsgemäß zu rendern.

Um das zu erreichen, was Sie erreichen möchten (Sie haben es nicht gesagt), können Sie einen Link erstellen, der eine JavaScript-Funktion aufruft, die die zusätzliche Funktionalität bietet, die Sie benötigen.

BobDalgleish
quelle
0

Der Grund ist wirklich ganz einfach.

Browser

Der AcceptsHeader sagt zu dem Server, den ich akzeptiere und weiß, wie diese Art von Datei / Dateiinhalt angezeigt wird ....

Javascript

Warum Sie den Header beim Senden einer Anfrage in Javascript ändern können, ist, dass Sie möglicherweise einen Weg zu acceptdiesem neuen Inhaltstyp geschaffen haben, der besagt, dass Sie etwas verschlüsselt und als Dateityp gesendet haben. encrypted/myencryptionIhr Javascript könnte es möglicherweise entschlüsseln, damit es dies akzeptieren kann Art des Inhalts, damit er dem Server mitteilt, dass er diesen Inhalt akzeptieren kann

Ankerverbindungen <a></a>

Sind nichts weiter als dem Browser zu sagen, dass er die Datei in der href abrufen und rendern soll. Wenn der Browser sie nicht verstehen kann, wurde versucht, sie zu analysieren und eine Download-Eingabeaufforderung für die Datei anzuzeigen. Einige Server umgehen dies, indem sie den Typ einfach auf text / plain setzen. Der Browser zeigt dann nur den Text der Datei an.

Martin Barker
quelle