Forum iSeries, hébergé par xdocs400.com

As400, iSeries, i5, System i, une machine qui évolue pour être de plus en plus puissante.

Vous n'êtes pas identifié(e).

Annonce

ATTENTION : Le système anti-spam est à nouveau opérationnel. Nous avons réactivé les inscriptions.

#1 2018-05-09 07:48:13

Florian67
Membre
Lieu : Alsace
Inscription : 2013-04-04
Messages : 180

Service Web et Unicode

Bonjour à tous,

Avez vous une méthode pour consommer un service Web mais avec des caractères unicode ? Quand je parle d'Unicode c'est de l'UTF16 (1200) pour pouvoir gérer les caractères russes, chinois etc...

Je ne peux pas utiliser wsdl2rpg car je n'ai pas de wsdl.
HTTPAPI me renvoi une erreur dès lors que je mets des caractères Unicode (que ce soit dans une chaine alpha ou Unicode).

J'ai déjà consommé pas mal de services SOAP / REST etc... mais je dois avouer que la je sèche un peu.

Merci d'avance pour vos réponses.
Florian

Hors ligne

#2 2018-05-09 10:22:05

natbon
Membre
Inscription : 2010-10-12
Messages : 92
Site Web

Re : Service Web et Unicode

Bonjour Florian,

Via le client ILE de webservice, la fonction axiscTransportSend() converti systématiquement les données en UTF-8 avant envoi.

Il faut appeler axiscTransportSetProperty() avec AXISC_PROPERTY_CONVERT_PAYLOAD à false pour envoyer les données non converties.

Je n'ai jamais testé ...

La doc : ftp://public.dhe.ibm.com/systems/suppor … nt_new.pdf


Nathanaël

Hors ligne

#3 2018-05-09 10:37:35

Florian67
Membre
Lieu : Alsace
Inscription : 2013-04-04
Messages : 180

Re : Service Web et Unicode

Merci Nathanaël pour ton aide.

Effectivement ça pourrait fonctionner. Je vais faire des tests de mon côté et je reviendrai donner mes résultats.

J'ai également trouvé cette doc qui pourrait être utile : https://www.ibm.com/developerworks/ibmi … index.html

Hors ligne

#4 2018-06-13 10:20:17

Bilbao400
Membre
Lieu : Bordeaux
Inscription : 2011-01-10
Messages : 370

Re : Service Web et Unicode

Bonjour,
Je ne sais pas si cela peux aider, mais voici un exemple de programme qui appelle 2 webservices REST. Il utilise les api de transport AXIS. En particulier l'API axiscTransportSetProperty() qui permet entre autre de définir si l'on souhaite une conversion de l'UTF8 vers un autre encodage.

