Page 1 sur 1

Web Service RPGLE Probleme CCSID

Posté : ven. 26 oct. 2018, 12:39:11
par jysaulieres
Bonjour,

Nous avons 2 partitions IBM i (V7R2 TR8 SF99720 niveau 18032)
Installés : 5770SS1 option 39, JV1 opt 11,14 à 17
variable environnement JAVA_HOME = .../JavaVM/jdk80/32bit

Mon soucis :
J'ai mis en place un web service REST en RPPGLEsur une partition "A" qui me renvoie des caractères accentués.
La réponse s'affiche correctement quand j'appelle le web service via un navigateur (mozilla,...), mais pas via une émulation 5250 à partir de ma partition B

PARTITION A (qui héberge le web service) :
- sysval QCCSID = 297
- Programme RPGLE
- renvoi du JSON

PARTITION B :
- sysval QCCSID = 65535, mais profil avec ccsid 297
- Appel du WebService via un SQLRPGLE ou via STRSQL

SELECT cast(substr(Reponse, 1, 1000) as varchar(1000))
FROM
(VALUES(SYSTOOLS.HTTPGETCLOB(
'http://[MonSysteme]/web/services/MonInfo/123456', ''))) ws(Reponse)

RENVOI : {"CODERETOUR":"Non Trouvé", ....}
====> probleme de conversion de CCSID quelque part, mais ou ?

idem si je met dans mon header :
'<header name="Content-Type" value="application/json;charset=UTF_8"/>'

Si j'appelle un web service sur internet qui renvoie des caractères accentué à partir de ma partition B ceux ci s'affichent correctement.
Je pense qu'il pourrait s'agir de la mise en place du web service et d'une config du serveur APACHE (V2.6) ou du web service
J'ai essayé à plusieurs endroit de mettre CCSID= UTF8, FR, 297, ... mais rien ne change malgré restart du serveur web.

CCSID

Posté : lun. 29 oct. 2018, 13:29:26
par cmasse
Pour y voir plus clair, que donne cette requête avec un site publique ?

values
cast(
systools.httpgetclob(
'http://data.nantes.fr/api/publication/2 ... ormat=json', '')
as varchar(20000)
)

