![]() |
Daten abholen von einem CakePHP Server
Ich würde gerne folgendes mit Indy realsieren, stehe aber auf dem Schlauch und bräuchte hierzu Denkanstöße
- Ein CakePHP Server soll eine (json) Antwort liefern - Übergeben werden muss dem Server ein Json-String der angibt welche Funktion ausgeführt werdenmuss, und vor allem auch - ein String für die Authorisierung als Kompbination von Username + ':' + Passwort in Base64Encoded (ich weiß wie das Encodieren geht)
Delphi-Quellcode:
dieser Spaß muss dann in ein HTTPHeaderField namens „Authorization“ geschrieben werden.
Function Encode64(const S: string; const ByteEncoding: IIdTextEncoding = nil): string;
begin Result := TIdEncoderMIME.EncodeString(S, ByteEncoding); end; .... UsernamePW_base64 := Encode64(aUsername + ':' + aPassword, IndyTextEncoding_UTF8); Dieses Feld soll den Text "Basic " + den base63Encoded String bekommen Und ich denke genau hier habe ich meinen Hänger denn ich bekomme trotz korrekter Daten immer einen Error 401 / Incorrect Authorisation) vermutlich liegt es daran wie ich die Authorisation mache
Delphi-Quellcode:
Var
data: TStringList; begin data := TStringList.Create; data.Values['authorization'] := 'Basic '+ UsernamePW_base64; // ... Response := IdHttp.Post(aURL, data); .... end; Help Please! LG Martin |
AW: Daten abholen von einem CakePHP Server
Hi,
ich glaube du wirfst HTTP-Header und POST-Daten durcheinander. Eine HTTP-Anfrage besteht immer (egal ob POST, GET, oder anderes) auch aus Headern. Einer davon ist der Authorization-Header in dem von dir beschriebenen Format. Der Unterschied zwischen POST und GET besteht darin, dass POST nach diesen Headern noch weitere Daten überträgt. Die Länge dieser Daten in Zeichen wird übrigens auch als Header ("Content-Length") übermittelt. Hier ein Beispiel wie es sein sollte (so sieht die HTTP-Anfrage dann tatsächlich aus, falls du das noch nicht kennst):
Code:
Mit Delphi habe ich nichts mehr zutun, aber du hast glaube ich folgendes gemacht:
POST /my/path HTTP/1.0
Content-Type: application/x-www-form-urlencoded Authorization: Basic base64string Content-Length: 8 ex=ample
Code:
Du musst diese Daten also in den Header verfrachten. (Google meint, du suchst IdHttp.Request.CustomHeaders.AddValue) Außerdem wirst du für eine POST-Anfrage auch weitere Daten zum übertragen brauchen, aber ich vermute, diese hast du in deinem Codebeispiel weggelassen. :)
POST /my/path HTTP/1.0
Content-Type: application/x-www-form-urlencoded Content-Length: keinelustzuzählen Authorization=Basic base64string |
AW: Daten abholen von einem CakePHP Server
Danke für Deinen Hinweis Valetin!
Ich habe durch etwas "rumprobieren" nun die Lösung einer erfolgreichen Anmeldung bei CakePHP mit INDY Bordmittel herausgefunden. Wenn jemand anders das mal braucht -> voila
Delphi-Quellcode:
LG Martin
Var
iDHTTP: TIdHttp; jsonData, Response: String; aUsername,aPassword : String; begin aUsername := 'FirstName.LastName@email.com'; aPassword := 'FictivePW0123455678'; IdHttp := TIdHttp.Create(nil); iDHTTP.Request.BasicAuthentication := True; iDHTTP.Request.Authentication := TIdBasicAuthentication.Create; iDHTTP.Request.Authentication.Username := aUsername; iDHTTP.Request.Authentication.Password := aPassword; IdHTTP.Request.ContentType := 'application/json'; jsonData := 'http://myhomepage.de/somecommand/changed.json?date=1970-01-01 00:00:00'; Response := IdHttp.Get(jsonData); IdHTTP.Free; end; |
AW: Daten abholen von einem CakePHP Server
Kleine Verbesserungsmöglichkeiten:
* iDHTTP.Request.Authentication := TIdBasicAuthentication.Create; Diese Zeile ist nicht notwendig * try ... finally Da die Methode eventuell (je nach Tagesform des Servers oder der Internetverbindung) mit einer Exception abbricht, sollte das Free über einen finally Block abgesichert werden. * TidHTTP.Create anstatt TidHTTP.Create(nil) Das (nil) kann weggelassen werden. Das spart fünf Tastenanschläge ein und ist funktionell gleichwertig. |
AW: Daten abholen von einem CakePHP Server
Danke nochmal, Michael!
-> iDHTTP.Request.Authentication := TIdBasicAuthentication.Create; ist bei CakePHP bei mir notwendig, ansonsten gibt's eine EAccessViolation (000000000) hier nochmal die finale version als "function" LG Martin
Delphi-Quellcode:
Function Ask4aCloudResponse(aUsername, aPassword, aServerURL, aBody : String ):String;
Var iDHTTP: TIdHttp; begin IdHttp := TIdHttp.Create; try iDHTTP.HandleRedirects := True; iDHTTP.Request.BasicAuthentication := True; iDHTTP.Request.Authentication := TIdBasicAuthentication.Create; iDHTTP.Request.Authentication.Username := aUsername; iDHTTP.Request.Authentication.Password := aPassword; IdHTTP.Request.ContentType := 'application/json'; Result := IdHttp.Get(aServerURL + aBody); finally IdHTTP.Free; end; end; |
AW: Daten abholen von einem CakePHP Server
Delphi-Quellcode:
bitte nach dem
try
Delphi-Quellcode:
!
Create
|
AW: Daten abholen von einem CakePHP Server
OK, "again what learnt" ;)
-> Geändert! |
AW: Daten abholen von einem CakePHP Server
Damit es nicht zu leicht wird, hier die nächste Challenge zum selben Thema
Neben den einfach Dingen die per Get-Befehl nun wunderbar laufen, muss ich für andere API Befehle weitere Daten mitschicken. Ich denke mal ich benötige dazu ein http.post hier ein Auszug aus der API: ================================== Login ausführen durch: ![]() Hierzu muss ein HTTPBody Field mitgeschickt werden (Anmerkung: was auch immer das genau ist...) HTTPBody { UID = "04DAB959-9EF6-442C-8A19-D463C57E61D5"; activeversion = 312; locale = de; password = aPassword; premium = 0; username = "its.me@mail.com"; } Wie macht man denn nun so etwas? Meine erste Idee war daraufhin so etwas.
Delphi-Quellcode:
Var
iDHTTP: TIdHttp; ResponseStr:String; Params: TStringStream; begin IdHttp := TIdHttp.Create; Params := TStringStream.create(''); try Params.WriteString(URLEncode('UID=' + '04DAB959-9EF6-442C-8A19-D463C57E61D5' + '&')); Params.WriteString(URLEncode('activeversion=' + '312' + '&')); Params.WriteString(URLEncode('locale=' + 'de' + '&')); Params.WriteString(URLEncode('password=' + EaCloudPassword.Text + '&')); Params.WriteString(URLEncode('premium=' + '1' + '&')); Params.WriteString(URLEncode('username=' + EaCloudUsername.Text)); iDHTTP.HandleRedirects := True; iDHTTP.Request.BasicAuthentication := True; iDHTTP.Request.Authentication := TIdBasicAuthentication.Create; iDHTTP.Request.Authentication.Username := EaCloudUsername.Text; iDHTTP.Request.Authentication.Password := EaCloudPassword.Text; IdHTTP.Request.ContentType := 'application/json'; try IdHTTP.Response.KeepAlive := False; ResponseStr := IdHTTP.Post('http://aServerName.de/users/login.json', Params); except on E: Exception do showmessage('Error encountered during POST: ' + E.Message); end; finally IdHTTP.Free; end; Der Code wird zwar ohne Fehler ausgeführt, die von CAKE-Server zurüchgelieferte Respons (ellenlang....) zeigt allerdings einen fehler '<pre class="cake-error"><a href="javascript:void(0);" onclick="document.getElementById(''cakeErr54366d3e 5b147-trace'').style.display = (document.getElementById(''cakeErr54366d3e5b147-trace'').style.display == ''none'' ? '''' : ''none'');"><b>Warning</b> (4096)</a>: Argument 1 passed to Hash::get() must be an array, null given, called in /var/www/vhosts/acalc.de/httpdocs/cakephp-2.4.3/lib/Cake/Network/CakeRequest.php on line 853 and defined [<b>CORE/Cake/Utility/Hash.php</b>, line <b>43</b>]<div id="cakeErr54366d3e5b147-trace" class="cake-stack-trace" style="display: none;"><a href="javascript:void(0);" onclick="document.getElementById(''cakeErr54366d3e 5b147-code'').style.display = (document.getElementById(''cakeErr54366d3e5b147-code'').style.display == ''none'' ? '''' : ''none'')">Code</a> <a href="javascript:void(0);" onclick="document.getElementById(''cakeErr54366d3e 5b147-context'').style.display = (document.getElementById(''cakeErr54366d3e5b147-context'').style.display == ''none'' ? '''' : ''none'')">Context</a><pre id="cakeErr54366d3e5b147-code" class="cake-code-dump" style="display: none;"><code><span style="color: #000000"><span style="color: #0000BB"> </span><span style="color: #007700">* @</span><span style="color: #0000BB">link http</span><span style="color: #007700">:</span><span style="color: #FF8000">//book.cakephp.org/2.0/en/core-utility-libraries/hash.html#Hash::get</span></span></code>'#$A'<code><span style="color: #000000"><span style="color: #0000BB"> </span><span style="color: #007700">*/</span></span></code>'#$A'<span class="code-highlight"><code><span style="color: #000000"><span style="color: #0000BB"> </span><span style="color: #007700">public static function </span><span style="color: #0000BB">get</span><span style="color: #007700">(array </span><span style="color: #0000BB">$data</span><span style="color: #007700">, </span><span style="color: #0000BB">$path</span><span style="color: #007700">) {</span></span></code></span></pre><pre class="stack-trace">Hash::get() - CORE/Cake/Utility/Hash.php, line 43'#$A'CakeRequest::data() - CORE/Cake/Network/CakeRequest.php, line 853'#$A'UsersController::login() - APP/Controller/UsersController.php, line 52'#$A'ReflectionMethod::invokeArgs() - [internal], line ??'#$A'Controller::invokeAction() - CORE/Cake/Controller/Controller.php, line 490'#$A'Dispatcher::_invoke() - CORE/Cake/Routing/Dispatcher.php, line 185'#$A'Dispatcher::dispatch() - CORE/Cake/Routing/Dispatcher.php, line 160'#$A'[main] - APP/webroot/index.php, line 108</pre></div></pre><pre class="cake-error"><a href="javascript:void(0);" onclick="document.getElementById(''cakeErr54366d3e 5b9d7-trace'').style.display = (document.getElementById(''cakeErr54366d3e5b9d7-trace'').style.display == ''none'' ? '''' : ''none'');"><b>Warning</b> (4096)</a>: Argument 1 passed to Hash::get() must be an array, null given, called in /var/www/vhosts/acalc.de/httpdocs/cakephp-2.4.3/lib/Cake/Network/CakeRequest.php on line 853 and defined [<b>CORE/Cake/Utility/Hash.php</b>, line <b>43</b>]<div id="cakeErr54366d3e5b9d7-trace" class="cake-stack-trace" style="display: none;"><a href="javascript:void(0);" onclick="document.getElementById(''cakeErr54366d3e 5b9d7-code'').style.display = (document.getElementById(''cakeErr54366d3e5b9d7-code'').style.display == ''none'' ? '''' : ''none'')">Code</a> <a href="javascript:void(0);" onclick="document.getElementById(''cakeErr54366d3e 5b9d7-context'').style.display = (document.getElementById(''cakeErr54366d3e5b9d7-context'').style.display == ''none'' ? '''' : ''none'')">Context</a><pre id="cakeErr54366d3e5b9d7-code" class="cake-code-dump" style="display: none;"><code><span style="color: #000000"><span style="color: #0000BB"> </span><span style="color: #007700">* @</span><span style="color: #0000BB">link http</span><span style="color: #007700">:</span><span style="color: #FF8000">//book.cakephp.org/2.0/en/core-utility-libraries/hash.html#Hash::get</span></span></code>'#$A'<code><span style="color: #0... was ist denn das jetzt schon wieder ?? LG M |
AW: Daten abholen von einem CakePHP Server
Verpacke mal die Stringwerte in ""
Lass Dir mal den Header in php anzeigen. |
AW: Daten abholen von einem CakePHP Server
Zitat:
Wenn ich das richtig sehe, hast du den richtigen Ort für diese im Code bereits gefunden. Vermutlich stimmt noch etwas mit der Encodierung nicht. Wo hast du deine Dokumentation mit dem "HTTPBody {" (insb. wegen der geschweiften Klammer auf) her? Kannst du uns eventuell eine genauere Dokumentation verlinken oder bereitstellen? Ich bisher nicht ganz sagen, in welchem Format die Eingabedaten erwartet werden. Übrigens: Sei gewarnt, dass du beim Benutzernamen und Passwort ein Problem bekommst, wenn Zeichen wie "&" darin vorkommen. Die Daten müssen erst Codiert werden. Eigentlich aber ist es sinnvoller die Kodierung dieser Daten nicht selbst zu machen. Indy bietet sicherlich eine Möglichkeit dir das abzunehmen. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 09:33 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