[RPGLE full free]
**FREE
CTL-OPT OPTION(*SHOWCPY) DEBUG(*YES);
/TITLE Consommation du WebService REST Keycloak clear-user-cache
//**************************************************************************************************
// Auteur : Ivan Farge 27 Mars 2018                                                                *
//**************************************************************************************************
// Description :                                                                                   *
// Ce programme permet d'appeler une API REST Keycloak pour vider le cache.                        *
//**************************************************************************************************
// Paramètres :                                                                                    *
//**************************************************************************************************
// Liste des propiétés du webservice :                                                             *
// SELECT TBCODE , TBDATA FROM MPTBCRG2                                                            *
// WHERE TBDOMAINE = 'WEBSERVICES' AND TBTABLE='PER310';                                           *
//                                                                                                 *
//**************************************************************************************************
// Compilation :                                                                                   *
//                                                                                                 *
// CRTSQLRPGI OBJ(FACOBJT/PER310) SRCFILE(FACSRCT/QSQLSRC) OBJTYPE(*MODULE) RPGPPOPT(*LVL1)        *
//                                                                                                 *
// Création du programme :                                                                         *
// CRTPGM PGM(FACOBJT/PER310)   MODULE(FACOBJT/PER310)                                             *
//   BNDSRVPGM((QSYSDIR/QAXIS10CC *IMMED) (FASRV))                                                 *
//   ACTGRP(*NEW) AUT(*USE)                                                                        *
//                                                                                                 *
//  Programmes de service liés avec le programme client :                                          *
//  QSYSDIR/QAXIS10CC : Appel des API Axis                                                         *
//                                                                                                 *
// Mise à jour du programme :                                                                      *
// UPDPGM PGM(FACOBJT/PER310) MODULE(FACOBJT/PER310)                                               *
//**************************************************************************************************
// Modifications :                                                                                 *
//**************************************************************************************************
//
// ... Déclaration des prototypes d'appel aux API Axis
//     axiscStubSetUsername    : Définition de l'utilisateur
//     axiscStubSetPassword    : Définition du mot de passe
//     axiscAxisStartTrace     : Activation de la trace
//
/COPY /QIBM/ProdData/OS/WebServices/V1/client/include/Axis.rpgleinc
//
//... Déclaration des variables pour la gestion des messages
//
/COPY QRPGSRC,SNDMSG_D
//
// ... Déclaration du prototype d'appel à la fonction de récupération
//     des propriétés de la table MPTBCRG2 (RTVTABFA)
//
/COPY QRPGSRC,PR_TAB011
/define json2Tab
/COPY QRPGSRC,PR_FASRV
//
// ... Program Status Datastructure
//
DCL-DS SDS EXTNAME('SDS') PSDS QUALIFIED END-DS;
//
// ... Zones isolées communes à tous WebServices
//
DCL-S wTraceFile           CHAR(2000);
DCL-S wHandle              POINTER;
DCL-S wRequest             CHAR(32768);
DCL-S wResponse            LIKE(wRequest);
DCL-S wPropBuf             CHAR(100);
DCL-S wPropBuf2            LIKE(wPropBuf);
DCL-S wBytesRead           INT(10) INZ(0);
DCL-S wReturnCode          INT(10);
DCL-S wURI                 LIKE(wTraceFile);
DCL-S wURI_clearUserCache  LIKE(wTraceFile);
DCL-S wURI_token           LIKE(wTraceFile);
DCL-S wStatusCode          POINTER;
DCL-S wHTTPHeader          POINTER;
DCL-S wAxisCode            INT(10);
DCL-S wLogSwitch           LIKE(wTraceFile);
//
DCL-S wGetTokenData_client_id   LIKE(wTraceFile);
DCL-S wGetTokenData_username    LIKE(wTraceFile);
DCL-S wGetTokenData_password    LIKE(wTraceFile);
DCL-S wGetTokenData_grant_type  LIKE(wTraceFile);
DCL-S wClearUserCacheData_realm LIKE(wTraceFile);
DCL-S wIO_TimeOut               LIKE(wTraceFile);
DCL-S wCertificateStore         LIKE(wTraceFile);
DCL-S wCertificateLabel         LIKE(wTraceFile);
DCL-S wCertificatePassword      CHAR(30);
DCL-S wToken                    LIKE(wRequest);
DCL-S wNullString               CHAR(1) INZ(X'00');
DCL-S wNone                     CHAR(10);
DCL-S wTolerate                 CHAR(10);
DCL-S wEnabled                  CHAR(5);
DCL-S wI                        INT(10);
DCL-S wHTTPStatusCode           CHAR(3);
DCL-S wTimeout                  INT(10);

DCL-DS tResponse LIKEDS(tTable) DIM(100);
//?
// ... Déclaration des variables des messages?
//?
DCL-DS wMsgEDI0014       QUALIFIED;
 WebServiceName          CHAR(256);
 ErrorCode               PACKED(10);
 ErrorText               CHAR(1000);
 HTTPStatusCode          CHAR(3);
END-DS;
DCL-DS wMsgEDI0015       QUALIFIED;
 HTTPStatusCode          CHAR(3);
 HTTPHeader              CHAR(200);
END-DS;
//?
//*********************************************************************************************
// Description des paramètres du web service appelé                                           *
//*********************************************************************************************
//?
//?
//*********************************************************************************************
// Description des paramètres *ENTRY PLIST                                                    *
//*********************************************************************************************
//?
DCL-PI PER310;
END-PI;
//?
//*********************************************************************************************
// DEBUT DU PROGRAMME (Voir *INZSR)                                                           *
//*********************************************************************************************
//?
EXEC SQL SET OPTION COMMIT = *NONE;
//
// ... Récurération du token
//
EXSR GetToken;
//
// ... Vidage du cache utilisateur Keycloak
//
IF wToken <> *BLANKS;
  EXSR ClearUserCache;
ENDIF;
//?
//*******************************************************************************************
// FIN DU PROGRAMME                                                                         *
//*******************************************************************************************
//?
*INLR = *ON;
RETURN;
//?
//*******************************************************************************************
// GetToken : Récupération du Token                                                         *
//*******************************************************************************************
//?
BEGSR GetToken;
  //
  // ... Initialisation et ouverture de la connexion
  //
  wURI = wURI_token;
  wHandle = axiscTransportCreate(wURI_token
                                :AXISC_PROTOCOL_HTTP11);
  //
  // ... La connection est ouverte si wHandle <> *NULL
  //
  IF wHandle = *NULL;
    EXSR GetLastErrorCode;
  ELSE;
    //
    // ... Configuration du SSL
    //
    EXSR SetSSLProperties;
    //
    // ... Préparation de l'entête HTTP
    //
    wPropBuf = 'Content-Type' + x'00';
    wPropBuf2 = 'application/x-www-form-urlencoded' + x'00';

    axiscTransportSetProperty(wHandle
                             :AXISC_PROPERTY_HTTP_HEADER
                             :%ADDR(wPropBuf)
                             :%ADDR(wPropBuf2));
    //
    // ... Préparation de la méthode d'appel du service REST
    //
    wPropBuf = 'POST' + x'00';
    axiscTransportSetProperty(wHandle
                             :AXISC_PROPERTY_HTTP_METHOD
                             :%ADDR(wPropBuf));
    //
    // ... Préparation de la requête
    //
    RTVTABFA('WEBSERVICES':SDS.STPNAM:'getTokenData_client_id':wGetTokenData_client_id);
    RTVTABFA('WEBSERVICES':SDS.STPNAM:'getTokenData_username':wGetTokenData_username);
    RTVTABFA('WEBSERVICES':SDS.STPNAM:'getTokenData_password':wGetTokenData_password);
    RTVTABFA('WEBSERVICES':SDS.STPNAM:'getTokenData_grant_type':wGetTokenData_grant_type);
    wRequest = *BLANKS;
    wRequest = 'client_id=' + %TRIM(wGetTokenData_client_id) + '&'
             + 'username=' + %TRIM(wGetTokenData_username) + '&'
             + 'password=' + %TRIM(wGetTokenData_password) + '&'
             + 'grant_type=' + %TRIM(wGetTokenData_grant_type);
    //
    // ... Appel de l'API REST
    //
    wReturnCode = axiscTransportSend(wHandle
                                    :%ADDR(wRequest)
                                    :%LEN(%TRIM(wRequest))
                                    :0);
    IF wReturnCode = -1; // Erreur
      EXSR GetLastErrorCode;
    ELSE;
      //
      // ... Envoi de la requête et réception des données
      //
      EXSR FlushAndReceiveData;
    ENDIF;
    //
    // ... Recherche du poste contenant la valeur du token dans le tableau
    //     retourné par le service getToken
    //
    wI = %LOOKUP('access_token':tResponse(*).Key);
    IF wI <> 0;
      wToken = %TRIM(tResponse(wI).value) + x'00';
    ELSE;
      wToken = *BLANKS;
    ENDIF;
    //
    //?... Fermeture de la connexion
    //?
    axiscTransportDestroy(wHandle);
  ENDIF;
ENDSR;
//?
//*******************************************************************************************
// ClearUserCache : Mise à blanc du cache utilisateur Keycloak                              *
//*******************************************************************************************
//?
BEGSR ClearUserCache;
  //
  // ... Initialisation et ouverture de la connexion
  //
  wURI = wURI_clearUserCache;
  wHandle = axiscTransportCreate(wURI_clearUserCache
                                :AXISC_PROTOCOL_HTTP11);
  //
  // ... La connection est ouverte si wHandle <> *NULL
  //
  IF wHandle = *NULL;
    EXSR GetLastErrorCode;
  ELSE;
    //
    // ... Configuration du SSL
    //
    EXSR SetSSLProperties;
    //
    // ... Préparation de l'entête HTTP avec le token
    //
    wPropBuf = 'Authorization' + x'00';
    wToken = 'bearer ' + %TRIM(wToken);

    axiscTransportSetProperty(wHandle
                             :AXISC_PROPERTY_HTTP_HEADER
                             :%ADDR(wPropBuf)
                             :%ADDR(wToken));
    //
    // ... Préparation de l'entête HTTP avec le type de contenu transmis
    //
    wPropBuf = 'Content-Type' + x'00';
    wPropBuf2 = 'application/json' + x'00';

    axiscTransportSetProperty(wHandle
                             :AXISC_PROPERTY_HTTP_HEADER
                             :%ADDR(wPropBuf)
                             :%ADDR(wPropBuf2));
    //
    // ... Préparation de la méthode d'appel du service REST
    //
    wPropBuf = 'POST' + x'00';
    axiscTransportSetProperty(wHandle
                             :AXISC_PROPERTY_HTTP_METHOD
                             :%ADDR(wPropBuf));
    //
    // ... Préparation de l'entête HTTP avec le TimeOut
    //
    RTVTABFA('WEBSERVICES':SDS.STPNAM:'IO_TIMEOUT':wIO_TimeOut);
    wTimeout = %INT(wIO_TimeOut);
    axiscTransportSetProperty(wHandle
                             :AXISC_PROPERTY_IO_TIMEOUT
                             :%ADDR(wTimeOut));
    //
    // ... Préparation de la requête
    //
    RTVTABFA('WEBSERVICES':SDS.STPNAM:'clearUserCacheData_realm':wClearUserCacheData_realm);
    wRequest = *BLANKS;
    wRequest = '{"realm":"' + %TRIM(wClearUserCacheData_realm) + '"}';
    //
    // ... Mise en cache de la requête avant envoi
    //
    wReturnCode = axiscTransportSend(wHandle
                                    :%ADDR(wRequest)
                                    :%LEN(%TRIM(wRequest))
                                    :0);
    IF wReturnCode = -1; // Erreur
      EXSR GetLastErrorCode;
    ELSE;
      //
      // ... Envoi de la requête et réception des données
      //
      EXSR FlushAndReceiveData;
    ENDIF;
    //
    //?... Fermeture de la connexion
    //?
    axiscTransportDestroy(wHandle);
  ENDIF;