pour nous
{"version":"1","nb_results":569,"data":[{ "geo" : { "name" : "Collège Anne de Bretagne"} ...
le "è" de collège est-il correct ?

Posté : lun. 29 oct. 2018, 14:16:08
par jysaulieres
Bonjour,

Oui, les caractères accentués sont bien affichés quand je lance cette requête sur le site public.
=>
...."Collège Anne de Bretagne"} , "_l" : [ 47.2065481346042.....

Voila mon source WS en RPG (très simplifié pour ne tenir compte que des accents) :
Ctl-opt alwnull(*usrctl) pgminfo(*pcml:*module);
Ctl-opt dftactgrp(*no);
// par défaut : global server setting = 00819
Dcl-pi *n;
Reference Char(20);
Code1 Char(20) ccsid(297);
Code2 Char(20) ccsid(1208);
end-pi;

Code1 = 'éèçàùâêîôûäËïöü';
Code2 = 'éèçàùâêîôûäËïöü';
*inlr=*on;

Puis l'affichage qd j'appelle ce WS a parrtir d'une autre partition
sELECT cast(substr(Reponse, 1, 500) as varchar(500))
FROM
(VALUES(SYSTOOLS.HTTPGETCLOB(
'http://MonServeur:10032/web/services/WS1208/a',
''))) ws(Reponse)

=>
Fonction CAST
{"CODE1":"éèçà ùâêîôûÀà ïöü","CODE2":"éèçà ùâêîôû"}

Par contre, si j'appelle ce WS via mozilla (ou IE) la réponse est correcte :
{"CODE1":"éèçàùâêîôûäËïöü","CODE2":"éèçàùâêîôû"}

(tronqué sur char(20) mais c'est normal, c'est juste pour du test)

CCSID

Posté : lun. 29 oct. 2018, 18:25:15
par cmasse
j'ai copié votre code et je rencontre le même problème.

Web service appelé depuis un navigateur : OK,
depuis le gestionnaire de scripts SQL (ou 5250)-> prb.

j'ai enlevé les CCSID sur les définitions de zone, ca ne sert à rien, de toutes façons je serveur de web services transporte de l'UNICODE.

J'ai essayé ce code

Code : Tout sélectionner

**free
dcl-s retour SQLTYPE&#40;CLOB &#58; 200&#41;;

exec sql
  values &#40;systools.httpgetClob&#40;'http&#58;//as400&#58;10052/web/services/TESTCCSID/abc', ''&#41;&#41;
    into &#58;retour;

dsply &#40;%subst&#40;retour_data &#58; 1 &#58; 50&#41;&#41;;
*INLR = *ON;  
                     
toujours le même problème dans retour_data

puis j'ai essayé

Code : Tout sélectionner

create table retourT &#40;retour clob CCSID 1208&#41;
et
insert into retourT values&#40;                              
   systools.httpgetClob&#40;                                 
     'http&#58;//as400&#58;10052/web/services/TESTCCSID/abc', ''&#41;
 &#41;                                                       
enfin

Code : Tout sélectionner

**free
dcl-s retour SQLTYPE&#40;DBCLOB_file&#41;;

retour_name = '/temp/retour.json';
retour_nl = %len&#40;%trim&#40;retour_name&#41;&#41;;
retour_fo = SQFOVR;

exec sql
  values &#40;systools.httpgetClob&#40;'http&#58;//as400&#58;10052/web/services/TESTCCSID/abc', ''&#41;&#41;
    into &#58;retour;

*INLR = *ON;   
                  
toujours pas...le fichier est déclaré CCSID=1208, mais les caractères ne sont pas bon. je pense que c'est au niveau de httpgetclob que ca se passe.

Posté : mar. 30 oct. 2018, 10:35:39
par jysaulieres
Bonjour,

Quand on exporte les données via le DBCLOB_FILE, on dirait qu'il y a un double encodage ... je m'explique :
1) le caractère "é" est normalement codé en UTF8 sur 2 octets qui ont pour valeur héxa 0xC3 0xA9 et représentés par les codes EBCDIC 297 par "é".
2) les caractères "é" sont respectivement codés en UTF8 : 0xC3 0x83 et 0xC2 0xA9

Et nous retrouvons ces 4 codes dans le fichier IFS à la place du "é"
(visible avec un éditeur de texte en hexa sous Windows)

Pour contourner le problème, j'ai trouvé une solution à la "barbare" qui ne fonctionne que quand la réponse du WS n'excède pas 32000 OCTETS (sachant que les caractères accentués et autres sont codés sur 2 ou 3 octets en UTF8)

1) Créer une table FIC297 avec 1 zone char ccsid 297

2) Ecrire la réponse du WS dans la table
insert into FIC297 (Zone297)
(SELECT cast(substr(Reponse, 1, 32000) as Varchar(32000))
FROM (VALUES(SYSTOOLS.HTTPGETCLOB(
'http://as400:10032/web/services/AWS1208/a','')))
ws(Reponse))

3) Export de la table vers IFS:
CPYTOIMPF FROMFILE(FIC297)
TOSTMF('/TEMP/FicIfs.txt')
MBROPT(*REPLACE)
STMFCCSID(*PCASCII)
RCDDLM(*CRLF)
STRDLM(*NONE)
=> le fichier est créé avec CCSID 1252 par défaut

4) CHGATR OBJ('/TEMP/FicIfs.txt') ATR(*CCSID) VALUE(1208)
pour forcer la lecture suivante en UTF8

5) import dans une 2eme table FIC297B
CPYFRMIMPF FROMSTMF('/TEMP/FicIfs.txt')
TOFILE(FIC297B)
MBROPT(*REPLACE)
FROMCCSID(*FILE)
TOCCSID(*FILE)
RCDDLM(*CRLF)
STRDLM(*NONE)
FLDDLM(*TAB)
Et là le résultat est lisible.

Mais :
- je ne sais pas si ça fonctionne pour TOUS les caractères provenant de l'UTF8
- ça ne fonctionne QUE si la longueur de la réponse du web service n'excède pas 32000 OCTETS (puisque le codage en UTF8 peut se faire sur 2 ou 3 octets), soit
Il est possible de dépasser les 32000 octets mais il faudrait mettre en place une usine à gaz qui balaye la réponse du WS par tranche de 32000 octets ...

Ce que je n'arrive pas à comprendre c'est pourquoi ça ne fonctionne pas en local, alors que les caractères accentués sont affichés correctement quand on appelle un WS public (comme celui de Nantes que vous avez donné comme exemple )

Point service

