JavaScript/WindowOrWorkerGlobalScope/fetch/Daten senden

Aus SELFHTML-Wiki
Wechseln zu: Navigation, Suche

Um mit Hilfe von fetch() Daten zu senden, muss man eine geeignete HTTP-Methode verwenden. Es gibt zwei davon: POST und PUT, wobei PUT auf dem Webserver gewisser Vorbereitungen bedarf, wenn man mit PHP darauf reagieren will.[1] Diese Vorbereitungen sind je nach Webserver unterschiedlich und können hier nicht im Detail diskutiert werden.

POST ist vor allem für Formulardaten gedacht. Für das Fetch-API bedeutet das, dass man ein FormData oder ein URLSearchParams-Objekt als Datencontainer verwendet. Über FormData lassen sich auch Dateien hochladen, und fetch setzt dann automatisch den multipart/formdata Content-Type und berechnet auch einen passenden boundary-Wert zum Trennen der Parts im Multipart-Format. Serverseitig kommt PHP mit solchen Requests automatisch zurecht und stellt die Daten in $_POST und $_FILES bereit.

Wenn man Daten mit dem PUT-Verb oder per POST in anderen Formaten übertragen möchte, sieht die Sache anders aus. In diesem Fall muss man den Content-Type selbst setzen (zum Beispiel "application/json") und die Daten in PHP aus dem stdin-Stream selbst einlesen. Der im Anhang gelistete Link zur PUT-Unterstützung in PHP zeigt, wie das geht.

Schritt 1: Senden des HTTP-Requests

Das ist für POST etwas aufwändiger als für GET. Wir benötigen hierfür den zweiten Parameter der fetch()-Funktion, mit dem sich ein RequestInit-Objekt übergeben lässt. RequestInit ist lediglich ein Name und keine Konstruktorfunktion, du musst einfach ein Objektliteral mit den benötigten Eigenschaften erzeugen. Welche Eigenschaften verwendet werden können, ist in der fetch-Spezifikation festgelegt.

Wichtig sind vor allem die folgenden Eigenschaften:

method
Die anzuwendende HTTP-Methode (also "POST" - es sind aber grundsätzlich alle HTTP-Methoden möglich)
body
Der zu sendende Inhalt. Außer einem FormData und URLSearchParams-Objekt werden noch weitere Objekttypen unterstützt:
  • Strings
  • ArrayBuffer
  • Blob
  • DataView
  • File
  • TypedArray
  • ReadableStream
headers
Wenn du Header übertragen musst, hinterlegst Du hier entweder ein Headers-Objekt oder ein Objektliteral, in dem die Eigenschaftsnamen die Headernamen darstellen. Die Eigenschaftswerte werden als Inhalt des Headers übertragen.

Für unser Beispiel wollen wir bei dem Wetterstationen-Netz bleiben. Eine Wetterstation muss gelegentlich Einstellungen bekommen (z.B. die Uhrzeit oder Alarmwerte für Wind, Temperatur oder Regenmenge). Die Einstellungswerte schicken wir ihr über den Server mittels POST auf settings.php. Wie diese Daten genau aussehen und was settings.php tut, kann uns für das Verständnis von fetch vollständig gleichgültig sein – unsere Wetterstationen sind ja ohnehin rein fiktiv – und deshalb sollen sie der konfiguriereStation()-Funktion auch als Parameter in settings übergeben werden. Wir nehmen aber an, dass es ein einfaches, flaches Objekt ist, und werden es mittels JSON-Codierung an den Server senden.

Das settings.php Script soll dann die vollständigen, aktuellen Einstellungen für die angegebene Stations-Id zurückliefern.

Senden eines Objekts an ein Server-API
async function konfiguriereStation(stationsId, settings) {
   const url = new URL("https://weather.example.com/settings.php");
   url.searchParams.set("station", stationsId);

   const settingsAsJson = JSON.stringify(settings);
   const requestInit = {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: settingsAsJson;
   };
   const response = await fetch(url, requestInit);
   if (response.ok) 
      return response.json();
   else
      throw new Error(`Setzen der Einstellungen für Station ${stationsId} gescheitert, ` +
                      `HTTP-Status ${response.status}`);
}

Das Beispiel zeigt aber noch eine Besonderheit: Auch bei einem POST-Request kann man URL-Parameter verwenden. Es wäre ungeschickt, die Stations-Id den Settings-Daten hinzuzufügen, da sie eigentlich kein Teil dieser Daten ist.

Wie eingangs gesagt, auf PHP-seite muss der JSON-String direkt von php://stdin eingelesen werden. Anders ist es, wenn man ein FormData-Objekt überträgt. Dafür lässt man den Content-Type Header weg, denn diese Objekte werden von fetch standardmäßig als multipart/form-data übertragen und die Inhalte finden sich im $_POST oder $_FILES-Array wieder. Unser Artikel über Segmentierte_Uploads zeigt Beispiele dafür. Wenn Du keine Files überträgst, kannst Du auch explizit in den Headern den Content-Type application/x-www-form-urlencoded angeben.

Schritt 2: Empfangen der Antwort

Dieser Teil ist identisch zum GET-Request und ist im Artikel fetch - Daten empfangen beschrieben.

Weblinks

  1. ↑ PHP Manual: PUT-Unterstützung