Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Netzwerke (https://www.delphipraxis.net/14-netzwerke/)
-   -   Daten abholen von einem CakePHP Server (https://www.delphipraxis.net/182150-daten-abholen-von-einem-cakephp-server.html)

MartinK 4. Okt 2014 18:19

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:
Function Encode64(const S: string; const ByteEncoding: IIdTextEncoding = nil): string;
begin
  Result := TIdEncoderMIME.EncodeString(S, ByteEncoding);
end;
....
UsernamePW_base64 := Encode64(aUsername + ':' + aPassword, IndyTextEncoding_UTF8);
dieser Spaß muss dann in ein HTTPHeaderField namens „Authorization“ geschrieben werden.
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

Valle 5. Okt 2014 01:29

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:
POST /my/path HTTP/1.0
Content-Type: application/x-www-form-urlencoded
Authorization: Basic base64string
Content-Length: 8

ex=ample
Mit Delphi habe ich nichts mehr zutun, aber du hast glaube ich folgendes gemacht:

Code:
POST /my/path HTTP/1.0
Content-Type: application/x-www-form-urlencoded
Content-Length: keinelustzuzählen

Authorization=Basic base64string
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. :)

MartinK 5. Okt 2014 06:38

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:
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;
LG Martin

mjustin 5. Okt 2014 11:00

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.

MartinK 7. Okt 2014 14:28

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;

Sir Rufo 7. Okt 2014 22:51

AW: Daten abholen von einem CakePHP Server
 
Delphi-Quellcode:
try
bitte nach dem
Delphi-Quellcode:
Create
!

MartinK 7. Okt 2014 23:37

AW: Daten abholen von einem CakePHP Server
 
OK, "again what learnt" ;)
-> Geändert!

MartinK 9. Okt 2014 12:56

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:
http://aServerName.de/users/login.json

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">&nbsp;</span><span style="color: #007700">*&nbsp;@</span><span style="color: #0000BB">link&nbsp;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">&nbsp;</span><span style="color: #007700">*/</span></span></code>'#$A'<span class="code-highlight"><code><span style="color: #000000"><span style="color: #0000BB">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #007700">public&nbsp;static&nbsp;function&nbsp;</span><span style="color: #0000BB">get</span><span style="color: #007700">(array&nbsp;</span><span style="color: #0000BB">$data</span><span style="color: #007700">,&nbsp;</span><span style="color: #0000BB">$path</span><span style="color: #007700">)&nbsp;{</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">&nbsp;</span><span style="color: #007700">*&nbsp;@</span><span style="color: #0000BB">link&nbsp;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

mkinzler 9. Okt 2014 13:08

AW: Daten abholen von einem CakePHP Server
 
Verpacke mal die Stringwerte in ""

Lass Dir mal den Header in php anzeigen.

Valle 9. Okt 2014 14:10

AW: Daten abholen von einem CakePHP Server
 
Zitat:

Zitat von MartinK (Beitrag 1275389)
Hierzu muss ein HTTPBody Field mitgeschickt werden (Anmerkung: was auch immer das genau ist...)

Das, was ich in #2 als POST-Daten betitelt habe.

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.

mjustin 9. Okt 2014 14:15

AW: Daten abholen von einem CakePHP Server
 
Zitat:

Zitat von MartinK (Beitrag 1275389)

Login ausführen durch:
http://aServerName.de/users/login.json

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";
}

Das ist kein gültiges JSON. Steht das genau so in der Dokumentation?

Wenn es JSON sein soll, das im Body gesendet wird, dann empfehle ich einen JSON Parser wie SuperObject zu verwenden.

Valle 9. Okt 2014 14:17

AW: Daten abholen von einem CakePHP Server
 
Zitat:

Zitat von mjustin (Beitrag 1275405)
Das ist kein gültiges JSON. Steht das genau so in der Dokumentation?

Was er schickt ist auch kein JSON.

Daher die Frage, was er überhaupt senden soll. Fest steht nur, dass er vermutlich JSON zurückbekommt.

mjustin 9. Okt 2014 14:20

AW: Daten abholen von einem CakePHP Server
 
Zitat:

Zitat von MartinK (Beitrag 1275389)

Delphi-Quellcode:
  Params := TStringStream.create('');
  try
    Params.WriteString(URLEncode('UID='          + '04DAB959-9EF6-442C-8A19-D463C57E61D5' + '&'));