Posté : mar. 30 oct. 2018, 18:11:25
par cmasse
je pense que ça vaut le coup d'ouvrir un incident au point service.

je m'y colle ! (mais ça risque d'être long)

Posté : mer. 31 oct. 2018, 08:30:02
par jysaulieres
Merci encore pour votre analyse et pour l'ouverture du ticket au point service. Je vais suivre avec intérêt la suite donnée par IBM.

HTTPGETCLOB

Posté : mer. 31 oct. 2018, 11:07:09
par cmasse
Pour l'instant la réponse est que ça doit venir du serveur WEB, en effet celui-ci peut fournir un "charset" dans les entêtes HTTP
(Content-Type: text/html; charset=utf-8 ).

si ce n'est pas transmis par le serveur, HTTPGETCLOB suppose alors ISO-8859-1, soit du LATIN-1 (et non de l'UTF-8), bref du coté HTTPGETCLOB : "work as design", l'incident passe du coté support Apache.

Posté : mer. 31 oct. 2018, 12:53:28
par jysaulieres
Quand je fais un :
SELECT cast(substr(RESPO00002, 1, 1500) as varchar(1500))
FROM table(SYSTOOLS.HTTPGETCLOBverbose(
'http://MonAS:10032/web/services/WS1208/abc', '')) as Reponse

j'obtiens :
<?xml version="1.0" encoding="UTF-8" ?><httpHeader responseCode="200"><responseMessage>OK
....
<header name="Content-Language" value="fr-FR"/>
...
<header name="Content-Type" value="application/json"/>
<header name="X-Powered-By" value="IBM i"/></httpHeader>

Je pensais que le : "encoding=UTF-"8 (avec le code retour=200) était la réponse du serveur Web indiquant le CCSID utilisé
J'attends la suite.

HEADER

Posté : jeu. 08 nov. 2018, 08:16:03
par cmasse
ce n'est pas le XML qui est en cause, mais le retour du serveur Apache.Pour l'instant ca marche en ajoutant dans httpd.conf

Code : Tout sélectionner

Header onsuccess Edit Content-type application/json "application/json; charset=utf-8"
(Astuce de Nathanaël BONNET)

qui force le serveur à indiquer dans l'entête HTTP que le format JSON est en UTF8 (à adapter pour le XML).

je vais voir si le point service indique plus simple ?

Header

Posté : jeu. 08 nov. 2018, 16:00:04
par cmasse
Réponse du point service
So Http server needs to have : Header set Content-Type "application/json;charset=UTF-8"

(sujet inconnu)

Posté : lun. 12 nov. 2018, 10:16:11
par jysaulieres
Bonjour,

En modifiant le fichier httpd.conf ça fonctionne correctement, tous les caractères accentués (et autres cédilles ...) fonctionnent en retour.

merci encore pour votre temps et votre analyse.

Re: HTTPGETCLOB

Posté : lun. 11 nov. 2019, 12:54:27
par Luciad58
cmasse a écrit :Pour l'instant la réponse est que ça doit venir du serveur WEB, en effet celui-ci peut fournir un "charset" dans les entêtes HTTP
(Content-Type: text/html; charset=utf-8 ).

si ce n'est pas transmis par le serveur, HTTPGETCLOB suppose alors ISO-8859-1, soit du LATIN-1 (et non de l'UTF-8) mutuelles professionnelle, bref du coté HTTPGETCLOB : "work as design", l'incident passe du coté support Apache.
Donc, si ce cas se produit, il ne faut pas essayer de rebooter le système.

Re: HEADER

Posté : mar. 14 janv. 2020, 09:24:07
par MattB
cmasse a écrit :ce n'est pas le XML qui est en cause, mais le retour du serveur Apache.Pour l'instant ca marche en ajoutant dans httpd.conf

Code : Tout sélectionner

Header onsuccess Edit Content-type application/json "application/json; charset=utf-8"
(Astuce de Nathanaël BONNET)

qui force le serveur à indiquer dans l'entête HTTP que le format JSON est en UTF8 (à adapter pour le XML).

je vais voir si le point service indique plus simple ?
Bonjour, vous parlez du httpd.conf du serveur éxécutant le webservice c'est bien ça ?
J'ai un problème identique en utilisant les webservices d'un ERP. La modification serait donc à faire sur le serveur de l'ERP ?

Re: Web Service RPGLE Probleme CCSID

Posté : mer. 29 janv. 2020, 15:26:25
par cmasse
Oui, c'est cela.