IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Web & réseau Delphi Discussion :

TIdHttp et IOHandler XE7 VCL


Sujet :

Web & réseau Delphi

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre Expert

    Homme Profil pro
    Retraité
    Inscrit en
    Novembre 2007
    Messages
    3 530
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 64
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Novembre 2007
    Messages : 3 530
    Par défaut TIdHttp et IOHandler XE7 VCL
    Bonjour

    Pas doué en prog web moi !
    Je veux juste récupérer un fichier Jours fériés

    Je voulais utiliser basiquement un TIDHttp et je trouve plein d'exemple sur le net dans le genre :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
     
    procedure DownloadHTTP(const AUrl : string; out DestStream: TStream);
    begin
      with TIdHTTP.Create(Application) do
      try
        try
          Get(AUrl, DestStream);
        except
          on e: Exception do
            MessageDlg(Format('Erreur : %s',[e.Message]), mtInformation, [mbOK], 0);
        end;
      finally
        Free;
      end;
    end;
    Problème : à chaque appel je reçois le message :

    ---------------------------
    Notification des exceptions du débogueur
    ---------------------------
    Le projet Project2.exe a déclenché la classe d'exception EIdIOHandlerPropInvalid avec le message 'Valeur IOHandler non valide'.
    ---------------------------
    Arrêter Continuer Aide
    ---------------------------
    Nulle part dans les exemples que je trouve il n'est question de IOHandler (même si j'ai bien le composant correspondant sur la palette delphi.

    Pourquoi un truc aussi simple me pose-t-il des problèmes ??

  2. #2
    Expert éminent
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    14 093
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 14 093
    Par défaut
    Si c'est pour le HTTPS et dans ce cas, les exemples sont très nombreux
    Cela implique de fournir libeay32.dll et ssleay32.dll

    C'est d'ailleurs la première chose que Google répond pour "delphi TIdHttp et IOHandler" -> Sécurisation des connexions réseau Indy

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
     
     
     
    procedure TFrmMain.Button1Click(Sender: TObject);
     
      function IsHTTPS(const AUrl : string): Boolean;
      begin
        with TIdURI.Create(AUrl) do
        try
          Result := SameText(Protocol, 'HTTPS');
        finally
          Free;
        end;
      end;
     
      // Surtout pas out pour AReponseContent !!!
      procedure DownloadHTTP(const AUrl: string; AReponseContent: TStream; const ExpectedContentType: string = '');
      begin
        with TIdHTTP.Create(nil) do // aucune raison de mettre Application ici !
        try
          if IsHTTPS(AUrl) then
          begin
            IOHandler := TIdSSLIOHandlerSocketOpenSSL.Create(nil); // ici nil pourrait être l'objet TIdHTTP mais avec la syntaxe with c'est pas compatible
            TIdSSLIOHandlerSocketOpenSSL(IOHandler).SSLOptions.Method := sslvSSLv23; // la valeur sslvSSLv23 laisse au server le choix du protocole, on ne s'en occupe pas
          end;
          try
            Get(AUrl, AReponseContent);
            if ResponseCode <> 200 then
              raise Exception.CreateFmt('[%d] %s', [ResponseCode, ResponseText]);
     
            if ExpectedContentType <> '' then
              if not SameText(Response.ContentType, ExpectedContentType) then
                raise Exception.CreateFmt('Invalid Response Content Type : %s', [Response.ContentType]);
     
          except
            on e: Exception do
              MessageDlg(Format('Erreur : %s',[e.Message]), mtInformation, [mbOK], 0);
          end;
        finally
          IOHandler.Free;
          Free;
        end;
      end;
     
    var
      JSONStream: TStringStream;
      ResponseJSON: TJSONObject;
      Pair: TJSONPair;
    begin
      JSONStream := TStringStream.Create('', TEncoding.UTF8);
      try
        DownloadHTTP('https://calendrier.api.gouv.fr/jours-feries/metropole.json', JSONStream, 'application/json');
     
        ResponseJSON := TJSONObject.ParseJSONValue(JSONStream.DataString) as TJSONObject; // UTF8 !
        try
          for Pair in ResponseJSON do
             ValueListEditor1.Values[Pair.JsonString.Value] := Pair.JsonValue.Value;
        finally
          ResponseJSON.Free();
        end;
      finally[ATTACH=CONFIG]651713[/ATTACH]
        JSONStream.Free();
      end;


    Si ce n'est pas pour du HTTPS, il faudrait nous donner plus d'information
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  3. #3
    Membre Expert

    Homme Profil pro
    Retraité
    Inscrit en
    Novembre 2007
    Messages
    3 530
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 64
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Novembre 2007
    Messages : 3 530
    Par défaut
    Il y en a beaucoup mais avec TIdSSLIOHandlerSocketOpenSSL , je n'en n'ai pas trouvé.

    Ton aide est toujours précieuse mais nouvelle erreur :

    ---------------------------
    Project2
    ---------------------------
    Erreur lors de la connexion avec SSL.

    error:1409442E:SSL routines:SSL3_READ_BYTES:tlsv1 alert protocol version.
    ---------------------------
    OK
    ---------------------------

    J'ai trouvé l'URL sur https://www.data.gouv.fr/fr/datasets...1df4822526c1c/

    Il y a lien vers la doc de l'API JSON mais je pensais pouvoir télécharger le fichier directement puisqu'on y arrive depuis un navigateur.

  4. #4
    Membre Expert

    Homme Profil pro
    Retraité
    Inscrit en
    Novembre 2007
    Messages
    3 530
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 64
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Novembre 2007
    Messages : 3 530

  5. #5
    Expert éminent
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    14 093
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 14 093
    Par défaut
    Avec le code fourni ci-dessus, cela fonctionne parfaitement avec les DLL que j'ai 1.0.2.11 (1.0.2k)

    Nom : Sans titre.png