Das Ergebnis in Params passt nicht zum dargestellten Format (& statt ;).

Tipp: für das Debuggen kann man ganz einfach einen Interceptor in Indy zuweisen, der dann die Kommunikation protokolliert. Wenn das zu einfach ist ( :) ) kann man alternativ Fiddler2 als Proxy zum Loggen einsetzen.

MartinK 9. Okt 2014 19:04

AW: Daten abholen von einem CakePHP Server
 
Ich würde mal sagen die Doku der API die ich erhalten habe ist noch "sehr basic". Die muss und werde ich im Anschluss selbst überarbeiten.

Die Idee mit dem JSON Superobjekt war mal wieder der Bringer überhaupt.
Das Teil ist ja echt Weltklasse sobald man es mal halbwegs verstanden hat.

-> Der Übergabe HTTPBody ist JSON
-> und ich bekomme inzw. auch einen passenden JSON String als response zurück, welchen ich nun nur noch auswerten muss

Bin absolut begeistert wie Klasse das funktioniert, muss jetzt aber erstmal etwas essen bevor ich das fertig mache.
Ich poste dann vermutlich wieder meinen Code, damit andere auch etwas davon haben

VIELEN DANK euch allen erneut
LG MARTIN

MartinK 10. Okt 2014 11:09

AW: Daten abholen von einem CakePHP Server
 
OK, here u go mit meinem Code zum Login

1.) wir erstellen uns einen record der die Anmeldedaten&Status beinhaltet um nachher einfacher darauf zugreifen zu können

Delphi-Quellcode:
  TaCloudLogin = record
     id                :String;  //returns the UID (User-ID) of the aCloud
     Username          :String;
     Password          :String;
     LogonSuccesfull   :Boolean;
     PremiumStatus     :Boolean; //does user get aditional access to functions like WebInterface etc. ?
   end;


Var
    aCloudLogin :TaCloudLogin;
2.) Die Funktion die den Login checkt und den record mit dem Anmeldedaten ausfüllt

Delphi-Quellcode:

Function TForm1.Login2ACloud(aUsername,aPassword,aLocale,anActiveVersion :String; aPremiumStatus:Integer; IsSilentMode:Boolean):Boolean;
Var
  iDHTTP: TIdHttp;
  Params: TStringStream;
  JSON: ISuperObject;
begin
  if NOT ((Length(EaCloudUsername.Text) >= 5) AND (Pos('@', EaCloudUsername.Text) > 1 ))
    then begin
           Showmessage(Txt[715,L]); //invalid e-mail adress
           exit;
         end;

  IF (Length(EaCloudPassword.Text) < 4)
    then begin
           Showmessage(Txt[718,L]); //password missing or invalid
           exit;
         end;

  IdHttp := TIdHttp.Create;
  Params := TStringStream.create('');

  //1.) Prepare and send a HTTP-Post to the CloudServer asking for LoggingIn
  try
    JSON := SO();
    JSON['UID']             := SO('"' + CreateGuid + '"');
    JSON['activeversion']   := SO(anActiveVersion);
    JSON['locale']          := SO(aLocale);
    JSON['password']        := SO(aPassword);
    JSON['premium']         := SO(aPremiumStatus);
    JSON['username']        := SO(aUsername);

    JSONParams := JSON.AsJSon();
    Params.WriteString(JSONParams);

    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';
    IdHTTP.Response.KeepAlive := False;

    try
      JSONResponse := IdHTTP.Post(aCloudServer + 'users/login.json', Params);
    except
      on E: Exception do
        IF (IsSilentMode = FALSE)
          then showmessage('Error encountered during POST: ' + E.Message);
    end;
  finally
    IdHTTP.Free;
  end;

  //2.) Now we interprete if the connection was succesful and write data into the record "aCloudLogin"
  JSON := SO(JSONResponse);         // Interprete the JSON response to the JSON Super-Object (SO)

  aCloudLogin.id          := JSON.O['return'].S['id'];
  if (POS('OK', Uppercase(JSON.O['return'].S['response']) ) > 0)
    then aCloudLogin.LogonSuccesfull   := True
    else aCloudLogin.LogonSuccesfull   := FALSE;
  If (aPremiumStatus = 0)
    then aCloudLogin.PremiumStatus     := True
    else aCloudLogin.PremiumStatus     := FALSE;
  aCloudLogin.Username    := aUsername;
  aCloudLogin.Password    := aPassword;

  Result:= aCloudLogin.LogonSuccesfull;
