![]() |
CURL in Delphi ausführen -d
Hallo Zusammen,
ich habe Schwierigkeiten, eine CURL in Delphi zu übersetzen...
Code:
yyy ersetzt den API-Key
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"
xxx ersetzt den API-Secret Ich habe die CURL bei ![]() Ich habe folgende Funktion geschrieben:
Delphi-Quellcode:
Leider bekomme ich immer als Ergebnis:
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;
Code:
Den Abschnitt mit dem -H gekennzeichnet ist, habe ich in den Header gepackt, alles nach dem -d in den Request.
HTTP/1.1 401 Unauthorized
Kann mir jemand sagen, was ich hier falsch mache? Vielen Dank Patrick |
AW: CURL in Delphi ausführen -d
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. |
AW: CURL in Delphi ausführen -d
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.
|
AW: CURL in Delphi ausführen -d
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:oops:
Delphi-Quellcode:
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...
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; |
AW: CURL in Delphi ausführen -d
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 |
AW: CURL in Delphi ausführen -d
Zitat:
ip.addr == 192.168.0.1 Dann werden nur Pakete angezeigt, die von oder zu dieser IP gehen. Das sollten nicht viele sein. |
AW: CURL in Delphi ausführen -d
@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) ![]() 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',..." |
AW: CURL in Delphi ausführen -d
Here an example of using trace with CURL
Zitat:
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 |
AW: CURL in Delphi ausführen -d
Zitat:
Delphi-Quellcode:
kannst du noch durch diese ersetzen:
Request.Params.AddItem('accept', 'application/json', pkHTTPHEADER, [poDoNotEncode]);
Request.Params.AddItem('content-type', 'application/x-www-form-urlencoded', pkHTTPHEADER, [poDoNotEncode]);
Delphi-Quellcode:
Diese Zeilen aus dem Original:
Request.Aaccept := 'application/json';
{ Das Setzen des ContentType kann entfallen (s.u.) }
Delphi-Quellcode:
solltest du besser so schreiben:
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, []);
Delphi-Quellcode:
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.
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]); 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' |
AW: CURL in Delphi ausführen -d
Liste der Anhänge anzeigen (Anzahl: 1)
@uwe Raabe
Vielen Dank, dass habe ich verstanden. Das poDoNotEncode hatte ich bereits hinzugefügt. Zitat:
@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 ![]() I will check how to read the header and body of the request before executing. Many thanks Patrick |
Alle Zeitangaben in WEZ +1. Es ist jetzt 20:23 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