Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Netzwerke (https://www.delphipraxis.net/14-netzwerke/)
-   -   Zweites AddHeader im RestRequest geht nicht (https://www.delphipraxis.net/204104-zweites-addheader-im-restrequest-geht-nicht.html)

Incocnito 23. Apr 2020 15:13

Zweites AddHeader im RestRequest geht nicht
 
Hi Zusammen,

ich habe eine Rest-Schnittstelle, an welche ich zwei Werte im Header mitschicken muss.
Ich erstelle einen TRestClient, passend dazu einen TRestResponse und einen TRestRequest.
Ich habe nun zwei Parameter, welche ich per Header übergeben muss.
Ich habe nun versucht mit
Delphi-Quellcode:
RESTRequest.Params.AddHeader('Authorization', 'Bearer ' + sAuth);
RESTRequest.Params.AddHeader('X-API-KEY', MAIN_API_KEY);
oder
Delphi-Quellcode:
RESTRequest.AddParameter('Authorization', 'Bearer ' + sAuth, TRESTRequestParameterKind.pkHTTPHEADER);
RESTRequest.AddParameter('X-API-KEY', MAIN_API_KEY, TRESTRequestParameterKind.pkHTTPHEADER);
die Werte hinzuzufügen, aber der Kollege meint, es kommt nur eines von beidem an.
Die gleichen Werte in Postman reinkopiert funktionieren (also kein Tippfehler).
Lustigerweise kommt "X-API_KEY" an, sonst hätte ich das auf das Minus geschoben.
Aber wie gesagt: Ich habe das 1:1 in Postman reinkopiert und dort geht es.

Hat jemand eine Idee, wie ich prüfen kann, was passiert?
Hat jemand mal ein vergleichbares Problem gehabt?
Muss ich irgendwas beachten? Geht das was ich mache unter Delphi einfach nicht? Warum?
Hat irgendjemand eine Idee, wonach ich überhaubt schauen kann?
Ehrlich gesagt weiß ich fast gar nicht wonach ich euch genau fragen soll! -.-

Ich bin für jeden Tipp dankbar.

Mit freundlichem Gruß
Incocnito

hhcm 23. Apr 2020 16:42

AW: Zweites AddHeader im RestRequest geht nicht
 
Zitat:

Zitat von Incocnito (Beitrag 1462782)
aber der Kollege meint, es kommt nur eines von beidem an.

Sicher das der Kollege recht hat :?

himitsu 23. Apr 2020 16:51

AW: Zweites AddHeader im RestRequest geht nicht
 
es kommt drauf an, was AddHeader macht
* z.B. falls schon vorhanden das überschreiben

und wie der Empfänger mit dem Header umgeht
* das was kommt blind an seine Header-Objektliste anhängen
* oder dort das was schon war überschreiben
* oder wie es ausgewertet wird, also da wo es ausgelesen wird:
* * mehreres einzeln auswerten
* * oder beim ersten Fund aufhören und nur das Erste verwenden
* * oder beim Auswerden due Liste durchgehen und sich den wert merken, also beim Dupplikat dann mit dem Wert überschreiben und nur das Letzte verwenden


Bei so mancher Komponente gibt es neben dem Header (mit festen/vordefinierten Einträgen) noch einen OptionalHeader, wo man sich nach belieben auslassen kann.

hoika 24. Apr 2020 04:24

AW: Zweites AddHeader im RestRequest geht nicht
 
Hallo,
übergib mal nicht sAuth, sondern z.B. Hallo als festen Wert.

Etwa vor einer Woche war doch schon mal,was mit Bearer gewesen.
Da stimmte das Encoding nicht

Du kannst die AddHeader-Aufrufe auch testweise mal umdrehen.

jaenicke 24. Apr 2020 05:41

AW: Zweites AddHeader im RestRequest geht nicht
 
Setze einfach mal einen Haltepunkt auf TCustomRESTRequest.Execute in der Unit REST.Client. Dort wird der Request zusammengebaut.

Incocnito 24. Apr 2020 08:52

AW: Zweites AddHeader im RestRequest geht nicht
 
Hi Zusammen,

Zitat:

Zitat von hhcm (Beitrag 1462789)
Sicher das der Kollege recht hat :?

Naja, ich glaube ihm, dass sein Programm sagt "da ist nur Wert A aber nicht Wert B".
Mir scheint das aber ein Problem im Zusammenspiel zwischen Delphi und seiner
Programmiersprache zu sein. Hier im Haus hatte ich schonmal ein Problem mit .Net,
wo die Änderung eines Aufrufes von
Delphi-Quellcode:
RESTRequest.Params.AddHeader(...)
nach
Delphi-Quellcode:
RESTRequest.AddParameter(...)
das Problem behoben hat.
Fragt mich! Ich habe keine Ahnung was das war.
Klingt für mich nach "Oh der Kugelschreiber liegt links von der Tastatur, ja dann kann das Programm auch nicht funktionieren!".

Zitat:

Zitat von himitsu (Beitrag 1462791)
es kommt drauf an, was AddHeader macht
...

Zitat:

Zitat von jaenicke (Beitrag 1462805)
Setze einfach mal einen Haltepunkt auf TCustomRESTRequest.Execute in der Unit REST.Client. Dort wird der Request zusammengebaut.

Ich habe nun mal da reingeschaut ... war übersichtlicher als ich befürchtet hatte ...
Dort konnte ich feststellen, dass Params 2 Elemente hat und bis kurz vor dem Senden war auch alles gut.

---

Lösung:
So! Ich habe mir dann gedacht: Gut, baust du mal einen Rest-Server und schaust was da ankommt.
Das war aber auf die Schnelle nicht so einfach zu erreichen.
Ich habe zumindest nichts (jetzt heute morgen mit 15 Minuten suchen) finden können,
dafür bin ich in der Delphi-Hilfe bei meiner Suche aber auf den Rest-Debugger von Embarcadero gestoßen.
Also dachte ich mir: "Ich habe eh das Gefühl, dass ich selbst irgendwas falsch mache und
dass das normalerweise geht, sonst würden sicher schon einige Leute mit Fackel und Forke
vor dem Hauptsitz von Embarcadero rumhocken!" ... Ich habe meine Daten eingegeben und oh Wunder
genau wie in Postman geht es. Nun, im Rest-Debugger war beim Hinzufügen von Parametern ein Haken
"Nicht Verschlüsseln", den ich aktiviert hatte. Als ich den Haken entfernt hatte, bekam ich den
gleichen "401 - Unauthorized"-Fehler im Rest-Debugger, wie ich auch in meinem Programm bekommen habe.
Nach etwas Nachforscherei und habe ich dann herausgefunden, dass "AddParameter" mehrere Parameterlisten hat.
Eine Variation hat "Optionen" und hier kann man "poDoNotEncode" angeben.
Setzt komme ich weiter! Das war das Problem.

Also nochmalzusammengefasst: Bei mir lief es dann, wenn ich beide Parameter mit
Delphi-Quellcode:
RESTRequest.AddParameter('xxx', 'yyy', pkHTTPHEADER, [poDoNotEncode]);
übergebe.

Das ganze hat mich dann nochmal Neugierig gemacht und ich habe mal Wireshark angeworfen,
aber egal ob mit oder ohne "poDoNotEncode", bei beidem bekomme ich bei einer https-Verbindung
nur Bytesalat, den ich selbst zumindest nicht mehr entschlüsseln kann.
Scheint also ohne den Header extra zu kodieren auch sicher zu sein.
Frage an dieser Stelle vielleicht nochmal:
Warum können Parameter seperat codiert werden? Was passiert dann?

Und mal so allgemein gefragt: Warum kommt 1 Parameter an, der 2 dann aber nicht?
Habe nur ich solch ein seltsames Verhalten?

Alles so Dinge, wo wir uns nun in Ruhe drüber unterhalten können,
da ich ja nun erstmal weiter komme.

Vielen Dank für die Tipps und Ideen soweit schonmal und ich hoffe,
dass andere in Zukunft durch diesen Post schneller auf die richtige Lösung kommen.
(Obwohl das zugegegebenermaßen doch noch unglaublich fix gelöst war!)

Liebe Grüße
Incocnito

Uwe Raabe 24. Apr 2020 09:15

AW: Zweites AddHeader im RestRequest geht nicht
 
poDoNotEncode bedeutet in diesem Fall kein URI-Encoding. Das hat mit Verschlüsselung nichts zu tun, sondern damit, dass bestimmte Zeichen nicht in der URL auftauchen dürfen.

Das wird übrigens auch wirksam bei einem ContentType von APPLICATION_X_WWW_FORM_URLENCODED.

TiGü 24. Apr 2020 09:57

AW: Zweites AddHeader im RestRequest geht nicht
 
Wieder so ein Fall, wo ein Blick auf die Logs von Telrik Fiddler den Unterschied zu Postman aufgezeigt und man schneller das Problem eingekreist hätte.
Diese Delphi-REST-Threads häufen sich in letzter Zeit.

Irgendwie ist die Embarcadero-Implementierung unglücklich.
Vielleicht wäre es besser gewesen keine negierende Logik zu verwenden, sondern das nicht-encodieren als Standard zu nehmen und statt eines TRESTRequestParameterOption.poDoNotEncode lieber ein TRESTRequestParameterOption.poDoEncode zu verwenden.

Incocnito 24. Apr 2020 13:53

AW: Zweites AddHeader im RestRequest geht nicht
 
Zitat:

Zitat von Uwe Raabe (Beitrag 1462809)
poDoNotEncode bedeutet in diesem Fall kein URI-Encoding. Das hat mit Verschlüsselung nichts zu tun, sondern damit, dass bestimmte Zeichen nicht in der URL auftauchen dürfen.

Das wird übrigens auch wirksam bei einem ContentType von APPLICATION_X_WWW_FORM_URLENCODED.

Oh wait! Also ich hatte HTTP nun so verstanden:
1) Ich schicke einen HTTP-Befehl an eine Adresse.
Diese Adresse ist die URL.
2) Dann habe ich eine Art Umverpackung in der in Simple-ASCII mit nur den nötigsten Zeichen
beschrieben wird, was dann kommt. Der Header. Hier könnte dann auch stehen, dass der Body
in UTF-16 codiert ist. Und wann das ganze geschickt wurde. Keine Ahnung, irgendwie sowas.
3) Und am Ende habe ich dann den Body der mit irgendeiner Codierung (was halt im Header steht)
irgendeine lustige Datenmenge enthällt bei dem nur noch gegeben ist, dass die Daten als Bytes
empfangen werden können. Der Body halt. Der muss dann vom Empfänger irgendwie interpretiert werden,
was aber durch die URL (wo bin ich) und den Header (ein paar Basisinformationen) eindeutig machbar ist.

URI-Encoding war für mich das Codieren der Zeichen in der URL (und nur da), damit beispielsweise ein Leerzeichen auch ankommt, falls das Leerzeichen ein Teil der URL-Parameter ist.
Demnach müsste ich aber nur die URL-Parameter codieren (und das müsste eigendlich immer) und nicht die Header-Parameter (da macht das eigendlich nie Sinn, wenn man so denkt wie ich ... nur ASCII).

Gibt es da irgendwo Infos zu wie das genau ist? So auf die Schnelle wird
das wohl kaum einer erklären können und wollen.

---
Zitat:

Zitat von TiGü (Beitrag 1462810)
Wieder so ein Fall, wo ein Blick auf die Logs von Telrik Fiddler den Unterschied zu Postman aufgezeigt und man schneller das Problem eingekreist hätte.
Diese Delphi-REST-Threads häufen sich in letzter Zeit.

Irgendwie ist die Embarcadero-Implementierung unglücklich.
Vielleicht wäre es besser gewesen keine negierende Logik zu verwenden, sondern das nicht-encodieren als Standard zu nehmen und statt eines TRESTRequestParameterOption.poDoNotEncode lieber ein TRESTRequestParameterOption.poDoEncode zu verwenden.

Was für Logs von wem? Wie hätte man da logs aktivieren/einsehen können?
Und wie sollte man das dann mit Postman vergleichen können?
Oder fängt der wie Wireshark den Netzwerkverkehr ab und kann das bei https sogar entschlüsseln?

Ansonsten bin ich mir gerade auch nicht sicher, was der richtige Weg sein sollte.
Meiner (bisherigen!?) Meinung nach sollten die Parameter welche an die URL angehängt werden eh
ohne Außnahme codiert werden (falls das jetzt das "URI-Encode" ist und ich nicht gänzlich was durcheinander haue) und beim Rest halt nie.

Alles in Allem bin ich mehr verwirrt als vorher! :oops:

Danke schonmal für die Gedanken und die Hilfen bis hierhin!

Liebe Grüße
Incocnito

Uwe Raabe 24. Apr 2020 14:18

AW: Zweites AddHeader im RestRequest geht nicht
 
Bei den Header Feldern muss man unterscheiden zwischen Standard- und Non-Standard. Standard-Header dürfen nur ASCII Zeichen enthalten oder müssen codiert werden (Deswegen ist das Default-Encoding von Embarcadero auch richtig gewählt!). Bei Non-Standard-Headern ist das nicht zwingend erforderlich - da ist das dann von der Implementation abhängig. Im Idealfall ist irgendwo angegeben, ob codiert werden muss oder nicht. Im Zweifel hilft nur ausprobieren.

Aviator 24. Apr 2020 14:40

AW: Zweites AddHeader im RestRequest geht nicht
 
Zitat:

Zitat von Incocnito (Beitrag 1462823)
Was für Logs von wem? Wie hätte man da logs aktivieren/einsehen können?
Und wie sollte man das dann mit Postman vergleichen können?
Oder fängt der wie Wireshark den Netzwerkverkehr ab und kann das bei https sogar entschlüsseln?

Schau dir mal Fiddler an. Ich habe damit auch noch nicht so viel gearbeitet und bin nicht so firm drin, aber der hat schon ein paar coole Features.

Die Funktion die du benötigt hättest wäre, dass er den HTTPS Stream lesbar macht. Damit das funktioniert, hängt sich Fiddler auf Port 443 ins System rein und gaukelt ein Zertifikat vor, dem dein System vertrauen muss (wird alles automatisch eingerichtet). Dadurch, dass Fiddler dann als HTTPS Endpunkt fungiert, sind die Daten dort ja wieder entschlüssel und dadurch lesbar. Im Nachgang werden die wieder verschlüsselt und wieder als HTTPS Stream an den eigentlichen Server gesendet. Das Gleiche passiert mit der Antwort auf dem Rückweg.

Das mal so als einfache Erklärung und ohne Gewähr auf Vollständigkeit und Richtigkeit.


Alle Zeitangaben in WEZ +1. Es ist jetzt 02:08 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