Affichages : 354
Taille : 20,3 Ko

    C'est pour cela que j'évite OpenSSL, je préfère laisse Windows le faire, je reviens avec une version sans OpenSSL et sa chiasse de version
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  6. #6
    Membre Expert

    Homme Profil pro
    Retraité
    Inscrit en
    Novembre 2007
    Messages
    3 530
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 64
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Novembre 2007
    Messages : 3 530
    Par défaut
    dans c:\windows\system32 j'ai la version 1.0.2.21 qui est plus récente. Est-ce que ça ne devrait pas fonctionner ?

    J'ai copié les 2 dll dans le répertoire du projet et cette fois ça passe.

    Mais l'encodage est incorrect. Exemple : Lundi de Pentecôte

  7. #7
    Expert éminent
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    14 093
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 14 093
    Par défaut
    Tu as bien repris le code fourni ci-dessus ?
    L'important étant TEncoding.UTF8 dans le constructeur du TStringStream

    On laisse Windows et WinInet gére le HTTPS et ça sans le problème de Handshake bien connu avec OpenSSL
    Pas besoin des deux DLL avec le code ci-dessus mais c'est un poil plus brut comme code, il est robuste, j'utilise une variante depuis des années, il est en PROD depuis 2017 et je ne suis plus dans la boite concernée, donc plus de maintenance de ma part.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
     
    procedure TFrmMain.Button1Click(Sender: TObject);
     
     
      procedure GetInternetFile(const AServerName: string; const AURL: string; AStream: TStream; const ExpectedContentType: string = '');
      type
        TAcceptTypes = packed array[0..1] of LPWSTR;
      const
        BufferSize = 1024;
        ACCEPT_TYPES: TAcceptTypes = (PChar('text/*'), nil); // PCTSTR rgpszAcceptTypes[] = {_T(“text/*”), NULL};
      var
        hSession, hHTTP, hReq : HINTERNET;
        Accept: TAcceptTypes;
        Buffer: array[1..BufferSize] of Byte;
        BufferLen: DWORD;
        sAppName: string;
      begin
        AStream.Size := 0;
        sAppName := ExtractFileName(Application.ExeName);
     
        Accept := ACCEPT_TYPES;
        if ExpectedContentType <> '' then
          Accept[0] := PChar(ExpectedContentType);
     
        // Winapi.WinInet !!!
        hSession := InternetOpen(PChar(sAppName), INTERNET_OPEN_TYPE_PRECONFIG, nil, nil, 0);
        try
          hHTTP := InternetConnect(hSession, PChar(AServerName), INTERNET_DEFAULT_HTTP_PORT, nil, nil, INTERNET_SERVICE_HTTP, 0, 1);
          try
            hReq := HttpOpenRequest(hHTTP, PChar('GET'), PChar(AURL), nil, nil, @accept, 0, 1);
            try
              if HttpSendRequest(hReq, nil, 0, nil, 0) then
              begin
                BufferLen := 0;
                repeat
                  if InternetReadFile(hReq, @Buffer, BufferSize, BufferLen) then
                    AStream.WriteBuffer(Buffer, BufferLen);
     
                until BufferLen = 0;
              end
              else
                raise Exception.Create('HttpOpenRequest failed. ' + SysErrorMessage(GetLastError));
            finally
              InternetCloseHandle(hReq);
            end;
          finally
            InternetCloseHandle(hHTTP);
          end;
        finally
          InternetCloseHandle(hSession);
        end;
      end;
     
    var
      JSONStream: TStringStream;
      ResponseJSON: TJSONObject;
      Pair: TJSONPair;
    begin
      JSONStream := TStringStream.Create('', TEncoding.UTF8);
      try
        GetInternetFile('calendrier.api.gouv.fr', '/jours-feries/metropole.json', JSONStream, 'application/json');
     
        ResponseJSON := TJSONObject.ParseJSONValue(JSONStream.DataString) as TJSONObject; // UTF8 !
        try
          for Pair in ResponseJSON do
             ValueListEditor1.Values[Pair.JsonString.Value] := Pair.JsonValue.Value;
        finally
          ResponseJSON.Free();
        end;
      finally
        JSONStream.Free();
      end;
    end;
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  8. #8
    Membre Expert

    Homme Profil pro
    Retraité
    Inscrit en
    Novembre 2007
    Messages
    3 530
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 64
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Novembre 2007
    Messages : 3 530
    Par défaut
    Ton dernier code avec Wininet fonctionne parfaitement.

    Merci encore ...

  9. #9
    Expert éminent
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    14 093
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 14 093
    Par défaut
    Si il fonctionne, autant prendre celui-là car sans dépendance

    En Delphi 11, je t'aurais conseillé TRESTClient et TRESTRequest,
    Je l'utilise aussi en D10 mais j'ai des soucis de Certificat HTTPS, D10 ne propage pas le OnNeedCertificate des ses couches basses de IPPeerClient, le comble, j'ai du repassé à du TIdHTTP pour ce WebService (interne)


    EDIT : n'utilise pas out pour échanger des objets comme TStream, c'est déjà un échange par référence implicite.

    Utilise un TBytesStream, c'est idéal pour gérer le fonctions du TEncoding ensuite :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    TEncoding.UTF8.GetString(BytesStream.Bytes);
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  10. #10
    Membre Expert

    Homme Profil pro
    Retraité
    Inscrit en
    Novembre 2007
    Messages
    3 530
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 64
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Novembre 2007
    Messages : 3 530
    Par défaut
    c'est vrai que les dépendances sont toujours problématiques. Autant s'en défaire quand on peut

  11. #11
    Membre Expert

    Homme Profil pro
    Retraité
    Inscrit en
    Novembre 2007
    Messages
    3 530
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 64
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Novembre 2007
    Messages : 3 530
    Par défaut
    Citation Envoyé par ShaiLeTroll Voir le message
    Tu as bien repris le code fourni ci-dessus ?
    L'important étant TEncoding.UTF8 dans le constructeur du TStringStream
    En fait, j'avais fait ça mais je me rends compte que le TMemoryStream ne prend l'encodage

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    var
      St: TMemoryStream;
    begin
     
      St := TMemoryStream.Create;
      DownloadHTTP(Format(API, [Zones[6]]), TStream(St));
      St.Seek(0, TSeekOrigin.soBeginning);
      Memo1.Lines.LoadFromStream(St);
      St.Free;
    Je vais modifier et comme ça j'aurai 2 façons de le faire.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [TIdHTTP] Récupérer code HTML
    Par daedric dans le forum Web & réseau
    Réponses: 1
    Dernier message: 26/04/2006, 10h02
  2. indy10 comment arrêter un tidhttp.post
    Par dvarrel dans le forum Web & réseau
    Réponses: 2
    Dernier message: 21/03/2006, 23h00
  3. TidHTTP et gestion d'un password incorrect
    Par Lio590 dans le forum Web & réseau
    Réponses: 2
    Dernier message: 16/10/2005, 22h10
  4. Petite question TIdHTTP
    Par tixu dans le forum Web & réseau
    Réponses: 7
    Dernier message: 29/10/2004, 16h25

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo