AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

CURL in Delphi ausführen -d

Ein Thema von Ykcim · begonnen am 5. Feb 2025 · letzter Beitrag vom 6. Feb 2025
Antwort Antwort
Seite 1 von 2  1 2      
Ykcim

Registriert seit: 29. Dez 2006
Ort: NRW
848 Beiträge
 
Delphi 10.4 Sydney
 
#1

CURL in Delphi ausführen -d

  Alt 5. Feb 2025, 18:08
Hallo Zusammen,

ich habe Schwierigkeiten, eine CURL in Delphi zu übersetzen...

Code:
curl -k -i -X POST -H "accept: application/json" -H 'content-type: application/x-www-form-urlencoded' https://api-sandbox.dhl.com/parcel/de/account/auth/ropc/v1/token -d "grant_type=password\&username=user-valid\&password=SandboxPasswort2023!\&client_id=yyyyyyyyyyyyyyy\&client_secret=xxxxxxxxx"
yyy ersetzt den API-Key
xxx ersetzt den API-Secret

Ich habe die CURL bei https://reqbin.com/curl getestet und dort bekomme ich ein richtiges Ergebnis raus.

Ich habe folgende Funktion geschrieben:
Delphi-Quellcode:
function TForm1.GetDHLAccessToken_Own3(APIKEY, APISecret, UserName, Password: string; var URL: string): string;
var Client : TRESTClient;
      Request : TRESTRequest;
      JsResponse: TJSONValue;
      response: TCustomRESTResponse;
begin
   Client := TRESTClient.Create(nil);
   Request:= TRESTRequest.Create(client);
   Try
      Try
         Client.BaseURL:= 'https://api-sandbox.dhl.com';
         Request.Resource:= 'parcel/de/account/auth/ropc/v1/token';

         Request.Method := rmPOST;

         Request.Params.AddItem('accept', 'application/json', pkHTTPHEADER, [poDoNotEncode]);
         Request.Params.AddItem('content-type', 'application/x-www-form-urlencoded', pkHTTPHEADER, [poDoNotEncode]);

         Request.AddParameter('grant_type', 'password', pkGETorPOST, []);
         Request.AddParameter('username', UserName, pkGETorPOST, []);
         Request.AddParameter('password', Password, pkGETorPOST, []);
         Request.AddParameter('client_id', 'APIKEY', pkGETorPOST, []);
         Request.AddParameter('client_secret', 'APISecret', pkGETorPOST, []);

         URL:= Request.GetFullRequestURL;
         Request.Execute;
         if request.Response.StatusCode = 200 then begin
            JsResponse:= TJSONObject.ParseJSONValue(request.Response.Content);
            Result:= JsResponse.GetValue<string>('JWTToken');
         end
         else begin
            ShowMessage(IntToStr(request.Response.StatusCode) + ' ' + request.Response.StatusText);
            Result:= 'Error: ' + IntToStr(request.Response.StatusCode) + ' ' + request.Response.StatusText;
         end;
      Except
         ON e: Exception do begin
            Result:= E.Message;
            ShowMessage('Keine Daten erhalten');
         end;
      end;
   Finally
      Request.Free;
      Client.Free;
   End;
end;
Leider bekomme ich immer als Ergebnis:
Code:
HTTP/1.1 401 Unauthorized
Den Abschnitt mit dem -H gekennzeichnet ist, habe ich in den Header gepackt, alles nach dem -d in den Request.

Kann mir jemand sagen, was ich hier falsch mache?

Vielen Dank
Patrick
Patrick
  Mit Zitat antworten Zitat
Benutzerbild von jaenicke
jaenicke
Online

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

AW: CURL in Delphi ausführen -d

  Alt 5. Feb 2025, 19:14
Mein Tipp ganz allgemein bei solchen Themen:
Nimm dir Wireshark. Damit kannst du in unverschlüsselte Kommunikation sehr einfach hineinschauen. In diesem Fall ist das https, daher würde das nicht so einfach gehen. Aber für Testzwecke ersetze einfach https durch http und sende den Request auf beiden Wegen ab. Der wird zwar dann bei den meisten Servern nicht funktionieren, aber du kannst in Wireshark 1:1 sehen, was geschickt wurde.

