HTTP Protokoll/POST Methode

Billie

Erfahrenes Mitglied
Helas!

Ja, ich bin schon wieder soweit dass mir der Kopf schmerzt und will mir jetzt nicht mehr den Kopf darüber zerbrechen, deshalb frage ich einfach mal nach. Also, ich habe spezielle Fragen zum HTTP Protokoll und ich weiß, es gibt da diese RFC2616 wo eigentlich alles drinnensteht - andererseits, ich kann da nicht das herauslesen was ich benötige.

Folgendes, nehmen wir an es gibt ein PHP Skript das eine Datei mittels POST empfängt und abspeichert. Die PHP Datei erwartet also eine POST Anweisung inkl. einer Datei und ich möchte nun wissen wie genau das aussieht, also die das Paket was vom Client zum Server geschieckt wird.

Stellt es euch so vor, ihr habt einen eigenen Browser programmiert und wollt nun mittels POST Dateien (zB Bilder in eine Gallerie) an den Server schiecken. Wie genau hat das auszusehen?
 
Das ist prinzipiell nicht weiter kompliziert. Beispiel:
Code:
POST /foobar HTTP/1.1
Host: foo.bar.net
Content-Type: multipart/form-data; boundary=~myboundary~

--~myboundary~
Content-Disposition: form-data; name="uploaded_file"; filename="localfile.html"
Content-Type: text/html

<html>
 <head>
  <title>Foobar</title>
 </head>
 <body>
  <h1>Foo</h1>
  <h2>bar</h2>
 </body>
</html>
--~myboundary~
Content-Disposition: form-data; name="name"

reima
--~myboundary~
Content-Disposition: form-data; name="forum"

26
--~myboundary~--

Die erste wichtige Zeile ist diese:
Content-Type: multipart/form-data; boundary=~myboundary~
boundary=~myboundary~ bestimmt ein "boundary", eine Abgrenzung also. Diese wird verwendet, um die verschiedenen Felder der Formulardaten voneinander zu trennen.

Der Datenbereich des Requests beginnt dann gleich mit dieser "boundary", allerdings mit einem vorangestellten Doppelminus (--).
Darauf folgt diese Zeile:
Content-Disposition: form-data; name="uploaded_file"; filename="localfile.html"
Sie definiert ein Feld des Formulars, in diesem Fall hat das Feld den Namen "uploaded_file" (im HTML-Quelltext des Formulars stand also sowas wie <input type="file" name="uploaded_file" />) und es handelt sich um eine Datei (filename="localfile.html")
Die nächste Zeile gibt noch an, um welcher MIME-Typ der Datei zugeordnet ist (hier: text/html)
Nach einem doppelten CR/LF folgt dann der Inhalt der Datei.

Entsprechend wird für andere Formularfelder verfahren: Zuerst "--", dann das "boundary" + CR/LF, dann über Content-Disposition: form-data; name="name_des_feldes"; die Feldbeschreibung und nach zweimaligem CR/LF den Inhalt (im Code oben gab es z.B. u.a. ein <input type="text" name="name" />, in das ich "reima" geschrieben hab).

Das Ende der Übertragung wird schließlich mit dem "boundary" gekennzeichnet, allerdings mit voran- und nachgestelltem Doppelminus (+CR/LF).

Ach ja, das "boundary" darf man frei wählen.

Du siehst also, ist eigentlich ganz einfach :)
 
Zuletzt bearbeitet:
Danke Matthias für deine sehr ausführliche Antwort! Genau so eine Erklärung/Beschreibung wollte ich 8) Das "boundary" Verfahren kenn ich schon von E-Mails her, also E-Mails mit Anhang usw. Trotzdem, es ergibt sich ein Problem. Wenn ich folgende Anweisung an den Server sende:

Code:
POST /upload.php HTTP/1.1
Host: localhost
Content-Type: multipart/form-data; boundary=1234

--1234
Content-Disposition: form-data; name="upload"; filename="C:\test.txt"
Content-Type: text/plain

123412341234123412341234
123412341234123412341234
123412341234123412341234
123412341234123412341234
--1234--

Bekomm ich folgende Server-Fehlermeldung zurück:
501 Method Not Implemented
--1234 to / not supported

Diese Fehlermeldung kann auch glaub ich schlecht das PHP Skript erzeugen, oder?
 
Hy nochmal!

Jub, es hat irgendetwas mit Content-Length am Hut. Ich habe mich jetzt nämlich ein bisschen mit den Headern gespielt. Wenn ich Content-Length und Connection nicht angebe, bekomme ich den eben genannten 501 Fehler. Dabei darf das Attribut Connection aber irgendwie nur den Wert "close" haben, mit Keep-Alive zB wird eine Bad Request Meldung ausgelöst, die Datei aber trotzdem gespeichert 8)

Und wenn ich das Content-Length Attribut weglasse, dafür aber das "Connection" Attribut stehen lasse, bekomme ich zwar eine OK Meldung aber die Datei wird nicht gespeichert. Das selbe passiert wenn das Content-Length Attribut einen zu gerinen Wert hat, darauf schlussfolgere ich jetzt einfach, dass wenn das Content-Length Attribut nicht angegeben wird, ein Standartwert wie zB 0 angenommen wird und somit die Datei nicht übertragen wird. Interessant ist weiteres, wenn das Content-Length weiter einen zu Hohen Wert hat. Dann bekomme ich erst nach einer zweiten Anfrage eine Rückmeldung vom Server, funktioniert aber einwandfrei. Ich vermute der Server wartet bis er die restlichen Bytes bekommt... die liefer ich ihm wahrscheinlich in Form der 2. Anfrage. Das würde bedeuten es ist Möglich eine große Datei in mehreren Anfragen zu versenden, oder etwa nicht? Wie genau wird das dann gemacht?

Fazit, einwandfrei Funktioniert die Anweisung nur wenn das Attribut "Content-Length" mit der richtigen Größe angegeben wird und das Connection Attribut mit dem Wert "Close". Hier kurz nocheinmal die Anweisung, so wie sie funkioniert:

Code:
POST /upload.php HTTP/1.1
Content-Type: multipart/form-data; boundary=1234
Host: localhost
Content-Length: 377
Connection: Close

--1234
Content-Disposition: form-data; name="upload"; filename="C:\Dokumente und Einstellungen\Afagschlun\Desktop\test.txt"
Content-Type: text/plain

123412341234123412341234
123412341234123412341234
123412341234123412341234
123412341234123412341234
--1234--

Wobei ich gerade gemerkt habe, die länge des Boundary spielt auch im Content-Length Attribut eine Rolle. Habe hier nämlich gerade der leserlichkeit halber das Boundary gekürzt (1234 anstatt viele Zeichen). Deshalb muss das Content-Length Attribut auf die neue Größe angepasst werden, dann funktioniert es auch einwandfrei mit dem 1234-boundary. Wäre deshalb interessant zu wissen was genau das Content-Length Attribut beschreibt... wahrscheinich alle Daten von "--1234" bist einschließlich "--1234--" ?!
 
Hallo,
auf der Suche nach einer Lösung für mein Problem bin ich bei diesem Thread gelandet.
Ich baue mithilfe eines Microcontrollers und eines GSM-Modems eine GPRS-Verbindung auf und möchte darüber eine HTTP-Adresse aufrufen und an einen Server schicken. In der URL sind dabei auch verschiedene Nutzdaten enthalten. Wenn ich die gleiche Adresse über meinen Internet-Browser aufrufe, werden die genannten Daten auch schon in der gewünschten Weise verarbeitet.
Nun möchte ich stattdessen aber die bereits oben genannte Microcontroller-Anordnung benutzen. Die Sache ist auch bereits soweit realisiert, daß eine GPRS-Verbindung aufgebaut wird und sich der Ziel-Server mit einem "Connect" meldet.
Nach Studium des Threads gehe ich nun davon aus, daß auch in meinem Fall die POST Methode zu benutzten ist. Nachdem ich aber keine separate Datei, sondern nur eine Adresse übertragen will, dürfte sich die Anzahl der erforderlichen Befehle gegenüber dem erwähnten Beispiel sogar noch verringern.

Ich würde mich sehr freuen, wenn Ihr mir kurz aufzeigen könntet, wie die erforderliche Befehlsfolge auszusehen hätte.

Dank schon im Voraus
Klaus
 
Hm, kommt darauf an. Also, du willst wie ich bestimmte Daten an ein Skript schiecken, nur eben über Handy. Die Frage ist, was für Daten das Skript erwartet und in welcher Form GET/POST?

Wenn es nur ein kleines Skript ist, kannst du es ja mal Posten. Oder du machst es wie ich, besorgst dir einen Netzwerksniffer und guckst nach was dein Browser schieckt damit es funktioniert.
 
Danke für die Antwort Billie Joe

> Hm, kommt darauf an. Also, du willst wie ich bestimmte Daten an ein Skript
> schiecken, nur eben über Handy. Die Frage ist, was für Daten das Skript
> erwartet und in welcher Form GET/POST?

Das ist halt die Frage. Vielleicht ist es auch ausreichend, wenn ich meine Daten nur ganz einfach per GET-Anweisung zum Server sende.
Zur Not muss ich alle möglichen Varianten praktisch austesten.

> Wenn es nur ein kleines Skript ist, kannst du es ja mal Posten. Oder du machst > es wie ich, besorgst dir einen Netzwerksniffer und guckst nach was dein
> Browser schieckt damit es funktioniert.

Hier ist ein etwas vereinfachtes Muster-Skript. Vom Format entspricht es aber dem, was ich an den Server übergeben möchte. Es handelt sich hierbei um die Übertragung geographischer Längen- und Breitengraddaten:

_http://www.zielservername.com/webform1.aspx?name=MEINNAME&latitude=49.4500000&longitude=008.240000<CR><LF>

PS: Damit die Anweisung hier nicht als HTTP-Zeile interpretiert und dabei automatisch manipuliert dargestellt wird, habe ich ihr einen ( normalerweise aber nicht vorhandenen) Tiefstrich vorangestellt.
Alle Anweisungen stehen in EINER Zeile.

Gruß
Klaus
 
Zuletzt bearbeitet:
In diesem Fall ist die Antwort einfach, du rufst mit der GET Methode die URL ab. So könnte das zB aussehen:

Code:
GET /webform1.aspx?name=MEINNAME&latitude=49.4500000&longitude=008.240000 HTTP/1.1
Accept: image/gif, image/jpeg, application/x-shockwave-flash, */*
Accept-Language: de-at
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.1.4322)
Host: localhost
Connection: Keep-Alive
\r\n
\r\n

Die Attribute wie Accept usw. sind auch nur optional, aber egal. Schreib wenn es noch immer Probleme gibt.
 
Hallo BillieJoe,
ich habe es ganz einfach mithilfe von "HyperTerminal" praktisch ausgetestet und es hat auch geklappt. Dabei musste ich nur GET und die restliche URL aussenden. Wenn auch das "HTTP/1.1" am Befehlsende stand, erhielt ich eine Fehlermeldung. Ich habe es dann einfach weggelassen. Auch die anderen von Dir angegebenen Befehlzeilen waren bei mir nicht erforderlich. Die versandten Navigationsdaten werden vom Server auf jeden Fall verarbeitet.
Noch einmal herzlichen Dank für die Unterstützung und ein schönes Wochenende
Klaus
 

Neue Beiträge

Zurück