Einzelnen Beitrag anzeigen

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