![]() |
Indy HTTPClient Post umlaute
Hallo,
ich habe zwar schon viel gelesen hier mit umlauten aber nichts klappt. Folgendes: ich sende mit POST(URL,String) z.b. öäü und bekomme laut PHP print_r($_POST); nur ??? zurück. Ich habe schon hnForceEncodeParams auf False sonst geht es garnicht. Hintergrund: Ich muss an einen Server z.b.
Code:
senden.
{ "q": "Länge 8,5 cm","source": "de", "target": "en", "api_key": "#####"}
Zurück bekomme ich
Code:
Der ContentType MUSS application/json sein sonst kommt 400 zurück. Wandel ich es in UTF-8 um, bekomme ich z.b. statt L?nge, L??nge zurück.
Array
( [{_"q":_"L?nge_8,5_cm","source":_"de",_"target":_"en",_"api_key":_"######"}] => ) Habe ich in der der Quelle keine umlaute klappt alles. Ich hoffe mir kann jemand helfen. Vielen Dank im voraus |
AW: Indy HTTPClient Post umlaute
Eventuell codieren? "Ä" wird "& # 1 9 6 ;" usw. (Leerzeichen entfernen)
(wenn ich die Leerzeichen weglasse, konvertiert mir das Forum automatisch den Ausdruck wieder nach "Ä", auch in Code-Tags. gna!) P.S. nochn Versuch: codiere "Ä" als "&# 196;" codiere "Ö" als "&# 214;" codiere "Ü" als "&# 220;" codiere "ä" als "&# 228;" codiere "ö" als "&# 246;" codiere "ü" als "&# 252;" codiere "ß" als "&# 223;" (wieder das Leerzeichen zwischen "#" und der ersten Ziffer entfernen) |
AW: Indy HTTPClient Post umlaute
Sorry, entweder steh ich mal wieder auf der Leitung oder... keine Ahnung. Ich verstehe das nicht.
|
AW: Indy HTTPClient Post umlaute
Welches Encoding verwendest du denn beim Senden? Üblich wäre UTF8.
|
AW: Indy HTTPClient Post umlaute
Zitat:
|
AW: Indy HTTPClient Post umlaute
@jaenicke,
Zitat:
|
AW: Indy HTTPClient Post umlaute
Noch zur Info...
Das verwundert mich nun aber... Ich habe mal mit Wireshark geschaut was raus geht.
Code:
Ich verstehe das nicht.
POST /translate HTTP/1.0
Connection: keep-alive Content-Type: application/json Content-Length: 105 Host: translate.lan:5000 Accept: application/json User-Agent: 'User-Agent', 'Mozilla/5.0 Cookie: session=75dbc5ad-adaf-4cb0-94e6-aaf4cf78cd31 { "q": "L?nger 8,5 cm","source": "de", "target": "en", "api_key": "#####"} |
AW: Indy HTTPClient Post umlaute
Da fehlt auf Delphi-Seite der charset Header wenn ich das richtig sehe.
Code:
HttpReq.Request.CharSet := 'utf-8';
|
AW: Indy HTTPClient Post umlaute
Den kann ich nicht angeben. Dann komm Fehler 400.
Wireshark:
Code:
POST /translate HTTP/1.0
Connection: keep-alive Content-Type: application/json; charset=UTF-8 Content-Length: 96 Host: translate.lan:5000 Accept: application/json User-Agent: 'User-Agent', 'Mozilla/5.0 { "q": "L?nge,"source": "de", "target": "en", "api_key": "######"}HTTP/1.0 400 BAD REQUEST |
AW: Indy HTTPClient Post umlaute
Dann muss das wahrscheinlich in der Webanwendung gefixt werden.
|
AW: Indy HTTPClient Post umlaute
Das ist LibreTranslate. Also das muss irgendwie gehen. Leider finde ich nichts darüber oder wieder zu doof zum suchen.
|
AW: Indy HTTPClient Post umlaute
Das sendet er bei UTF-8. Es kommt zwar ein 200 zurück aber halt L??nge
Code:
POST /translate HTTP/1.0
Connection: keep-alive Content-Encoding: UTF-8 Content-Type: application/json Content-Length: 105 Host: translate.lan:5000 Accept: application/json User-Agent: 'User-Agent', 'Mozilla/5.0 { "q": "L??nge 8,5 cm","source": "de", "target": "en", "api_key": "#######"}HTTP/1.0 200 OK |
AW: Indy HTTPClient Post umlaute
Probier doch mal mit einem separaten API client, z.B.
![]() |
AW: Indy HTTPClient Post umlaute
Mein letzter Post (hoffe ich). Mit Overbyte geht es auf anhieb. UTF8Encode() und absenden. Klappt.
Ob Indy da eventuell einen "kleinen" Fehler hat? |
AW: Indy HTTPClient Post umlaute
Mein persönlicher Geschmack war Indy nie. Ich hatte sehr mit denen gekämpft, als ich mit TCP/IP anfing...und mit den ICS hat es auf Anhieb geklappt. Die sind auch irgendwie mehr "delphisch" (vergleiche mit Pythons "pythonic").
|
AW: Indy HTTPClient Post umlaute
Zitat:
Delphi-Quellcode:
Da du keinen Quelltext gezeigt hast, kann ich auch nicht beurteilen, was bei dir falsch läuft.
var
Http: TIdHTTP; Data: TStringList; begin Http := TIdHTTP.Create(Self); try Data := TStringList.Create; try Data.Add('{ "q": "Länge 8,5 cm","source": "de", "target": "en", "api_key": "#####"}'); ShowMessage(Http.Post('http://www.familie-jaenicke.de/b.php', Data, IndyTextEncoding_UTF8)); finally Data.Free; end; finally Http.Free; end; end; |
AW: Indy HTTPClient Post umlaute
So wie ich gelesen habe, bin ich nicht der einzige mit diesem Fehler. Du hast eine andere Indy Version als ich. z.b. bei Delphi 2009 soll der Bug noch drin gewesen sein. Quelle der Info:
![]() Aber mit OverByte ging es sofort. Deswegen....... |
AW: Indy HTTPClient Post umlaute
Zitat:
Delphi-Quellcode:
Wie schon geschrieben: Ohne deinen Code kann man dir auch nur sehr schlecht helfen. Darum ist es immer am besten ein Beispielprojekt oder Beispielcode zu zeigen, mit dem du es versucht hast...
var
Http: TIdHTTP; Data: TStringList; begin Http := TIdHTTP.Create(Self); try Data := TStringList.Create; try Data.Add('{ "q": "Länge 8,5 cm","source": "de", "target": "en", "api_key": "#####"}'); ShowMessage(Http.Post('http://www.familie-jaenicke.de/b.php', Data)); finally Data.Free; end; finally Http.Free; end; end; ICS ist eine gute Wahl, aber mit Indy geht es auch. |
AW: Indy HTTPClient Post umlaute
Zitat:
Dein Code läuft mit deiner URL/deinem PHP Skript super und ä kommt an. Wenn man aber den Code zum Beispiel auf 'http://httpbin.org/post' loslässt, dann gibt der Server ä Unicode codiert zurück: "{ \"q\": \"L\u00e4nge 8,5 cm\",\"source\": \"de\", |
AW: Indy HTTPClient Post umlaute
Eben das ist der Punkt. Wenn man nicht weiß, wie der Quelltext aussieht, kann man nicht sagen, woran es liegt. Wenn ich ein konkretes Beispiel habe, kann ich sehen oder auch testen was raus geht.
|
AW: Indy HTTPClient Post umlaute
Zitat:
Hier der Code, also der Kern. Alles zu posten ist was lang. Indy:
Delphi-Quellcode:
ICS:
pdata:=TStringList.Create;
for i:=0 to memoPost.Lines.Count-1 do begin pdata.Add(UTF8Encode(memoPost.Lines.Strings[i])); end; try line:=HTTPClient.Post(URL,pdata); except i:=1; end; memoAnswer.Lines.Text:=line;
Delphi-Quellcode:
ICS ging auf anhieb. Und wie gesagt ich denke das ich die gebuggte Version von Indy habe. Ich habe vor Jahren mal Indy 10.6.0 Installiert. Nun wo man es weiß, sollte ich das mal updaten. Man kann ja auch mit Wireshark sehen das Indy das falsch übergibt. Indy macht ja die ? rein.
SndStrm := TMemoryStream.Create;
RcvStrm := TMemoryStream.Create; Data := UTF8Encode(memoPost.Lines.Text); HttpCli1.SendStream := SndStrm; HttpCli1.SendStream.Write(Data[1],Length(Data)); HttpCli1.SendStream.Seek(0,0); HttpCli1.RcvdStream := RcvStrm; HttpCli1.URL := URL; HttpCli1.Post; RcvStrm.Position:=0; memoAnswer.Lines.LoadFromStream(RcvStrm); memoAnswer.Lines.Add('....'); RcvStrm.Free; SndStrm.Free; |
AW: Indy HTTPClient Post umlaute
Das stimmt, mit dem UTF8Encode kommt es falsch an. Es sei denn ich lese es auf dem Server auch wieder als UTF-8 ein:
Delphi-Quellcode:
Der Grund ist simpel:
<?php
print_r(mb_convert_encoding($_POST, 'ISO-8859-1', 'UTF-8')); ?> Du kodierst es zwar als UTF-8, teilst das aber nicht mit. ICS wiederum verwendet UTF-8 Encoding als Standard, weshalb du das dort nicht explizit setzen musst. Korrekt mit Indy ist daher:
Delphi-Quellcode:
pdata:=TStringList.Create;
for i:=0 to memoPost.Lines.Count-1 do begin pdata.Add(UTF8Encode(memoPost.Lines.Strings[i])); end; try HTTPClient.Request.ContentEncoding := 'UTF-8'; line:=HTTPClient.Post(URL,pdata); except i:=1; end; memoAnswer.Lines.Text:=line; |
AW: Indy HTTPClient Post umlaute
Hi, bitte steck da keine Zeit mehr rein.
Delphi-Quellcode:
HTTPClient.Request.ContentEncoding := 'UTF-8';
Das habe ich alles versucht. Bevor ich hier Frage, kannst du davon ausgehen das ich mind. 2 Tage versuche das selber zu lösen. Und ja, das php gibt UTF-8 zurück und nimmt es an. Ich danke dir trotzdem Tausend mal für deine Hilfe und mühe. :thumb: |
AW: Indy HTTPClient Post umlaute
Delphi-Quellcode:
jaenicke ich habe
procedure libretranslate_Indy;
var json : rawbytestring; line : WideString; Stream: TStream; begin Stream := TMemoryStream.Create; try json := UTF8Encode('{ "q": "anöa","source": "auto", "target": "en", "api_key": ""}'); Stream.WriteBuffer(Pointer(json)^, Length(json)); Stream.Position := 0; form103.idhttp1.Request.ContentType := 'application/json'; line := UTF8Decode(form103.idhttp1.Post('http://127.0.0.1:5000/translate',stream)); // line:=form103.idhttp1.Post('http://httpbin.org/anything',pdata); Showmessage( line ); finally stream.Free; end; end; ![]() ![]() Sogar das funktioniert: json := UTF8Encode('{ "q": "أرى الكلب الأزرق الصغير خلف المنزل الأصفر على النهر الأحمر.","source": "auto", "target": "en", "api_key": ""}'); |
AW: Indy HTTPClient Post umlaute
Hi,
du musst auf jeden fall hoForceEncodeParams auf False setzen. Nachtrag: Nimm doch ICS, klappt auf anhieb. Ich habe grade mal Indy 10.6.3.1 Installiert. Selber Fehler. |
AW: Indy HTTPClient Post umlaute
Der Code in #24 funktioniert.
Ich nutze Indy sonst nicht - nur weil du gefragt hast, habe ich das Ding wieder einmal angeschaut - und es reicht wieder für ein paar Wochen. Ich nutze ICS. Fürs Posten setze ich wohl häufiger TNetHTTPClient, weil diese Komponente direkt mit den Sicherheitsfunktionen (https Unterstützung ohne "Basteln") von Windows interagiert. Herzlichen Dank für deinen Supertipp "libretranslate" - kannte ich nicht, ist grossartig und es fallen mir viele Dinge ein, welche ich tun würde, wenn ich mehr Zeit hätte... Dein Tipp "hoForceEncodeParams entfernen" gilt fürs Post mit zweitem Parameter TStringList, da sonst die Daten nur im HTTP Header landen und von libretranslate nicht "gesehen" werden (Bad request). Für post via Stream spielt die Option keine Rolle. Stream wird (wie von libretranslate gewünscht) im Body übertragen. Wenn ich den Indy Code anschaue, glaube ich, dass das Posten in diesem Fall mit TStrings nicht klappen kann. Wünsche wie Request.CharSet := 'utf-8'; Request.ContentEncoding := 'utf-8' oder utf8 beim Post als dritten Parameter setzen werden von Indy nicht berücksichtigt. Indy behandelt die von dir beim Post als zweiten Parameter übergebene TStringList als Parameter vom Typ par1=val1&par2=val2.... und codiert diese entsprechend via URLEncode. Die ?, welche du gesehen hast waren "nicht druckbare" Zeichen; HEX Monitor nutzen wäre hier u.U. aufschlussreicher. Fiddler ist übrigens grossartig, wenn du http Traffic untersuchen willst. Kurz: Beim Posten der json Daten statt TStrings einen Stream verwenden löst das Problem. Ich habe in #24 TMemorystream verwendet. Viel schöner ist es mit einem TStringStream (Copilot hat dies übrigens vorgeschlagen, als ich fragte, ob man den Code vereinfachen oder schöner schreiben könne.) Ich habe nun auch eine Fehlerbehandlung (ich habe Copilot nicht gefragt was KI davon hält ;-)) eingebaut:
Delphi-Quellcode:
oder via TNetHTTPClient (SSL Unterstützung)
function fehler : string;
var fehlermeldung : PCHar; begin getmem( fehlermeldung , 600 ); ExceptionErrorMessage( ExceptObject, ExceptAddr, fehlermeldung, 599 ); Result := fehlermeldung; end; function libretranslate_Indy(uebersetze : string; var uebersetzung : string ) : boolean; // RESULT=false, wenn eine Exception aufgetreten ist // Bei RESULT=false wird in uebersetzung die Fehlermeldung übergeben // Bei RESULT=true wird in übersetzung die Serverantwort von libretranslate zurückgeben. var JsonToSend : TStringStream; idhttp : TIdHTTP; begin Result := false; try JsonToSend := TStringStream.Create(uebersetze, TEncoding.UTF8); idhttp := TIdHTTP.Create(nil); try idhttp.Request.ContentType := 'application/json'; uebersetzung := UTF8Decode(idhttp.post('http://127.0.0.1:5000/translate',jsontosend)); Result := true; finally jsontosend.free; idhttp.Free; end; except uebersetzung := fehler; Result := false; end; end;
Delphi-Quellcode:
procedure WriteStringToStream(Stream: TStream; const Str: String);
var Data: TBytes; begin Data := TEncoding.UTF8.GetBytes(Str); Stream.WriteBuffer(Data[0], Length(Data)); end; function CreateHTTPClient: TNetHTTPClient; begin Result := TNetHTTPClient.Create(nil); end; function CreateHTTPRequest(Client: TNetHTTPClient): TNetHTTPRequest; begin Result := TNetHTTPRequest.Create(nil); Result.Client := Client; Result.CustomHeaders['Content-Type'] := 'application/json'; end; function CreateParamsStream(const Str: String): TStream; begin Result := TMemoryStream.Create; WriteStringToStream(Result, Str); Result.Position := 0; end; (* SSL/TLS-Details abstrahiert; interagiert direkt mit den Windows-Sicherheitsfunktionen *) procedure Uebersetze; var HTTPClient: TNetHTTPClient; HTTPRequest: TNetHTTPRequest; Params: TStream; Response: IHTTPResponse; begin HTTPClient := CreateHTTPClient; HTTPRequest := CreateHTTPRequest(HTTPClient); Params := CreateParamsStream(atest); try Response := HTTPRequest.Post('http://127.0.0.1:5000/translate', Params); ShowMessage(Response.ContentAsString(TEncoding.UTF8)); finally HTTPRequest.Free; HTTPClient.Free; Params.free; end; end; |
AW: Indy HTTPClient Post umlaute
Hi,
sowas sollte man sich mit Wireshark ansehen. Hier mal kurz. Indy mit hoForceEncodeParams
Code:
Das würde normalerweise wieder zusammen gebastelt. Aber Libre kann bzw. macht das nicht.
POST /translate HTTP/1.0
Connection: keep-alive Content-Encoding: UTF-8 Content-Type: application/json Content-Length: 167 Host: translate.lan:5000 Accept: application/json Accept-Charset: UTF-8 Accept-Encoding: UTF-8, identity User-Agent: 'User-Agent', 'Mozilla/5.0 %7B+%22q%22%3A+%22L%C3%83%C2%A4nge+8%2C5+cm%22%2C%22source%22%3A+%22de%22%2C+%22target%22%3A+%22en%22%2C+%22api_key%22%3A+%22%22%7D Indy ohne hoForceEncodeParams
Code:
ICS:
POST /translate HTTP/1.0
Connection: keep-alive Content-Encoding: UTF-8 Content-Type: application/json Content-Length: 105 Host: translate.lan:5000 Accept: application/json Accept-Charset: UTF-8 Accept-Encoding: UTF-8, identity User-Agent: 'User-Agent', 'Mozilla/5.0 { "q": "L??nge 8,5 cm","source": "de", "target": "en", "api_key": "##########"}
Code:
POST /translate HTTP/1.0
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */* Content-Type: application/json User-Agent: Mozilla/4.0 Host: translate.lan:5000 Content-Length: 107 { "q": "Länge 8,5 cm","source": "de", "target": "en", "api_key": "############"} |
AW: Indy HTTPClient Post umlaute
Ja ich weiss. Libre ist nicht so frei im Denken. Aber meinen Code hast du probiert? Sollte mit dem aktuellen libretranslate klappen. Und mit Indy TStrings geht's ja vielleicht auch nach Setzen von Eigenschaft X und Abschalten von Y und Löschen von Z ;-).
|
AW: Indy HTTPClient Post umlaute
Zitat:
das habe ich schon alles hinter mir. |
AW: Indy HTTPClient Post umlaute
Nun habe ich doch kurz libretranslate in einer meiner Linux-VMs installiert. Es stimmt, die Variante mit TStrings funktioniert nicht so wie erwartet. Das bekommt man zwar hin, aber einfacher ist es so:
Delphi-Quellcode:
Das funktioniert unter Delphi 2007 und z.B. Delphi 11 analog. Genauso klappt es auch mit ICS. Manuell in den Stream schreiben ist auch dort nicht notwendig.
function Translate(const AText, ASourceLang, ADestLang, AApiKey: string): string;
var Http: TIdHTTP; Data: TStream; begin Http := TIdHTTP.Create(nil); try Data := TStringStream.Create(UTF8Encode( Format('{"q": "%s","source": "%s", "target": "%s", "api_key": "%s"}', [AText, ASourceLang, ADestLang, AApiKey]))); try Http.Request.ContentType := 'application/json'; Result := UTF8Decode(Http.Post('http://192.168.119.53:5000/translate', Data)); finally Data.Free; end; finally Http.Free; end; end; ShowMessage(Translate('Länge 8,5 cm', 'de', 'en', '')); ShowMessage(Translate('Length 8,5 cm', 'en', 'de', '')); Wenn du Streams verwendest, funktioniert es mit Indy und ICS identisch. |
AW: Indy HTTPClient Post umlaute
Huhu,
das hat dir aber keine ruhe gelassen, gell... :coder2: Da kenne ich noch einen der weiter gesucht hat. Er kam auf die gleiche Lösung. Aber wie gesagt ich habe mich entschlossen ICS zu nehmen, zumal die das "neue" SSL unterstützen, deswegen hatte ich da nicht weitergesucht. Ich dachte ja erst das ich einen "dummen" Fehler mache. Deswegen hatte nach viel googlen gefragt was ich schon wieder falsch mache. Einen schönen Sonntag wünsche ich dir... |
AW: Indy HTTPClient Post umlaute
Zitat:
Kürzeste Änderung (ohne eine Zeile weiteren Code) wäre gewesen: Wenn idhttp.post('http://127.0.0.1:5000/translate',hs); nicht funktioniert, dann streame idhttp.post('http://127.0.0.1:5000/translate',TStringStream.Create(hs.Text, TEncoding.UTF8))); Bloss frage ich mich bei solchen Konstrukten jeweils immer "wer räumt danach auf" ;-). Wenn man bei Indy Post mit TStrings verwendet: Auch Indy verwendet Streams, macht aber dies: mit Option hoForceEncodePar erwartet Indy, dass man ![]() ohne Option hoForceEncodePar gibt leider Indy die beim Post angegebene Kodierung nicht weiter. (hier glaube ich eher an einen Bug als an by design) Indy prüft zwar dann, ob eine Kodierung ausgewählt worden ist, diese ist aber halt dann immer nil. Indy prüft bei nil auf GIdDefaultTextEncoding und wählt diese. D.h. wenn man vor dem Post GIdDefaultTextEncoding := encUTF8; setzt, funktioniert idhttp.post('http://127.0.0.1:5000/translate',hs); jeanicke, ich habe noch eine Frage zu deinem #22. Du verwendest dort UTF8Encode() und fügst den encodierten string einer TStringlist hinzu:
Delphi-Quellcode:
Ist das ein neues Feature von Delphi 12? Ich bin immer noch auf dem Stand 11.2 (weil Delphi 11.2 bis auf wenige Macken so super läuft). Und in 11.2 kann TStringList keine utf8strings aufnehmen.
pdata:=TStringList.Create;
for i:=0 to memoPost.Lines.Count-1 do begin pdata.Add(UTF8Encode(..)); D.h. bei meinem Delphi ist, wenn u : utf8string; s : string; nach u := s, s := u in s wieder ein string drin. Oder anders geschrieben: In meinem Delphi ist pdata.Add(UTFEncode(s)) gleichwertig mit pdata.Add(s). Kann Delphi 12 hier mehr? |
AW: Indy HTTPClient Post umlaute
Zitat:
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 22:05 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 by Thomas Breitkreuz