AGB  ·  Datenschutz  ·  Impressum  







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

ContentType in TRESTClient

Ein Thema von Scurra · begonnen am 6. Mär 2019 · letzter Beitrag vom 6. Mär 2019
Antwort Antwort
Seite 1 von 2  1 2      
Scurra

Registriert seit: 19. Jan 2015
81 Beiträge
 
Delphi 10.3 Rio
 
#1

ContentType in TRESTClient

  Alt 6. Mär 2019, 06:33
Delphi-Version: 10 Seattle
Hallo zusammen,

wir sind in unserer Firma gerade dabei, von Seattle auf 10.3.1 Rio umzusteigen, was einige Probleme verursacht hat. Die meisten davon konnte man leicht lösen, beim TRESTClient bin ich aber auf eine sehr merkwürdige Implementierung gestoßen, die - soweit ich das bislang einschätzen kann - den TRESTClient unbrauchbar macht.

Meine Hoffnung ist, dass das Problem darin besteht, dass ich den Rest-Client bisher falsch benutzt habe. Deshalb richte ich die Frage mal hier ins Forum und hoffe, dass mir jemand helfen kann:

Wie setzt man den content-type für einen Request richtig?

Ich benutze den TRESTClient beispielsweise für eine Kommunikation mit Klarna und Klarna erwartet als content-type so etwas wie "application/vnd.klarna.checkout.aggregated-order-v2+json". Das Problem ist, dass der TRESTClient den content-type in der Execute-Methode jedes Mal durch einen der X verschiedenen "Standard"-content-types ersetzt, in meinem Fall beispielsweise durch "application/json". Das führt dazu, dass Klarna sich mit der Meldung "415 Unsupported Media Type" zurückmeldet und ich keine erfolgreiche Anfrage mehr durch bekomme.

Bei der "alten" Delphi-Version wurde, nachdem der content-type in der Execute-Methode überschrieben wurde, die virtuelle Methode "DoPrepareRequestBody" aufgerufen, die wir dazu misbraucht haben, den content-type wieder auf den gewünschten Wert zu setzen. Bei Rio hat sich hier aber die Reihenfolge vertauscht, so dass dies jetzt nicht mehr möglich ist.

Geändert von Scurra ( 6. Mär 2019 um 06:38 Uhr)
  Mit Zitat antworten Zitat
TiGü

Registriert seit: 6. Apr 2011
Ort: Berlin
3.060 Beiträge
 
Delphi 10.4 Sydney
 
#2

AW: ContentType in TRESTClient

  Alt 6. Mär 2019, 09:18
Nur eine Idee:
Wäre es für euch eine Möglichkeit, die Unit REST.Types zu kopieren, mit in euer Projekt aufzunehmen und zu patchen?
So dass ihr euren Typ in TRESTContentType und entsprechend function ContentTypeToString(AContentType: TRESTContentType): string; anpasst?
Man müsste aber prüfen, in wie weit das mit den anderen REST-Units dann noch kompatibel ist. Ggf. muss man sich mehrere davon ins Projekt nehmen.
Dann kann man aber auch gleich die Execute-Methode anpassen.

Weitere Möglichkeit:
Unter Windows würde die Möglichkeit bestehen, sich in die Winapi-Funktion WinHttpAddRequestHeaders reinzuhängen (intercept) und den Wert beim Aufruf dort auszutauschen.
Diese wird in procedure TWinHTTPRequest.AddHeader(const AName, AValue: string); aus System.Net.HttpClient.Win aufgerufen.
Natürlich insofern, dass dies in Rio verwendet wird. Ich kann im Moment nur in Tokyo nachschauen.

Geändert von TiGü ( 6. Mär 2019 um 09:28 Uhr)
  Mit Zitat antworten Zitat
TiGü

Registriert seit: 6. Apr 2011
Ort: Berlin
3.060 Beiträge
 
Delphi 10.4 Sydney
 
#3

AW: ContentType in TRESTClient

  Alt 6. Mär 2019, 09:20
Hier die Idee mit den intercept/hooken:
https://www.delphipraxis.net/198305-...-tls-win7.html
  Mit Zitat antworten Zitat
Schokohase
(Gast)

n/a Beiträge
 
#4

AW: ContentType in TRESTClient

  Alt 6. Mär 2019, 09:31
Ich würde so vorgehen
https://www.delphipraxis.net/1416350-post2.html
  Mit Zitat antworten Zitat
Scurra

Registriert seit: 19. Jan 2015
81 Beiträge
 
Delphi 10.3 Rio
 
#5

AW: ContentType in TRESTClient

  Alt 6. Mär 2019, 09:41
Wäre es für euch eine Möglichkeit, die Unit REST.Types zu kopieren, mit in euer Projekt aufzunehmen und zu patchen?
So dass ihr euren Typ in TRESTContentType und entsprechend function ContentTypeToString(AContentType: TRESTContentType): string; anpasst?
Man müsste aber prüfen, in wie weit das mit den anderen REST-Units dann noch kompatibel ist. Ggf. muss man sich mehrere davon ins Projekt nehmen.
Dann kann man aber auch gleich die Execute-Methode anpassen.
Das war auch unsere Idee.
Ich bin mir nur nicht sicher, ob das mit dem content-type ein Bug ist oder ein Feature Letzteres würde bedeuten, dass man beim zukünftigen Wechsel auf neuere Delphi-Versionen immer wieder die Implementierung anpassen muss.


Zitat:
Weitere Möglichkeit:
Unter Windows würde die Möglichkeit bestehen, sich in die Winapi-Funktion WinHttpAddRequestHeaders reinzuhängen (intercept) und den Wert beim Aufruf dort auszutauschen.
Diese wird in procedure TWinHTTPRequest.AddHeader(const AName, AValue: string); aus System.Net.HttpClient.Win aufgerufen.
Natürlich insofern, dass dies in Rio verwendet wird. Ich kann im Moment nur in Tokyo nachschauen.
Dieses Intercepten würde aber auf Anwendungsebene ablaufen, oder? Also wenn ich den REST-Client an zwei verschiedenen Stellen verwende, weiß ich beim Intercepten nicht, von welcher Stelle aus die Funktion aufgerufen wurde. In diesem Fall wäre es nämlich schwer bis unmöglich, herauszufinden, auf welchen content-type man den Header setzen muss.

Aber danke jedenfalls schon mal für die Idee und den Link!
  Mit Zitat antworten Zitat
TiGü

Registriert seit: 6. Apr 2011
Ort: Berlin
3.060 Beiträge
 
Delphi 10.4 Sydney
 
#6

AW: ContentType in TRESTClient

  Alt 6. Mär 2019, 10:59
Dieses Intercepten würde aber auf Anwendungsebene ablaufen, oder? Also wenn ich den REST-Client an zwei verschiedenen Stellen verwende, weiß ich beim Intercepten nicht, von welcher Stelle aus die Funktion aufgerufen wurde. In diesem Fall wäre es nämlich schwer bis unmöglich, herauszufinden, auf welchen content-type man den Header setzen muss.

Aber danke jedenfalls schon mal für die Idee und den Link!
Ja, das gilt dann nur für eure Anwendung.

Klar, es ist etwas tricky, falls die Contenttypes variieren, aber man kann sich da ggf. mit etwas Globalen behelfen(oh mein Gott, hat er das wirklich geschrieben?).

Also an einer Stelle (eigene Unit) den aktuellen, jetzt gleich zu verwendeten Contenttype setzen (also bevor ihr Request.Execute aufruft) und im Intercepter auslesen und ersetzen.

Klar ist das alles nur Gebastel, aber euren Code jetzt komplett auf eine saubere Lösung wie von Schokohase vorgeschlagen umzustricken, könnt ihr machen wenn ganz viel Zeit ist.

Mit der Intercept-Lösung könnt ihr ja per {IFDEF Compilerversion=XYZ} arbeiten.
So dass ihr in der ggf. nächsten Version den Fix nicht verwenden müsst, wenn da alles wieder schön sein sollte.
  Mit Zitat antworten Zitat
Bbommel
Online

Registriert seit: 27. Jun 2007
Ort: Köln
652 Beiträge
 
Delphi 12 Athens
 
#7

AW: ContentType in TRESTClient

  Alt 6. Mär 2019, 13:06
Eine einfache Lösung habe ich leider auch nicht, aber ich hatte vor einiger Zeit das selbe Problem und hatte dafür mal ein Ticket aufgemacht mit einem einfachen Lösungsvorschlag.

https://quality.embarcadero.com/browse/RSP-19793

Vielleicht könnt ihr ja mal dafür voten oder kommentieren, in der Hoffnung, dass es dann auch mal umgesetzt wird.
  Mit Zitat antworten Zitat
Benutzerbild von Union
Union

Registriert seit: 18. Mär 2004
Ort: Luxembourg
3.487 Beiträge
 
Delphi 7 Enterprise
 
#8

AW: ContentType in TRESTClient

  Alt 6. Mär 2019, 13:14
So geht es also definitiv nicht?

Delphi-Quellcode:
 RestClient.ContentType := 'application/veryspecialjson+V42';
 RestRequest.Params.AddItem('Content-Type',
    RestClient.ContentType,
    TRESTRequestParameterKind.pkHTTPHEADER,
    [TRESTRequestParameterOption.poDoNotEncode],
    TRESTContentType.ctNone);
Ibi fas ubi proxima merces
sudo /Developer/Library/uninstall-devtools --mode=all
  Mit Zitat antworten Zitat
Bbommel
Online

Registriert seit: 27. Jun 2007
Ort: Köln
652 Beiträge
 
Delphi 12 Athens
 
#9

AW: ContentType in TRESTClient

  Alt 6. Mär 2019, 13:22
Wenn ich mich an meine Odysee von vor einem Jahr richtig erinnere, hast du dann den Content-Type entweder doppelt drin stehen - also einmal den selbst gesetzten und den automatischen - oder es wird das eigene Feld doch wieder überschrieben. Ich meine, es war ersteres, also dass er doppelt vorkommt.
  Mit Zitat antworten Zitat
Scurra

Registriert seit: 19. Jan 2015
81 Beiträge
 
Delphi 10.3 Rio
 
#10

AW: ContentType in TRESTClient

  Alt 6. Mär 2019, 15:25
So geht es also definitiv nicht?

Delphi-Quellcode:
 RestClient.ContentType := 'application/veryspecialjson+V42';
 RestRequest.Params.AddItem('Content-Type',
    RestClient.ContentType,
    TRESTRequestParameterKind.pkHTTPHEADER,
    [TRESTRequestParameterOption.poDoNotEncode],
    TRESTContentType.ctNone);
Zitat:
Wenn ich mich an meine Odysee von vor einem Jahr richtig erinnere, hast du dann den Content-Type entweder doppelt drin stehen - also einmal den selbst gesetzten und den automatischen - oder es wird das eigene Feld doch wieder überschrieben. Ich meine, es war ersteres, also dass er doppelt vorkommt.
Diesen Vorschlag habe ich neulich schon einmal im Internet gefunden und es kam weiterhin "Unsupported media type" zurück. Ich wollte jetzt gerade bBommels Aussage mit Charles überprüfen, also ob der Header doppelt auftaucht oder ob er wieder überschrieben wird, aber nun hat es plötzlich funktioniert.

Irgendwas habe ich gestern wohl falsch gemacht.

Ich halte es zwar für ein falsches Design, dass die Property "ContentType" von außen gesetzt werden kann, obwohl das überhaupt keine Auswirkung auf den Request hat, aber nun ja, für mich zählt erst einmal, dass ich eine (einfache) Lösung habe.

Danke jedenfalls für eure Hilfe
  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 08:33 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