Auf diese Weise kannst du den funktionierenden Request sehr einfach mit dem nicht funktionierenden vergleichen.

Zu diesem Fall:
Müssten die Parameter nicht mit pkREQUESTBODY statt pkGETorPOST hinzugefügt werden? Gegebenenfalls noch mit [TRESTRequestParameterOption.poDoNotEncode] wie bei den anderen Parametern, falls das Encoding eine Rolle spielen sollte.
Sebastian Jänicke
AppCentral

Geändert von jaenicke ( 5. Feb 2025 um 19:16 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe

Registriert seit: 20. Jan 2006
Ort: Lübbecke
11.556 Beiträge
 
Delphi 12 Athens
 
#3

AW: CURL in Delphi ausführen -d

  Alt 5. Feb 2025, 21:43
Anstatt der Request.Params.AddItem Aufrufe solltest du besser die entsprechenden Properties Request.Accept und Client.ContentType setzen. Dann weiß TCustomRESTRequest.DoPrepareRequestBody auch wie es die Parameter zusammensetzen muss.
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
Ykcim

Registriert seit: 29. Dez 2006
Ort: NRW
848 Beiträge
 
Delphi 10.4 Sydney
 
#4

AW: CURL in Delphi ausführen -d

  Alt 5. Feb 2025, 21:52
Hallo jaenicke,
vielen Dank für Deine Antwort. Leider war das noch nicht die Lösung. Ich habe es auf pkREQUESTBODY umgestellt und mit und ohne poDoNotEncode getestet...
Ergebnis ist in beiden Fällen ein HTTP/1.1 400 Bad Request

Ich habe jetzt ein bißchen wild durchprobiert, weil mir der logische Ansatz fehlt...

Diese Kombination scheint zu klappen. Es kommt kein Fehler und der Content ist wie erwartet. Aber warum das jetzt funktioniert weiß ich leider nicht

Delphi-Quellcode:
function TForm1.GetDHLAccessToken_Own3(APIKEY, APISecret, UserName, Password: string; var URL: string): string;
var Client : TRESTClient;
      Request : TRESTRequest;
      JsResponse: TJSONValue;
      response: TCustomRESTResponse;
begin
   Client := TRESTClient.Create(nil);
   Request:= TRESTRequest.Create(client);
   Try
      Try
         Client.BaseURL:= 'https://api-sandbox.dhl.com';
         Request.Resource:= 'parcel/de/account/auth/ropc/v1/token';

         Request.Method := rmPOST;

         Request.Params.AddItem('accept', 'application/json', pkHTTPHEADER, [poDoNotEncode]);
         Request.Params.AddItem('content-type', 'application/x-www-form-urlencoded', pkHTTPHEADER, [poDoNotEncode]);

         Request.Params.AddItem('client_id', APIKEY, pkGETorPOST, [poDoNotEncode]);
         Request.Params.AddItem('client_secret', APISecret, pkGETorPOST, [poDoNotEncode]);
         Request.Params.AddItem('username', UserName, pkGETorPOST, [poDoNotEncode]);
         Request.Params.AddItem('password', Password, pkGETorPOST, [poDoNotEncode]);

         Request.AddParameter('grant_type', 'password', pkGETorPOST, [poDoNotEncode]);


         URL:= Request.GetFullRequestURL;
         Request.Execute;
         if request.Response.StatusCode = 200 then begin
            JsResponse:= TJSONObject.ParseJSONValue(request.Response.Content);
            Result:= JsResponse.GetValue<string>('access_token');
         end
         else begin
            ShowMessage(IntToStr(request.Response.StatusCode) + ' ' + request.Response.StatusText);
            Result:= 'Error: ' + IntToStr(request.Response.StatusCode) + ' ' + request.Response.StatusText;
         end;
      Except
         ON e: Exception do begin
            Result:= E.Message;
            ShowMessage('Keine Daten erhalten');
         end;
      end;
   Finally
      Request.Free;
      Client.Free;
   End;
end;
Mit WireShark habe ich schon versucht, komme ich aber nicht zurecht. Es werden einfach zu viele Pakete gleichzeitig protokolliert und ich finde die richtigen nicht, geschweige denn, dass ich etwas richtiges herauslesen kann. Das ist mir erst einmal gelungen...
Patrick
  Mit Zitat antworten Zitat
Ykcim

Registriert seit: 29. Dez 2006
Ort: NRW
848 Beiträge
 
Delphi 10.4 Sydney
 
#5

AW: CURL in Delphi ausführen -d

  Alt 5. Feb 2025, 22:01
Hallo Uwe,
wie meinst Du das? Ich bin auf dem Gebiet ein Neuling. Kannst das in 2-3 Code-Zeilen erklären?
Vielen Dank
Patrick
Patrick
  Mit Zitat antworten Zitat
Benutzerbild von jaenicke
jaenicke
Online

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

AW: CURL in Delphi ausführen -d

  Alt Gestern, 08:02
Mit WireShark habe ich schon versucht, komme ich aber nicht zurecht. Es werden einfach zu viele Pakete gleichzeitig protokolliert und ich finde die richtigen nicht
Hast du denn gefiltert?
ip.addr == 192.168.0.1

Dann werden nur Pakete angezeigt, die von oder zu dieser IP gehen. Das sollten nicht viele sein.
Sebastian Jänicke
AppCentral
  Mit Zitat antworten Zitat
Kas Ob.

Registriert seit: 3. Sep 2023
382 Beiträge
 
#7

AW: CURL in Delphi ausführen -d

  Alt Gestern, 08:49
@Ykcim, Hi

Here few thoughts :
1) Skip WireShark as it is overkill in your situation, you have CURL commands which easily can be logged in full with -v (--verbose) you can have the headers in full but with --trace, you will have everything even the body (payload/post_content/data/post_data ... these just names for the same thing)
https://everything.curl.dev/usingcur...ose/trace.html
Also in your Delphi code you have access to Request then just right before Request.Execute; grab the headers and the body and log it or show it somewhere, then compare to find your problem, don't have these access to TRESTClient and TRESTRequest, so may be someone else here can help with that, i mean how to extract the header and the body also the URI/URL.

2) CURL command you pasted has "-d" for these parameters this means they are in the body request aka post payload, unlike your other question not long ago, see and remember there is 3 places data can be exchanged between HTTP client and server, in the URI, HTTP header or in the body, make sure to put each in its needed place as requested per documentation, for that use (1) above in case you are in doubt.

3) What Uwe suggested is right and should be followed always, for these common header fields that are known and almost always needed, you should use the provided and named property to set the values, in other words if there is a property TRESTRequest like these "Request.Accept und Client.ContentType" then use them and don't use the "Request.Params.AddItem('accept',...." or "Request.Params.AddItem('content-type',..."
Kas
  Mit Zitat antworten Zitat
Kas Ob.

Registriert seit: 3. Sep 2023
382 Beiträge
 
#8

AW: CURL in Delphi ausführen -d

  Alt Gestern, 09:05
Here an example of using trace with CURL

Zitat:
curl -k -i -X POST -H "accept: application/json" -H 'content-type: application/x-www-form-urlencoded' https://api-sandbox.dhl.com/parcel/d.../ropc/v1/token -d "grant_type=password\&username=user-valid\&password=SandboxPasswort2023!\&client_id=yy yyyyyyyyyyyyy\&client_secret=xxxxxxxxx" --trace-ascii dump.txt
You will have dump.txt file in the same folder contain many things and here a small part you might need to look at
Code:
=> Send header, 203 bytes (0xcb)
0000: POST /parcel/de/account/auth/ropc/v1/token HTTP/1.1
0035: User-Agent: curl/7.39.0
004e: Host: api-sandbox.dhl.com
0069: accept: application/json
0083: Content-Length: 123
0098: Content-Type: application/x-www-form-urlencoded
00c9:
=> Send data, 123 bytes (0x7b)
0000: grant_type=password\&username=user-valid\&password=SandboxPasswo
0040: rt2023!\&client_id=yyyyyyyyyyyyyyy\&client_secret=xxxxxxxxx
== Info: upload completely sent off: 123 out of 123 bytes
Kas
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe

Registriert seit: 20. Jan 2006
Ort: Lübbecke
11.556 Beiträge
 
Delphi 12 Athens
 
#9

AW: CURL in Delphi ausführen -d

  Alt Gestern, 11:45
Diese Kombination scheint zu klappen. Es kommt kein Fehler und der Content ist wie erwartet. Aber warum das jetzt funktioniert weiß ich leider nicht
Diese beiden Zeilen:
Delphi-Quellcode:
         Request.Params.AddItem('accept', 'application/json', pkHTTPHEADER, [poDoNotEncode]);
         Request.Params.AddItem('content-type', 'application/x-www-form-urlencoded', pkHTTPHEADER, [poDoNotEncode]);
kannst du noch durch diese ersetzen:
Delphi-Quellcode:
         Request.Aaccept := 'application/json';
         { Das Setzen des ContentType kann entfallen (s.u.) }
Diese Zeilen aus dem Original:
Delphi-Quellcode:
         Request.AddParameter('grant_type', 'password', pkGETorPOST, []);
         Request.AddParameter('username', UserName, pkGETorPOST, []);
         Request.AddParameter('password', Password, pkGETorPOST, []);
         Request.AddParameter('client_id', 'APIKEY', pkGETorPOST, []);
         Request.AddParameter('client_secret', 'APISecret', pkGETorPOST, []);
solltest du besser so schreiben:

Delphi-Quellcode:
         Request.AddParameter('grant_type', 'password', pkGETorPOST, [poDoNotEncode]);
         Request.AddParameter('username', UserName, pkGETorPOST, [poDoNotEncode]);
         Request.AddParameter('password', Password, pkGETorPOST, [poDoNotEncode]);
         Request.AddParameter('client_id', APIKEY, pkGETorPOST, [poDoNotEncode]);
         Request.AddParameter('client_secret', APISecret, pkGETorPOST, [poDoNotEncode]);
Statt der String-Literale 'APIKEY' und 'APISecret' werden nun die übergebenen Aufruf-Parameter verwendet und das poDoNotEncode sorgt für die korrekte Darstellung der Inhalte.

Da alle Parameter als pkGETorPOST angegeben sind, wird automatisch ein 'application/x-www-form-urlencoded' verwendet und der Body entsprechend zusammengebaut.

Der Body sieht dann so aus: 'grant_type=password&username=user-valid&password=SandboxPasswort2023!&client_id=xxxx xxxxx&client_secret=yyyyyyyyyyyyyyy'
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
Ykcim

Registriert seit: 29. Dez 2006
Ort: NRW
848 Beiträge
 
Delphi 10.4 Sydney
 
#10

AW: CURL in Delphi ausführen -d

  Alt Gestern, 14:49
@uwe Raabe
Vielen Dank, dass habe ich verstanden. Das poDoNotEncode hatte ich bereits hinzugefügt.

Zitat:
Request.Params.AddItem('accept', 'application/json', pkHTTPHEADER, [poDoNotEncode]);
Request.Params.AddItem('content-type', 'application/x-www-form-urlencoded', pkHTTPHEADER, [poDoNotEncode]);
kannst du noch durch diese ersetzen:
markierenDelphi-Quellcode:
Request.Aaccept := 'application/json';
{ Das Setzen des ContentType kann entfallen (s.u.) }
Das werde ich mal ausprobieren. Ich habe viel zu wenig Ahnung, wie die Kommunikation bei REST-Abfragen über das Internet technisch funktioniert. Hast Du da eine gute Quelle, wo ich mir einen Überblick verschaffen kann?

@Kas Ob
Many thanks for your answer and the explanation. I have not CURL installed jet. I tried by CMD. What I do not understand is the fact, that the Query of the CURL by CMD gives an error: 400 Bad Request. I upload a screenshot of the cmd window. When I check the exact same CURL by https://reqbin.com/curl I get the right result. Unfortunately the first 4 hours I tried by cmd only...

I will check how to read the header and body of the request before executing.
Many thanks

Patrick
Miniaturansicht angehängter Grafiken
fehler_curl_token.jpg  
Patrick

Geändert von Ykcim (Gestern um 17:18 Uhr)
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      


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:31 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