ENDSR;
//?
//*******************************************************************************************
// FlushAndReceiveData : Envoi de la requête et réception des données                       *
//*******************************************************************************************
//?
BEGSR FlushAndReceiveData;
  CLEAR wResponse;
  //
  // ?... Envoi de la requête
  //
  wReturnCode = axiscTransportFlush(wHandle);
  IF wReturnCode = -1;
    EXSR GetLastErrorCode;
  ELSE;
    //
    // ... Réception de la réponse
    //
    wReturnCode = axiscTransportReceive(wHandle
                                       :%ADDR(wResponse)
                                       :%SIZE(wResponse)
                                       :0);
    IF wReturnCode = 0; // Pas de données en retour
    ELSE;
      DOW wReturnCode > 0 AND wBytesRead < %SIZE(wResponse);
        wBytesRead = wBytesRead + wReturnCode;
        wReturnCode = axiscTransportReceive(wHandle
                                           :%ADDR(wResponse) + wBytesRead
                                           :%SIZE(wResponse) - wBytesRead
                                           :0);
      ENDDO;
    ENDIF;
    //
    // ?... Lecture du code retour HTTP
    //
    axiscTransportGetProperty(wHandle
                             :AXISC_PROPERTY_HTTP_STATUS_CODE
                             :%ADDR(wStatusCode));
    wHTTPStatusCode = %STR(wStatusCode);
    IF %SUBST(wHTTPStatusCode:1:1) = '4' OR %SUBST(wHTTPStatusCode:1:1) = '5';
      wMsgId = 'EDI0015';
      wMsgEDI0015.HTTPStatusCode = wHTTPStatusCode;
      axiscTransportGetProperty(wHandle
                               :AXISC_PROPERTY_HTTP_HEADER
                               :%ADDR(wHTTPHeader));
      IF wHTTPHeader <> *NULL;
         wMsgEDI0015.HTTPHeader = %STR(wHTTPHeader);
      ELSE;
         wMsgEDI0015.HTTPHeader = '*NULL';
      ENDIF;
      wMsgDt = wMsgEDI0015;
      wMsgTp = '*ESCAPE';
      wMsgSt = 2;
      EXSR SNDMSG;
    ELSE;
      //
      // ... Chargement de la réponse au format JSON dans
      //     un tableau de Clés/Valeurs : tResponse
      //
      CLEAR tResponse;
      wJsonString = wResponse;
      json2Tab(wJsonString:tResponse);
    ENDIF;
  ENDIF;
ENDSR;
//?
//*******************************************************************************************
// GetLastErrorCode : Récupération du code erreur                                           *
//*******************************************************************************************
//?
BEGSR GetLastErrorCode;
  //
  // ?... Récupération du code erreur
  //
  wAxisCode = axiscTransportGetLastErrorCode(wHandle);
  wMsgId = 'EDI0014';
  wMsgEDI0014.WebServiceName = wUri;
  wMsgEDI0014.ErrorCode = wAxisCode;
  wMsgEDI0014.ErrorText = %STR(axiscTransportGetLastError(wHandle));
  IF wAxisCode = EXC_TRANSPORT_HTTP_EXCEPTION;
    axiscTransportGetProperty(wHandle
                             :AXISC_PROPERTY_HTTP_STATUS_CODE
                             :%ADDR(wStatusCode));
    wMsgEDI0014.HTTPStatusCode = %STR(wStatusCode);
  ELSE;
    wMsgEDI0014.HTTPStatusCode = 'Non applicable';
  ENDIF;
  wMsgDt = wMsgEDI0014;
  wMsgTp = '*ESCAPE';
  wMsgSt = 2;
  EXSR SNDMSG;