end;
und hier noch ein Funktionsaufruf.....

Delphi-Quellcode:
  Login2ACloud(EaCloudUsername.Text,EaCloudPassword.Text,'de', 'Aqua Calculator (V' + LVersionNr.Caption + ')', 1, True);

lG Martin

MartinK 29. Okt 2014 16:27

AW: Daten abholen von einem CakePHP Server
 
Nachdem jetzt mit direktem www Zugang alles klappt, habe ich noch ein Thema sobald ich via Proxy verbinde

hier mal ein Stück Code das bei mir heraussucht welche Art von Proxy-Auth gemacht wird
Delphi-Quellcode:
procedure TForm1.IdHTTPProxyAuthorization(Sender: TObject; Authentication: TIdAuthentication; var Handled: Boolean);
begin
  Handled := False;
end;

function TForm1.IdSSLIOHandlerSocketOpenSSLVerifyPeer(Certificate: TIdX509; AOk: Boolean; ADepth, AError: Integer): Boolean;
begin
  Result := True;
end;


procedure TForm1.IdHTTPSelectProxyAuthorization(Sender: TObject; var AuthenticationClass: TIdAuthenticationClass; AuthInfo: TIdHeaderList);

begin
  ProxyAuthTxt       := 'Proxy-Authentification: Unkown';

  // First check for NTLM authentication, as you do not need to set username and password because Indy will automatically
  // handle passing your Windows Domain username and password to the proxy server
  if (pos('Proxy-Authenticate: NTLM', IdHTTP.Response.RawHeaders.Text)>0)
    then begin
           IdHTTP.ProxyParams.BasicAuthentication := false;
           AuthenticationClass := TIdSSPINTLMAuthentication;
           ProxyAuthTxt       := 'Proxy-Authentific.: NTML (w/o Username+PW)';
           ProxyAuthType      := 1;
         end
    else begin
           //...now check for Basic Authentication
           if (pos('Proxy-Authenticate: Basic', IdHTTP.Response.RawHeaders.Text)>0)
             then begin
                    IdHTTP.ProxyParams.BasicAuthentication := true;
                    AuthenticationClass := TIdBasicAuthentication;
                    ProxyAuthTxt       := 'Proxy-Authentification: Basic';
                    ProxyAuthType      := 2;
                   end
             else begin
                    // Then Digest
                    if (pos('Proxy-Authenticate: Digest', IdHTTP.Response.RawHeaders.Text)>0)
                      then begin
                             IdHTTP.ProxyParams.BasicAuthentication := true;
                             AuthenticationClass := TIdDigestAuthentication;
                             ProxyAuthTxt       := 'Proxy-Authentification: Digest';
                             ProxyAuthType      := 3;
                           end;
                  end;
           //.------------
           IdHTTP.ProxyParams.ProxyUsername := EProxyUsername.Text;
           IdHTTP.ProxyParams.ProxyPassword := EProxyPassword.Text;
         end;

  LProxyAutent.Caption := ProxyAuthTxt;
end;

HTTP Get funktioniert auch einwandfrei solange ich ein normales get/Post mache,
"OHNE dem Server ein Username/Password für den Cloud-Zugriff mitzuübergeben"
(URL, Port und Pasword/Username wegen das proxys sind natürlcih angegeben passen !)


sobald ich den Cloud Username und Passwort mit angebe, bekomme ich beim "IdHttp.Get" eine Exception "HTTP/1.1 400 bad request"
Gehe ich ich aber nicht über den Proxy, sondern verbinde direkt, dann funktioniert der Code eiwandfrei;

Delphi-Quellcode:
Function TForm1.Ask4aCloudResponse(aUsername, aPassword, aServerURL, aServerCommand: String ):String;
begin
  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 + aServerCommand);
  finally
    ;
  end;
end;
woran kann denn das liegen?

MartinK 5. Nov 2014 14:56

AW: Daten abholen von einem CakePHP Server
 
Einige Tage später und "der Knoten hat sich leider noch nicht gelöst"

Ich denke mein Problem ist das ich 2 Pärchen aus Username & Password habe
a) Username & Password die ich brauche um mich bei einem "Basic" oder "Digest" Proxy zu authentifizieren
(das müssten doch eigentlich sein: IdHTTP.ProxyParams.ProxyUsername / ProxyPassword
wobei die ja zumindest bei NTML ja irgendwie duch Indy eingesetzt werden)

b) Username & Password die dem Cloud-Server übergeben werden müssen um sich für den eigenen Cloud-Acount zu indetifizieren
(das müssten doch eigentlich sein: iDHTTP.Request.Authentication.Username / Password)

hat da jemand noch eine Idee die mich aus der völligen Desillusion befreit ?

LG Martin

MartinK 19. Nov 2014 14:18

AW: Daten abholen von einem CakePHP Server
 
Manchmal braucht man leider Ewigkeiten für eine Kleinigkeit.. hier war das der Fall

Ich habe den Fehler nach mehrfachem Kontakt zu Remy lebau (von Indy) und mittels 2 WireShark-Protokollen herausfinden können.
Und zwar habe ich 1x das Protokoll meiner App gelogged und das mit dem Protokoll des IE verglichen (wo das ganze funktioniert hatte...)

Mein Fehler war dass ich beim Übergabe-String so etwas geschickt hatte
Delphi-Quellcode:
'measurements/changed.json?date=1970-01-01 01:01:00'
der MS-IE hat das Kommando intern umgewandelt in
Delphi-Quellcode:
'measurements/changed.json?date=1970-01-01%2001:01:00'
...und damit lief es

Die Lösung ist also nichts weiter als ein
Delphi-Quellcode:
URLEncode('tanks/changed.json?date=1970-01-01 00:00:00')
und alles ist gut


LG Martin

MartinK 8. Jan 2015 11:47

AW: Daten abholen von einem CakePHP Server
 
Zwecks Vollständigekit halber hier ein weiteres CodeFragment, da ich denke das es evtl. weiteren Personen hilft die mal etwas ähnliches machen wollen

Ziel: Ein FileUpload auf den Server mittels eines sog "Multipart Form DataStreams". So etwas wird zB zum Uploaden von Bildern eingesetzt

lG Martin

Delphi-Quellcode:
Function TForm1.ACloud_UploadPicture(_PictureID, _OriPictureFPathAndName:String) : String;
Var
  POSTData: TIdMultipartFormDataStream;
  JSON: ISuperObject;
begin
  Result := '';
  try
    //generate a so called Multipart Object with
    //- the picture File itself. it is loaded as Stream form the path specified
    //- identifiers needed for the Cake server routines 'picture' , 'image/jpg'
    POSTData := TIdMultiPartFormDataStream.Create;
    POSTData .AddFile('picture', _OriPictureFPathAndName, 'image/jpg');

    IDHTTP.HandleRedirects := True;
    IDHTTP.Request.BasicAuthentication := false;
    IDHTTP.Request.Authentication := TIdBasicAuthentication.Create;
    IDHTTP.Request.Authentication.Username := aCloudLogin.Username;
    IDHTTP.Request.Authentication.Password := aCloudLogin.Password;
    //although we handle the Multipart message, servers answers are again JSON for easier interpretation
    IdHTTP.Request.ContentType := 'application/json';

    aCloudURL := URLEncode(aCloudServer + 'pictures/uplpic.json?PictureID=' + _PictureID+'.jpg');
    JSONResponse := IDHTTP.Post(aCloudURL, POSTData);
  except
    on E : Exception do
      Result := Result + 'Exception uploading an image to aCloud: "' + E.ClassName + '" "' + E.Message +'"';
  end;
  POSTData.Free;
  //---------------------------
  if Result <> '' then exit;
  //---------------------------
  //Now let's check if everythimng worked correctly. ...we interprte the Response returend from the Server
  //This is specific to your servers specifications and just an example on how it could be done
  JSON := SO();
  JSON := SO(JSONResponse); // Interprete the response to the JSON Super-Object (SO)
  If (Uppercase(JSON.S['response'])  <> Uppercase('OK') ) OR
     (Uppercase(JSON.S['entityID'])  <> Uppercase(_PictureID+'.jpg')) OR
     (Uppercase(JSON.S['entityType']) <> Uppercase('picturedata') ) OR
     (Uppercase(JSON.S['type'])      <> Uppercase('u') )
     then Result := Result + 'Error responded updating an aCloud-picture: ' + JSONResponse;
end;


Alle Zeitangaben in WEZ +1. Es ist jetzt 11:02 Uhr.

Powered by vBulletin® Copyright ©2000 - 2022, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2021 by Daniel R. Wolf