Ich hab gerade noch gesehen, dass die die Daten, die via POST kommen, stark vom 'enctype' im <form></form> Block abhängen.
Somit reicht ja nicht mal ein simpler Parser, sondern damit wird das echt komplex ... :-(
Druckbare Version
Mein Vorschlag mit dem GET Request war auch nicht ganz richtig,
mir fiel auf, dass im allgemeinen "Request handle", also vorher schon geparsed werden muss,
da dies genauso bei POST Requests der Fall sein kann.
Und man müsste noch nach Slash zerlegen und auf "is directory" prüfen,
da es auch sein kann dass der Query String (und resultierende enviroment variable: QUERY_STRING wenn cgi implementiert wird) Slashs enthält
( z.B: http://1.2.3.4/shop.cgi/categories/all ).
Ich dachte man kann es so realisieren,
dass alles was POST ist, auch ein potentieller Upload sein kann, also den POST Header parsen auf wenn vorhanden:
* "content-type" : auch "boundary=" enthalten ist, muss zerlegt werden.
* "content-disposition" : filename oder name und noch
* "content-transfer-encoding".
Gibt es denn einen Grund PUT zu implementieren?
Viele Webserver unterstützen nur POST, GET und HEAD, vorallem aus Sicherheitsgründen.
Das parsen des query-Strings habe ich aktuell noch nicht 100%ig implementiert bzw. durchdacht.
Aber ich denke, das dürfte nicht wirklich sooo kompliziert werden.
Ich hab mich mehr beim POST festgefressen. ;)
Ich will ja gar nicht PUT implementieren!
Das POST raubt mir schon genug Nerven ...
Hier mal ein paar Beispiele
#1 mit
http://pastebin.de/13713Code:<form action="post.html" name="form" enctype="multipart/form-data" method="post">
#2 mit
http://pastebin.de/13714Code:<form action="post.html" name="form" method="post">
Also 2 völlig verschiedene Wege um die POST-Variablen auszuwerten ...
Bei #1 fällt dann auch auf, dass 'Content-Disposition: form-data; ...' mehrmals vorkommt.
Ich bin ja so vorgegangen, dass ich vom letzten Eintrag anfange zu parsen. Scheinbar funktioniert das aber nicht wie gewünscht ...
Ja, man braucht wahrscheinlich mindestens 2 Schritte um postdata zu parsen.
Aber dass sind, soweit ich weiss, auch die einzigen 2 Fälle die auch andere Webserver abfangen.
Ich glaube so könnte der Ablauf funktionieren:
Allgemein Header splitten auf ':' zum Auslesen.
Wenn POST dann (content-length speichern etc.) im
HEADER['content-type'] auf "boundary" oder "multipart" testen.
Wenn es kein Multipart ist und boundary enthält, kann man die Parameter (wie #1)
zerlegen.
Ansonsten boundary speichern ( #2 ), dann muss man parsen, z.B. mit spiltten nach boundary, diese beginnen mitund in einer Schleife analysieren, wenn dann ein filename enthalten ist, muss dies temporär gespeichert werden, z.B. nach /tmp mit einem "tmp name".Code:"\r\n--" + boundary
#1 Nach new 2 NewLines "\r\n\r\n" und als QUERY_STRING speichern,
(ggf. nach & und = zerlegen)
#2 mit boundary, dann boundaries zerlegen.
Aus der 'content-disposition' Line name und ggf. filename extrahieren,
ggf. alles nach Semikolon auf '=' splitten.
Wenn zwischen den Boundaries 'content-type' vorkommt, dann die eingelesen Chars (data)
als Datei speichern, ansonsten als Postdata in z.B. POST[name] = data .
Ich denke das kann auch richtig Spass machen :)
Eventuell lässt sich auch QUrl zum parsen der GET URL heranziehen, das hätte u.A. hasQuery()
Ciao,
_
Naja .. Spaß machen ... ;)
Scheinbar habe ich Probleme beim 'Auseinandernehmen' der Request-Daten:
Nach 'Content-Length' müssten es ~280k sein.Code:[22:49:26:261] [ Debug] : HEADER: [595]
'POST /post.html HTTP/1.1
Host: localhost:8080
User-Agent: Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.13) Gecko/20110102 Gentoo Firefox/3.6.13
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.7,de-de;q=0.3
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-15,utf-8;q=0.7,*;q=0.7
Keep-Alive: 115
Connection: keep-alive
Referer: http://localhost:8080/
X-Behavioral-Ad-Opt-Out: 1
X-Do-Not-Track: 1
Content-Type: multipart/form-data; boundary=---------------------------1525561818437990015185174710
Content-Length: 278153'
[22:49:26:261] [ Debug] : Request: 'POST' - 'post.html' - 'HTTP/1.1'
[22:49:26:261] [ Debug] : Content-Disposition found ...
[22:49:26:261] [ Debug] : Request-Size '56749'
[22:49:26:261] [ClassDebug] : void MultiPart::init()
[22:49:26:262] [ Debug] : capacity 57344
[22:49:26:262] [ Debug] : i think, we can have 1 attachments
[22:49:26:262] [ Debug] : name 'file1'
[22:49:26:262] [ Debug] : filename '01ba2c47cf8ceb8a8d23e565dcec297b-d31oky4.jpg'
[22:49:26:262] [ Debug] : type 'image/jpeg'
[22:49:26:262] [ Debug] : size '56270'
[22:49:26:262] [ Debug] : datetime '10.01.2011-22:49:26:262'
[22:49:26:262] [ Debug] : md5 '684f129518e241c154fdaa5d5b8bba3d'
Nach meinem auseinander-cut-en habe ich nur 56k übrig. :(
Ich krieg 'n Fön
update #1
Ich glaube fast, der socket in Request.cpp bekommt die Daten nicht fix genug und wird geschlossen, bevor alles bei ihm gelandet ist.
Gibt es keine Möglichkeit das anders zu gestalten?
update #2
aktuelle Version
Ich hab da eine Theorie, wieso das mit dem POST nicht so klappt ...
Liegt das evtl. daran, dass der Request in einem Thread abgearbeitet wird und der irgendwie Probleme mit dem syncronisieren der IP / Ports bekommt?
Denn anders kann ich mir das jetzt nicht mehr erklären.
Ich hab das jetzt auch erstmal weiter nach hinten verschoben um mit Cookie & Session weiterzumachen ...
Ich habe mal unterschiedliche Wege ausprobiert, um an die Daten zu kommen:
#1
#2Code:bool done = true;
do {
usleep(500);
pRawHeaderData.append( socket->readAll() );
done = socket->atEnd();
socket->flush();
} while( !done );
#3Code:while( socket->waitForDisconnected( 100 ) ) {
pRawHeaderData.append( socket->readLine() );
}
Nur um zu sehen, ob sich da irgendwas ändert.Code:while( socket->canReadLine() ) {
pRawHeaderData.append( socket->readLine() );
}
Aber was soll ich sagen?
Das Ergebniss bleibt immer das gleiche ... :(
Vielleicht eher so:
Ciao,Code:do {
while ( socket->waitForReadyRead( 100 ) ){
pRawHeaderData.append( socket->read( socket->bytesAvailable() ) );
}
} while (!socket->atEnd())
_
Moin Moin!
Ich habe jetzt eine halbwegs lauffähige Version (download).
Momentan speichere ich die Sessions in einer sqlite-DB, bin mir aber nicht sicher, ob das als eine Performancebremse auswirken könnte.
PHP hat ja nicht wirklich was mit typsicheren Variablen am Hut, so dass man dort (in den Sessions) problemlos ganze Arrays reindrücken kann. Wenn ich diese Funktionalität noch implementieren will, wüsste ich noch gar nicht wie.
Mal abgesehen davon halte ich sie nicht gerade für sinnvoll. ;)
So, schaut euch das Ding an wenn ihr wollt.
Über Kritik und Anregungen bin ich echt dankbar, also übt keine Zurückhaltung! :D
Nachdem ich nun soweit bin, habe ich wohl noch ein einzigest Problem ... und zwar das Ding mit den Plugins.
Mein Wunschverhalten wäre dieses:
Beim Start des Servers werden die Verfügbaren Plugins geladen und können dann generell von überall her genutzt werden.
Aktuell scheine ich da aber an eine meiner (momentanen) Grenzen gestossen zu sein.
Wenn ich die Plugins in der Klasse RIPCoreApplication lese, kann ich diese in Request nicht benutzen, also muß ich die da wieder laden.
Und ich möchte nicht wirklich, dass die Plugins bei jedem Request neu geladen werden müssen. Dann brauch ich auch gar keine ...
Gibt es da für mich keine Elegantere Lösung?
Anda Skoa? Vielleicht hast du eine Idee? ;)
Ich bin mit nicht ganz sicher, ob ich das Problem richtig verstehe.
In deiner Applikationsklasse lädst du die Plugins und hälst sie dann in einem Container?
Und in deiner Requestklasse hast du keine Zugriff auf diesen Container?
Ciao,
_
Richtig.
Ich denke, es liegt daran, das der eigentliche Construktor des PluginLoaders privat und er eigentlich über eine statische PluginLoader::self() Funktion instanziert und erstellt wird.
self() ruft dann intern die (private) scan() Funktion auf.
Ich hab bislang noch keinen Hebel gefunden, dem Container eine Funktion mit zu geben, mit der die geladenen Plugins public zur Verfügung gestellt werden können.
DAs versteh ich jetzt nicht ganz.
Kannst du nicht einfach
aufrufen?Code:PluginLoader::self()->createForName(...);
Ciao,
_
Bin gerade über etwas gestolpert, dass dich vielleicht interessieren könnte:
https://github.com/nikhilm/qhttpserver
Ciao,
_
Ahh, da schien jemand eine ähnlich Idee gehabt zu haben. ;)
Danke, dass werd ich mir bei Gelegenheit gern mal mit anschauen.
Zur Zeit kämpfe ich eher mit dem ausliefern von Bildern ... das scheint nicht ganz so zu funktionieren, wie ich es mir vorstelle. ;)
Reine HTML & Stylesheet Daten funktionieren