ENDSR;
//?
//*******************************************************************************************
// SetSSLProperties : Configuration SSL                                                     *
//*******************************************************************************************
//?
BEGSR SetSSLProperties;
  //
  // ... Configuration des paramètres SSL
  //
  wNone = 'NONE' + X'00';
  wTolerate = 'true' + X'00';
  wReturnCode = axiscTransportSetProperty(wHandle
                     :AXISC_PROPERTY_HTTP_SSL
                     :%ADDR(wCertificateStore)   // Certificate Store
                     :%ADDR(wNullString)         // Password certificate Store
                     :%ADDR(wNullString)         // Certificate label
                     :%ADDR(wNone)               // Disabled SSL Version 2 ciphers
                     :%ADDR(wNone)               // Disabled SSL Version 3/TLS Version 1 ciphers
                     :%ADDR(wNone)               // Disabled TLS Version 1 ciphers
                     :%ADDR(wNone)               // Disabled TLS Version 1.1 ciphe
                     :%ADDR(wNullString)         // Enable   TLS Version 1.2 ciphe
                     :%ADDR(wTolerate));         // Tolerate soft validation errors

  IF wReturnCode = -1;
    EXSR GetLastErrorCode;
  ENDIF;
ENDSR;
//?
//*******************************************************************************************
// *INZSR : Initialisation du programme                                                     *
//*******************************************************************************************
//?
BEGSR *INZSR;
  //
  // ... Le paramétrage du WebService est stocké dans la table PER310
  //     du fichier MPTBCRG2
  //
  //     Description des paramètres :
  //     LOGSWITCH : *ON  Activation de la trace Axis
  //                 *OFF Aucune log n'est générée
  //     LOGDIR    : Emplacement du fichier log.
  //                 Le fichier de log sera nommé avec le nom du programme suivi
  //                 par un timestamp avec une extension ".log"
  //
  RTVTABFA('WEBSERVICES':SDS.STPNAM:'LOGSWITCH':wLogSwitch);
  IF wLogSwitch = '*ON';
    RTVTABFA('WEBSERVICES':SDS.STPNAM:'LOGDIR':wTraceFile);
    wTraceFile = %TRIM(wTraceFile) + '/' + %TRIM(SDS.STPNAM) + '_'
               + %CHAR(%TIMESTAMP()) + '.log';
    wMsgID = 'GEN0062';
    wMsgDT = wTraceFile;
    EXSR SNDMSG;
    wTraceFile = %TRIM(wTraceFile) + x'00';
    axiscAxisStartTrace(%ADDR(wTraceFile):*NULL); // Activation trace
  ENDIF;
  //?
  //?... Alimentation de l'URI de l'API REST
  //?
  RTVTABFA('WEBSERVICES':SDS.STPNAM:'URI_clear-user-cache':wURI_clearUserCache);
  RTVTABFA('WEBSERVICES':SDS.STPNAM:'URI_token':wURI_token);
  RTVTABFA('WEBSERVICES':SDS.STPNAM:'CertificateStore':wCertificateStore);
  wCertificateStore = %TRIM(wCertificateStore) + X'00';

ENDSR;
/COPY QRPGSRC,SNDMSG_C 

Hors ligne

#5 2018-07-13 10:24:43

Florian67
Membre
Lieu : Alsace
Inscription : 2013-04-04
Messages : 180

Re : Service Web et Unicode

Merci pour vos réponses. Ca faisait longtemps Bilbao smile

Du coup ça fonctionne bien!!!!
Par contre on doit se mettre dans le bon host page etc... par exemple pour envoyer des données polonaise il faut le host page polonais (1153) que le profil soit en polonais etc..
Je trouve ça un peu dommage car on traite de l'unicode mais au final il faut quand même être dans le bon environnement.

Hors ligne

#6 2018-07-13 15:22:04

B.Hauser
Membre
Inscription : 2014-11-15
Messages : 50

Re : Service Web et Unicode

Il ya aussi un Open Source Tool de Rainer Ross avec lequel le travail avec des WebServices est encore plus facile.
WEBSRVUTL

Birgitta

Hors ligne

Pied de page des forums