Autor Thema: Problem/Frage zu HttpUtils_NonblockingGet POST mit multipart/form-data  (Gelesen 345 mal)

Offline DS_Starter

  • Developer
  • Hero Member
  • ****
  • Beiträge: 6140
Hallo Rudi, @all,

ich erstelle zur Zeit ein Modul zur Integration der Synology File Station in FHEM.
Es wird bis jetzt komplett mit HttpUtils umgesetzt und nach vielen Stunden der Analyse und
RFC Studiums läuft jetzt auch der Upload von Files mit POST und multipart/form-data.

Dabei ist mir aber folgendes aufgefallen.
Laut RFC1521 muß der Body Part von multipart/form-data mit einem CRLF beginnen, gefolgt von einem boundary und
weiteren Daten in einer festgelegten Syntax die auch im Synology API Guide beschrieben ist.
Zum Test habe ich folgendes Kontrukt verwendet:

       
       my $crlf     = "\r\n";
       my $bound = "AaB03x";

       my $dat   = $crlf;
       $dat     .= "--".$bound;
       $dat     .= $crlf;
       $dat     .= qq{content-disposition: form-data; name="path"};
       $dat     .= $crlf;
       $dat     .= $crlf;
       $dat     .= qq{/home/upload};
       $dat     .= $crlf;
       $dat     .= "--".$bound;
       $dat     .= $crlf;
       .....

       $param = {
           url      => $url,
           timeout  => $timeout,
           hash     => $hash,
           method   => "POST",
           header   => "Content-Type: multipart/form-data, boundary=$bound",
           data     => $dat,
           loglevel => 1,
           callback => \&FHEM::SSFile::execOp_parse
       };
       
       HttpUtils_NonblockingGet ($param);

Damit bin ich ständig auf einen API Fehler gelaufen.
Dann habe ich einige zusätzliche Logs in HttpUtils eingefügt und mir das zusammengebaute Ergebnis angeschaut
bevor es an $hash->{directWriteFn} übergeben wird:

2020.10.21 09:57:20.291 1: HttpUtils data for directWriteFn:
POST /webapi/entry.cgi?api=SYNO.FileStation.Upload&version=2&method=upload&_sid=wIW_bdkKplgfP4ceU4zxMuj4Xbms4lGi7weKn8Gon9ke58d9fk7b-sHmL0ZzGd_dH9kqc8eh_M0GUfVXWsr-BM HTTP/1.0
Host: 192.168.2.10:5000
User-Agent: fhem
Accept-Encoding: gzip,deflate
Content-Type: multipart/form-data, boundary=AaB03x
Content-Length: 361


--AaB03x
content-disposition: form-data; name="path"

/home/upload
--AaB03x
content-disposition: form-data; name="create_parents"

true
--AaB03x
content-disposition: form-data; name="overwrite"

true
--AaB03x
content-disposition: form-data; name="file"; filename="file1.txt"
Content-Type: application/octet-stream

0123456789aBcDeF
--AaB03x--
2020.10.21 09:57:30.625 1: http://192.168.2.10:5000/webapi/entry.cgi?api=SYNO.FileStation.Upload&version=2&method=upload&_sid=wIW_bdkKplgfP4ceU4zxMuj4Xbms4lGi7weKn8Gon9ke58d9fk7b-sHmL0ZzGd_dH9kqc8eh_M0GUfVXWsr-BM: HTTP response code 200
....
Dabei habe ich bemerkt, dass unter dem Header nach "Content-Length: 361" nicht ein CRLF wie erwartet, sondern zwei CRLF eingefügt
wurden. Nachdem ich nun das führende CRLF in meinem Testaufbau weggelassen habe, funktioniert es dann.

D.h. HttpUtils fügt einen CRLF nach dem Header automatisch ein.
Meiner Meinung nach passiert das in Zeile 613:

$hdr .= "\r\n";
Jetzt stellt sich mir die Frage, ob dieses eingefügte CRLF nach dem Header seine Berechtigung hat.
Zumindest in meinem speziellen Fall von POST mit multipart/form-data bewirkt es eine Störung des Aufbaus nach RFC.
Wenn man es herausbekommen hat was stört, war es einfach zu lösen.
Aber möglicherweise stolpern andere User/Entwickler auch über ein solches Thema und wundern sich warum die Datenfolge nicht
funktioniert.

Ich kann jetzt nicht übersehen wieso dieses CRLF nach dem Header eingefügt wird, aber vllt. sollte/kann es entfernt werden ?

Danke und viele Grüße,
Heiko   
« Letzte Änderung: 21 Oktober 2020, 11:56:08 von DS_Starter »
ESXi 6.5 @NUC6i5SYH mit FHEM auf Debian 10, DbLog/DbRep mit MariaDB auf Synology 415+
Maintainer: SSCam, SSChatBot, SSCal, SSFile, DbLog/DbRep, Log2Syslog, SMAPortal, Watches, Dashboard
Kaffeekasse: https://www.paypal.me/HMaaz
Contrib: https://svn.fhem.de/trac/browser/trunk/fhem/contrib/DS_Starter

Offline rudolfkoenig

  • Administrator
  • Hero Member
  • *****
  • Beiträge: 23125
Zitat
Jetzt stellt sich mir die Frage, ob dieses eingefügte CRLF nach dem Header seine Berechtigung hat.
Ich beantworte sie mit ja :)

Ein HTTP-Header endet mit einer leeren Zeile.
In deinem Fall muss wohl das erste Body-Part auf dem ersten CR/NL verzichten.

Offline DS_Starter

  • Developer
  • Hero Member
  • ****
  • Beiträge: 6140
Danke für das Statement Rudi.  :)

Auf das erste CRLF zu verzichten ist kein Problem, allerdings muß man erstmal darauf kommen dass dieser Umstand das Problem ist.  ;)
Vielleicht ist es einen Hinweis im HttpUtils Wiki für $param->{data} wert ?
ESXi 6.5 @NUC6i5SYH mit FHEM auf Debian 10, DbLog/DbRep mit MariaDB auf Synology 415+
Maintainer: SSCam, SSChatBot, SSCal, SSFile, DbLog/DbRep, Log2Syslog, SMAPortal, Watches, Dashboard
Kaffeekasse: https://www.paypal.me/HMaaz
Contrib: https://svn.fhem.de/trac/browser/trunk/fhem/contrib/DS_Starter