![]() |
REST via Indy IdHTTP, Problem mit JSON/Content-Length
Moin,
bei einer (XE6-)REST-Kommunikation via Indy IdHTTP als POST tritt ein Problem mit der Content-Length und dem JSON-Format auf. Wenn ein JSON gesendet wird: Body:
Code:
komme eine Socket-Error#10054 und keine Response-JSON vom Server zurück.
{
"recordtype" : "REC1", "dealer": "xxxx", "branch":xx, "ordernumber": xxxxxx } Das funktioniert übrigens in POSTMAN problemlos:
Code:
POST https://xxxxxxmobile-xx.xxxxx.com/xxx/api/v2/xxx/xxxx/xxxxxxxxxxxx
POST /xxx/api/v2/xxx/xxxx/xxxxxxxxxxxxx HTTP/1.1 Content-Type: application/json Authorization: Bearer ey...Tw Host: xxxxxxmobile-xx.xxxxx.com Content-Length: 88 Cookie: 053...20a; TS0172207b=01...94b { "recordtype" : "REC1", "dealer": "xxxx", "branch":xx, "ordernumber": xxxxxx } HTTP/1.1 200 OK content-type: application/json; charset=utf-8 date: Tue, 15 Aug 2023 11:18:56 GMT vary: Accept-Encoding x-kong-upstream-latency: 90 x-kong-proxy-latency: 18 via: kong/2.0.4 Set-Cookie: TS0172207b=01...c72bf; Path=/; Domain=.xxxxxxmobile-xx.xxxxx.com; Secure; HTTPOnly Transfer-Encoding: chunked { "recordtype": "REC1", "dealer": "xxxx ", "branch": xx, "ordernumber": xxxxxx, "returncode": "00" } Dann ein JSON im Format:
Code:
mit der "Content-Length: 0" (! s.u.)
{"recordtype":"REC1","dealer":"xxxx","branch":xx,"ordernumber":xxxxxx}
Jetzt reagiert der Server mit der Antwort:
Code:
HTTP/1.1 400 Bad Request
{ "errorCode": "URL0001", "message": "No input dataÜ" }
Code:
Req:
POST /xxx/api/v2/xxx/xxxx/xxxxxxxxxxxx HTTP/1.1 Content-Type: application/json Content-Length: 0 Authorization: Bearer ey...5AQ Cookie: 053...20a; TS0172207b=01...1c Body: {"recordtype":"REC1","dealer":"xxxx","branch":xx,"ordernumber":xxxxxx} Host: xxxxxxmobile-xx.xxxxx.com Accept: */* Accept-Encoding: identity User-Agent: Mozilla/3.0 (compatible; Indy Library) Resp: HTTP/1.1 400 Bad Request content-type: application/json; charset=utf-8 date: Tue, 15 Aug 2023 17:57:22 GMT x-kong-upstream-latency: 50 x-kong-proxy-latency: 17 via: kong/2.0.4 Set-Cookie: TS0......c75; Path=/; Domain=.xxxxxxmobile-xx.xxxxx.com; Secure; HTTPOnly Transfer-Encoding: chunked Resp: { "errorCode": "URL0001", "message": "No input dataÜ" } Da Content-Length: 0 ist, wie von IdHTTP/POST generiert, diesmal MIT Content-Length: 0 UND Content-Length: 72:
Code:
das POST und das Programm hängt ohne response.
Req:
POST /xxx/api/v2/xxx/xxxx/xxxxxxxxxxxxx HTTP/1.1 Content-Type: application/json Content-Length: 0 Authorization: Bearer ey..qg Cookie: 053...0a; TS0172207b=01f...1c Body: {"recordtype":"REC1","dealer":"xxxx","branch":xx,"ordernumber":xxxxxx} Content-Length: 72 Host: xxxxxxmobile-xx.xxxxx.com Accept: */* Accept-Encoding: identity User-Agent: Mozilla/3.0 (compatible; Indy Library)
Delphi-Quellcode:
Der Server hat offenbar ein Problem mit dem JSON-Format des IdHTTP-Body. Gut, das darf er, er nimmt ja das formatlose JSON.
IdLogFile.Filename:='LogOrder.txt';
IdLogFile.Active:=true; IdHTTP.Response.Clear; IdHTTP.Request.Clear; with IdSSLIOHandlerSocketOpenSSL do begin SSLOptions.SSLVersions := [sslvTLSv1, sslvTLSv1_1, sslvTLSv1_2]; SSLOptions.Mode := sslmClient; SSLOptions.VerifyMode := []; SSLOptions.VerifyDepth := 0; DefStringEncoding := enUTF8; ReadTimeout := 1000; ConnectTimeout := 1000; end; with IdHTTP do begin ConnectTimeout := 1000; AllowCookies := True; HandleRedirects := True; IOHandler := IdSSLIOHandlerSocketOpenSSL; end; with IdHTTP.Request do begin Clear; BasicAuthentication := false; Accept:='*/*'; ContentType:='application/json'; CustomHeaders.AddValue('Authorization', 'Bearer ' + token); CustomHeaders.AddValue('Cookie','053...20a; TS0172207b=01f...1c'); CustomHeaders.AddValue('Body',Body); // ContentLength:=length(Body); //see Remy Lebeau ! // CustomHeaders.AddValue('Content-Length',length(Body).ToString()); end; rs :=IdHTTP.Post(BaseURL, ResponseList); except on E: Exception do begin Mal rhetorisch gefragt: was macht IdHTTP mit dem JSON dass der Server es nicht annimmt? Im Log sieht es harmlos aus. IdHTTP/POST generiert eine Content-Length: 0 und das mag der Server auch nicht. Wie Remy Lebeau so richtig sagt: DO NOT set a ContentLength manually, let Post() fill it in for you.. Ok, wie überrede ich IdHTTP/POST dazu, eine richtige Content-Length über length(Body) zu bilden? mny tnx! Thomas |
AW: REST via Indy IdHTTP, Problem mit JSON/Content-Length
So etwas debugge ich meistens sehr einfach:
Ich lege mir ein Skript auf einen Server, das loggt, was dorthin gesendet wird. Auf diese Weise kann ich auch einfach an eine URL ohne SSL die Anfragen schicken und so beide z.B. in Wireshark vergleichen, da diese dort im Klartext erscheinen. Das kann man natürlich auch mit einem Proxy oder ähnlichem erreichen, aber so ist es ganz einfach. |
gelöst: REST via Indy IdHTTP, Problem mit JSON/Content-Length
@Sebastian
Guter Tip! Die Lösung für Content-Length ist einfach: (JSON im Body:string)
Delphi-Quellcode:
Und schon stimmt die Content-Length. Also nicht: CustomHeaders.AddValue('Body',Body);
RequestBody:=TStringStream.Create(Body,TEncoding.UTF8);
... Response:=IdHTTP.Post(Base, RequestBody); ... wer lesen kann ist klar im Vorteil... mny tnx Thomas |
AW: gelöst: REST via Indy IdHTTP, Problem mit JSON/Content-Length
Jupp, die Daten "nach" den Headern, mit einer Leerzeile dawischen (welche das Ende der Header kennzeichnet)
Drum kann das so
Code:
eigentlich auch nicht richtig sein.
Cookie: 053...20a; TS0172207b=01...94b
{ |
AW: REST via Indy IdHTTP, Problem mit JSON/Content-Length
Zitat:
Wenn es ein Bug in der alten Indy Version ist, stehen die Chancen gut dass dieser mittlerweile behoben ist. Die neue Version kann testweise einfach in einem neuen Verzeichnis entpackt werden - eine Package-Installation ist nicht unbedingt notwendig. |
AW: REST via Indy IdHTTP, Problem mit JSON/Content-Length
@himitsu
Zitat:
@mjustin Zitat:
![]() |
AW: REST via Indy IdHTTP, Problem mit JSON/Content-Length
Einfach z.B. von GitHub runterladen,
dann das SourceVerzeichnis im Suchpfad (Projektoptionen) des aktuellen Programms. Oder die Indy-Quellcodes ins Projektverzeichnis kopieren. Es werden dann direkt die PAS einkompiliert (Laufzeitpackages=False), drum sind keine DCU oder DCP/BPL nötig, weswegen es auch nicht nörtig ist das Indy-Setup auszuführen. Du kannst dabei bloß keine Form im FormDesigner öffnen, wo komponenten drauf liegen. (bzw. es geht womöglich, wobei im Designer dann aber die derzeit installierte Version genutzt würde) |
Alle Zeitangaben in WEZ +1. Es ist jetzt 01:04 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz