AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Netzwerke Delphi Indy HTTPClient Post umlaute
Thema durchsuchen
Ansicht
Themen-Optionen

Indy HTTPClient Post umlaute

Ein Thema von DelTurbo · begonnen am 16. Apr 2024 · letzter Beitrag vom 21. Apr 2024
Antwort Antwort
Seite 3 von 4     123 4      
DelTurbo

Registriert seit: 12. Dez 2009
Ort: Eifel
1.212 Beiträge
 
Delphi 2007 Architect
 
#21

AW: Indy HTTPClient Post umlaute

  Alt 17. Apr 2024, 10:30
"{ \"q\": \"L\u00e4nge 8,5 cm\",\"source\": \"de\",
Das nimmt er nicht an. Er will das wirklich so wie ich geschrieben hatte.

Hier der Code, also der Kern. Alles zu posten ist was lang.
Indy:
Delphi-Quellcode:
    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;
ICS:
Delphi-Quellcode:
    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;
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.
Alle meine Rechtschreibfehler sind Urheberrechtlich geschützt!!
  Mit Zitat antworten Zitat
Benutzerbild von jaenicke
jaenicke

Registriert seit: 10. Jun 2003
Ort: Berlin
9.589 Beiträge
 
Delphi 11 Alexandria
 
#22

AW: Indy HTTPClient Post umlaute

  Alt 17. Apr 2024, 13:29
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:
<?php
print_r(mb_convert_encoding($_POST, 'ISO-8859-1', 'UTF-8'));
?>
Der Grund ist simpel:
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;
Sebastian Jänicke
Alle eigenen Projekte sind eingestellt, ebenso meine Homepage, Downloadlinks usw. im Forum bleiben aktiv!
  Mit Zitat antworten Zitat
DelTurbo

Registriert seit: 12. Dez 2009
Ort: Eifel
1.212 Beiträge
 
Delphi 2007 Architect
 
#23

AW: Indy HTTPClient Post umlaute

  Alt 17. Apr 2024, 14:18
Hi, bitte steck da keine Zeit mehr rein.

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.
Alle meine Rechtschreibfehler sind Urheberrechtlich geschützt!!
  Mit Zitat antworten Zitat
Michael II

Registriert seit: 1. Dez 2012
Ort: CH BE Eriswil
760 Beiträge
 
Delphi 11 Alexandria
 
#24

AW: Indy HTTPClient Post umlaute

  Alt 17. Apr 2024, 18:05
Delphi-Quellcode:
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;
jaenicke ich habe libretranslate lokal installiert (und Fiddler fürs Vergleichen von Header und Daten und...) und da führt dein Code beim "Post" zu einem Bad Request oder einem Method not allowed. Eventuell mache ich was falsch. - Ich glaube aber, dass der Code oben funktionieren sollte. Bei mir werden die Sonderzeichen im Response als Sonderzeichen angezeigt.

Sogar das funktioniert: json := UTF8Encode('{ "q": "أرى الكلب الأزرق الصغير خلف المنزل الأصفر على النهر الأحمر.","source": "auto", "target": "en", "api_key": ""}');
Michael Gasser

Geändert von Michael II (18. Apr 2024 um 01:51 Uhr)
  Mit Zitat antworten Zitat
DelTurbo

Registriert seit: 12. Dez 2009
Ort: Eifel
1.212 Beiträge
 
Delphi 2007 Architect
 
#25

AW: Indy HTTPClient Post umlaute

  Alt 18. Apr 2024, 10:23
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.
Alle meine Rechtschreibfehler sind Urheberrechtlich geschützt!!

Geändert von DelTurbo (18. Apr 2024 um 11:50 Uhr) Grund: Weil ich nicht so schnell bin
  Mit Zitat antworten Zitat
Michael II

Registriert seit: 1. Dez 2012
Ort: CH BE Eriswil
760 Beiträge
 
Delphi 11 Alexandria
 
#26

AW: Indy HTTPClient Post umlaute

  Alt 18. Apr 2024, 16:23
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:
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;
oder via TNetHTTPClient (SSL Unterstützung)
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;
Michael Gasser

Geändert von Michael II (18. Apr 2024 um 16:26 Uhr)
  Mit Zitat antworten Zitat
DelTurbo

Registriert seit: 12. Dez 2009
Ort: Eifel
1.212 Beiträge
 
Delphi 2007 Architect
 
#27

AW: Indy HTTPClient Post umlaute

  Alt 18. Apr 2024, 16:50
Hi,
sowas sollte man sich mit Wireshark ansehen.

Hier mal kurz.


Indy mit hoForceEncodeParams
Code:
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
Das würde normalerweise wieder zusammen gebastelt. Aber Libre kann bzw. macht das nicht.

Indy ohne hoForceEncodeParams
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
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": "##########"}
ICS:
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": "############"}
Alle meine Rechtschreibfehler sind Urheberrechtlich geschützt!!
  Mit Zitat antworten Zitat
Michael II

Registriert seit: 1. Dez 2012
Ort: CH BE Eriswil
760 Beiträge
 
Delphi 11 Alexandria
 
#28

AW: Indy HTTPClient Post umlaute

  Alt 18. Apr 2024, 17:17
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 .
Michael Gasser

Geändert von Michael II (18. Apr 2024 um 17:26 Uhr)
  Mit Zitat antworten Zitat
DelTurbo

Registriert seit: 12. Dez 2009
Ort: Eifel
1.212 Beiträge
 
Delphi 2007 Architect
 
#29

AW: Indy HTTPClient Post umlaute

  Alt 18. Apr 2024, 17:25
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 .
Hi,
das habe ich schon alles hinter mir.
Alle meine Rechtschreibfehler sind Urheberrechtlich geschützt!!
  Mit Zitat antworten Zitat
Benutzerbild von jaenicke
jaenicke

Registriert seit: 10. Jun 2003
Ort: Berlin
9.589 Beiträge
 
Delphi 11 Alexandria
 
#30

AW: Indy HTTPClient Post umlaute

  Alt 21. Apr 2024, 02:30
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:
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', ''));
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.

Wenn du Streams verwendest, funktioniert es mit Indy und ICS identisch.
Sebastian Jänicke
Alle eigenen Projekte sind eingestellt, ebenso meine Homepage, Downloadlinks usw. im Forum bleiben aktiv!
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 3 von 4     123 4      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 23:18 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz