<div dir="ltr"><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">Salut,</div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif"><br></div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">Bon, j'avance... Mais lentement. En réalité, je soupçonne désormais plutôt un bogue dans Dancer2. En effet, en virant le code React Native par un bête script javascript full-native, je reproduis le phénomène.</div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif"><br></div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">Voici le javascript :</div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif"><br></div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">% cat index.html</div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif"><!DOCTYPE html><br><html><br> <head><br> <script><br><br> const submitConnectAsync2 = async () => {<br>        return fetch('<a href="http://localhost:5000/connect">http://localhost:5000/connect</a>', {<br>         mode: 'no-cors',<br>         method: 'POST',<br>        headers: {<br> 'Accept' : 'application/json',<br> 'Content-Type' : 'application/json',<br>        },<br>         body: JSON.stringify({'login':"PK", 'password':"PK"})<br>        })<br>        //.then(response => response.json())<br>         .then(response => response.text())<br>         .then(text => {<br>         console.log("Received text:", text);<br>         })<br>         .then(json => {<br>         console.log("Received:", json);<br>         })<br>         .catch(error => {<br>         console.log("Error:", error);<br>         });<br> };<br> <br> window.onload = () => {<br>        document.querySelector("button").onclick = submitConnectAsync2;<br> };<br> <br> </script><br> </head></div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif"><br></div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">et le code pour Dancer2 (j'ai amélioré en ajoutant les status de retour corrects) :</div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif"><br></div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">% cat <a href="http://server.pm" rel="noreferrer" target="_blank">server.pm</a><br>
package server;<br>
use Dancer2;<br>
<br>
set session => "Simple";<br>
set serializer => 'JSON';<br>
<br>
hook 'before' => sub {<br>
response_header 'Access-Control-Allow-Origin' => '*';<br>
};<br>
</div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif"><br></div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">hook before => sub {<br> if (!session('user') && request->path !~ m{^/connect}) {<br> forward '/connect', { requested_path => request->path };<br> }<br>};<br><br>post '/connect' => sub {<br> my $post = from_json( request->body );<br> debug "\t\t", request->body;<br> my $login = params('body')->{login};<br> my $password = params('body')->{password};<br> status 200;<br> debug "\t\t login : $login password : $password";<br> if ( ($login eq 'PK') && ($password eq 'PK') ) {<br> # nothing possible to add after sending a request<br> debug "\t\t Valid login and password : state connected\n";<br> session user => $login;<br> debug "\t\t", ({"ConnectionState" => "connected"});<br> my %state = ( ConnectionState => "connected" );<br> debug "\t\t", %state;<br> #send_as JSON => ({"ConnectionState" => "connected"});<br> status 201;<br> #send_as JSON => \%state;<br> send_as JSON => {"OK"};<br> }<br> else {<br> debug "\t\t Unvalid login and password : state unconnected\n";<br> debug "\t\t", ({"ConnectionState" => "unconnected"});<br> status 401;<br> session flash => 'Unvalid login and password match!';<br> send_as JSON => ({"ConnectionState" => "unconnected"});<br> redirect '/connect?failed=1';<br> };</div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif"><br>
<br>
true;<br>
<br>
(le hook ne sert à rien, puisque je désactive le CORS dans l'envoi)<br>
Il faut aussi ajouter dans le fichier de conf<br>
<br>
% cat config.yml<br>
logger: Console<br>
<br>
engines:<br>
logger:<br>
Console:<br>
log_level: core</div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif"><br></div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">Le test est toujours valide avec cURL (cf. mon premier post), ce qui prouve que ce test n'est pas correct pour valider le serveur Dancer2. En revanche, en testant dans FF et Chromium, j'ai toujours les 2 mêmes erreurs (c'est-à-dire une erreur de parsing du json retour pour FF, qui trouve pourtant la requête retour, et Chrome qui s'arrête dès l'erreur).</div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif"><br></div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">Du coup, je suis obligé de penser que l'erreur vient de Dancer2, puisque le script javascript est bon et si je remplace Dancer2 par un serveur en javascript, il fonctionne... Donc soit mon code contient une erreur, soit Dancer2 est bogué... J'aurais tendance à incriminer mon code, mais là, je sèche :(<br></div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif"><br></div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">PK<br></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">Le ven. 9 juin 2023 à 06:25, Patrice Karatchentzeff <<a href="mailto:patrice.karatchentzeff@gmail.com">patrice.karatchentzeff@gmail.com</a>> a écrit :<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Merci de ta réponse.<br>
<br>
Je ne me souviens plus d'où j'ai récupéré ce code, mais je crois qu'il<br>
est dans la doc officielle de Dancer2.<br>
<br>
Avec ta modif, j'ai exactement le même comportement, sauf que cela<br>
ajoute une erreur côté Dancer en cas de chaîne vide :<br>
<br>
% curl --header "Content-Type: application/json" --request POST<br>
<a href="http://localhost:5000/connect" rel="noreferrer" target="_blank">http://localhost:5000/connect</a><br>
{"title":"Error 500 - Internal Server<br>
Error","status":500,"exception":"Can't use string (\"\") as a HASH ref<br>
while \"strict refs\" in use at...<br>
<br>
confirmée dans les logs :<br>
<br>
[xx:704249] error @2023-06-09 06:21:38> Route exception: Can't use<br>
string ("") as a HASH ref while "strict refs" in use at /home/pk/...<br>
line 94. in /home/pk/perl5/lib/perl5/Dancer2/Core/App.pm l. 1516<br>
[xx:704249] core @2023-06-09 06:21:38> Entering hook core.error.init<br>
in (eval 245) l. 1<br>
[xx:704249] core @2023-06-09 06:21:38> Entering hook core.error.before<br>
in (eval 245) l. 1<br>
[xx:704249] core @2023-06-09 06:21:38> Entering hook core.error.after<br>
in (eval 245) l. 1<br>
127.0.0.1 - - [09/Jun/2023:06:21:38 +0200] "POST /connect HTTP/1.1"<br>
500 256 "-" "curl/7.81.0"<br>
<br>
Donc, ça me dégrade plutôt les choses. Avec le code initial, j'ai :<br>
<br>
% curl --header "Content-Type: application/json" --request POST<br>
<a href="http://localhost:5000/connect" rel="noreferrer" target="_blank">http://localhost:5000/connect</a><br>
{"ConnectionState":"unconnected"}<br>
<br>
ce qui est le comportement attendu.<br>
<br>
Merci en tout cas d'avoir essayé de m'indiquer une piste.<br>
<br>
Je pense désormais à un bogue, côté React. J'ai déposé un bug request<br>
dans le github de React Native. Je verrais bien...<br>
<br>
Merci<br>
<br>
PK<br>
<br>
Le jeu. 8 juin 2023 à 21:47, Sébastien Feugère <<a href="mailto:sebastien@feugere.net" target="_blank">sebastien@feugere.net</a>> a écrit :<br>
><br>
> Les messages d'erreur de Firefox et de Chrome semblent indiquer que les navigateurs essaient de parser du JSON qui n'en est pas, ou qui n'est pas valide... Peut être une page 404 ?<br>
><br>
> J'ai mis la même route dans une application Dancer crée avec le générateur par défaut.<br>
><br>
> params('body')->{login};<br>
><br>
> params('body')->{password};<br>
><br>
><br>
> sont tous les deux undef, car dans cette situation, params('body') retourne un hash vide... Je ne vois pas comment ce code peut fonctionner avec cURL. Donc dans une application React, encore moins.<br>
><br>
> my $post = from_json( request->body );<br>
> my $login = $post->{login};<br>
> my $password = $post->{password};<br>
><br>
> Avec ceci, j'ai pu me "connecter" avec cURL, pas de soucis et le JSON est bien valide, en utilisant :<br>
><br>
> curl --header "Content-Type: application/json" --request POST --data '{"login":"PK","password":"PK"}' <a href="http://localhost:5000/connect" rel="noreferrer" target="_blank">http://localhost:5000/connect</a><br>
><br>
> En espérant que cela puisse aider...<br>
><br>
> On 08/06/2023 09:10, Patrice Karatchentzeff wrote:<br>
><br>
> Salut,<br>
><br>
> Je poste ici, un peu en désespoir de cause...<br>
><br>
> J'ai isolé mon problème, donc ce sera plus facile. Je cherche à me<br>
> connecter à un back-end Dancer2 avec un simple login+mot de passe<br>
> depuis une appli en Native React. Tout est hard-codé pour plus de<br>
> simplicité. Je poste une requête json (login+mot de passe) et le<br>
> serveur répond en json (connecté ou pas connecté selon la valeur de la<br>
> requête initiale).<br>
><br>
> J'ai un résultat bizarre. Je n'arrive pas à incriminer exactement le<br>
> responsable. Ça marchotte avec Firefox, mais foire avec Chrome.<br>
><br>
> Le problème identifié : la valeur de retour du json (donc côté<br>
> Dancer2) serait mal formattée. Firefox gueule, mais récupère le json<br>
> pourtant correctement. Chrome ne négocie rien du tout et s'arrête en<br>
> cours.<br>
><br>
> Voici le code isolé en react native (désolé, GMail ne veut pas<br>
> d'attaché en javascript) :<br>
><br>
> % cat App.js<br>
> import React, { useState, useEffect } from 'react';<br>
> import {<br>
> View,<br>
> Text,<br>
> } from 'react-native';<br>
><br>
> const ipAddress = "192.168.1.103";<br>
> const portAddress ="5000";<br>
> const httpProtocol = "http";<br>
> const uriBase = httpProtocol + "://" + ipAddress + ":" + portAddress ;<br>
><br>
><br>
> function App() {<br>
><br>
> const jsonReader = { 'login':"PK", 'password':"PK" };<br>
> let string = JSON.stringify(jsonReader);<br>
><br>
> const [message, setMessage] = useState("disconnected");<br>
><br>
> const submitConnectAsync2 = async () => {<br>
> return fetch(<br>
> uriBase + '/connect', {<br>
> //'<a href="http://jsonplaceholder.typicode.com/posts" rel="noreferrer" target="_blank">http://jsonplaceholder.typicode.com/posts</a>', {<br>
> mode: 'no-cors', // beurk...<br>
> method: 'POST',<br>
> headers: {<br>
> 'Accept' : 'application/json',<br>
> 'Content-Type' : 'application/json',<br>
> },<br>
> body: JSON.stringify(jsonReader),<br>
> })<br>
> .then( (response) => {<br>
> //response.text();<br>
> response.json();<br>
> //console.log("Response:", response.text());<br>
> console.log("Response:", response.json());<br>
> console.log("Fin de l'envoi");<br>
> })<br>
> .then(text => {<br>
> console.log(`Received ${JSON.stringify(text)}`);<br>
> console.log("text :", text);<br>
> //let json = JSON.parse(text);<br>
> //setMessage(json);<br>
> console.log("Coucou2");<br>
> })<br>
> .then( (json) => {<br>
> setMessage("Connecté à la main");<br>
> console.log("(1) connection state:", message);<br>
> console.log("Fin de la réception");<br>
> })<br>
> .catch( error => {<br>
> console.log("Transaction error:", error);<br>
> //console.log("body:", JSON.stringify(jsonReader));<br>
> //console.log("response:", response.son());<br>
> //console.log("json:", json);<br>
> });<br>
> };<br>
> console.log("(2) connection state:", message);<br>
><br>
> useEffect(() => {<br>
> submitConnectAsync2();<br>
> }, []);<br>
><br>
><br>
> return (<br>
> <View style={{flex:1,backgroundColor:"white"}}><br>
> <Text><br>
> {message}<br>
> </Text><br>
> </View><br>
> );<br>
><br>
><br>
> }<br>
><br>
> export default App;<br>
><br>
> Voici le code côté Dancer2 :<br>
><br>
> % cat <a href="http://server.pm" rel="noreferrer" target="_blank">server.pm</a><br>
> package server;<br>
> use Dancer2;<br>
><br>
> set session => "Simple";<br>
> set serializer => 'JSON';<br>
><br>
> hook 'before' => sub {<br>
> response_header 'Access-Control-Allow-Origin' => '*';<br>
> };<br>
><br>
> post '/connect' => sub {<br>
> my $post = from_json( request->body );<br>
> debug request->body;<br>
> my $login = params('body')->{login};<br>
> my $password = params('body')->{password};<br>
> debug "\t\t login : $login password : $password";<br>
> if ( ($login eq 'PK') && ($password eq 'PK') ) {<br>
> # nothing possible to add after sending a request<br>
> debug "\t\t Valid login and password : state connected\n";<br>
> session user => $login;<br>
> debug "\t\t", ({"ConnectionState" => "connected"});<br>
> my %state = ( ConnectionState => "connected" );<br>
> debug "\t\t", %state;<br>
> #send_as JSON => ({"ConnectionState" => "connected"});<br>
> send_as JSON => \%state;<br>
> }<br>
> else {<br>
> debug "\t\t Invalid login and password : state unconnected\n";<br>
> debug "\t\t", ({"ConnectionState" => "unconnected"});<br>
> send_as JSON => ({"ConnectionState" => "unconnected"});<br>
> };<br>
> };<br>
><br>
> true;<br>
><br>
> (le hook ne sert à rien, puisque je désactive le CORS dans l'envoi)<br>
> Il faut aussi ajouter dans le fichier de conf<br>
><br>
> % cat config.yml<br>
> logger: Console<br>
><br>
> engines:<br>
> logger:<br>
> Console:<br>
> log_level: core<br>
><br>
> pour activer les debug, sinon remplacer par des print perl suffit.<br>
><br>
> Le serveur « semble » fonctionner correctement :<br>
><br>
> % curl --header "Content-Type: application/json" \<br>
> --request POST \<br>
> --data '{"login":"PK","password":"PK"}' \<br>
> <a href="http://localhost:5000/connect" rel="noreferrer" target="_blank">http://localhost:5000/connect</a><br>
> {"ConnectionState":"connected"}<br>
><br>
> % curl --header "Content-Type: application/json" --request POST --data<br>
> '{"login":"PK","password":""}' <a href="http://localhost:5000/connect" rel="noreferrer" target="_blank">http://localhost:5000/connect</a><br>
> {"ConnectionState":"unconnected"}<br>
><br>
> % curl --header "Content-Type: application/json" --request POST<br>
> <a href="http://localhost:5000/connect" rel="noreferrer" target="_blank">http://localhost:5000/connect</a><br>
> {"ConnectionState":"unconnected"}<br>
><br>
> % curl <a href="http://localhost:5000/connect" rel="noreferrer" target="_blank">http://localhost:5000/connect</a><br>
> {"status":404,"title":"Error 404 - Not Found","message":"/connect"}<br>
><br>
> % curl --header "Content-Type: application/json" --request POST<br>
> <a href="http://localhost:5000/connect" rel="noreferrer" target="_blank">http://localhost:5000/connect</a><br>
> {"ConnectionState":"unconnected"}<br>
><br>
> Le débogueur de Firefox gueule sur le retour de json :<br>
><br>
> 08:44:52,153 (2) connection state: disconnected App.js:58<br>
> 08:44:52,407 Response:<br>
> Promise { <state>: "pending" }<br>
> App.js:36<br>
> 08:44:52,408 Fin de l'envoi App.js:37<br>
> 08:44:52,408 Received undefined App.js:40<br>
> 08:44:52,408 text : undefined App.js:41<br>
> 08:44:52,408 Coucou2 App.js:44<br>
> 08:44:52,409 (1) connection state: disconnected App.js:48<br>
> 08:44:52,409 Fin de la réception App.js:49<br>
> 08:44:52,409 (2) connection state: Connecté à la main App.js:58<br>
> 08:44:52,413 Uncaught (in promise) SyntaxError: JSON.parse: unexpected<br>
> end of data at line 1 column 1 of the JSON data<br>
><br>
> La promesse n'est pas tenue, le response.json semble mal formaté.<br>
> Pourtant, dans l'onglet Réseau, j'ai bien la négociation correcte et<br>
> il lit correctement la réponse ! Ça fonctionne en changeant les<br>
> valeurs des logins/mot de passe.<br>
><br>
> Le log de Dancer2 est en phase : tout semble se passer correctement...<br>
> sauf que je ne peux pas récupérer en interne la valeur de<br>
> response.json comme le montre la sortie console de FF. L'erreur est<br>
> donc « exacte » si je puis m'exprimer ainsi.<br>
><br>
> Chrome est plus brutal.<br>
><br>
> (2) connection state: disconnected<br>
> App.js:36 Response: Promise {<rejected>: SyntaxError: Unexpected end of input<br>
> at <a href="http://localhost:19006/static/js/bundle.js:54:43" rel="noreferrer" target="_blank">http://localhost:19006/static/js/bundle.js:54:43</a>}<br>
> App.js:37 Fin de l'envoi<br>
> App.js:40 Received undefined<br>
> App.js:41 text : undefined<br>
> App.js:44 Coucou2<br>
> App.js:48 (1) connection state: disconnected<br>
> App.js:49 Fin de la réception<br>
> App.js:58 (2) connection state: Connecté à la main<br>
> App.js:34 Uncaught (in promise) SyntaxError: Unexpected end of input<br>
> (at App.js:34:1)<br>
> at App.js:34:1<br>
> App.js:36 Uncaught (in promise) SyntaxError: Unexpected end of input<br>
> (at App.js:36:1)<br>
> at App.js:36:1<br>
><br>
> et il y a plus logiquement aucun échange dans l'onglet Réseau. Dancer2<br>
> renvoie alors bien un 404.<br>
><br>
> Je nage complètement. Le code native semble correct et a l'air de<br>
> fonctionner chez les autres. J'ai réinstallé node/nvm/native... et<br>
> Dancer2 semble fonctionner correctement. J'ai même essayé avec un<br>
> serveur en ligne, sans plus de succès, ce qui me laisse penser que<br>
> Dancer2 n'est pas en cause. J'ai aussi essayé toutes les versions de<br>
> nvm :(<br>
><br>
> Bref, je ne sais plus qui incriminer, à part moi !<br>
><br>
> Un œil neuf serait aussi bienvenu qu'un conseil...<br>
><br>
> Merci<br>
><br>
> PK<br>
><br>
><br>
> PS : pour installer mon exemple en native :<br>
><br>
> % npx install expo-cli<br>
> % npx create-expo-app App<br>
> % cd App<br>
> Remplacer App.js par mon exemple<br>
> % nps expo install react-dom react-native-web @expo/webpack-config<br>
> % npx expo start -- -c<br>
> taper w pour le serveur<br>
><br>
> Changer la valeur des IP pour adapter à votre réseau !<br>
><br>
> --<br>
> Sébastien Feugère<br>
><br>
> _______________________________________________<br>
> Perl mailing list<br>
> <a href="mailto:Perl@mongueurs.net" target="_blank">Perl@mongueurs.net</a><br>
> <a href="http://listes.mongueurs.net/mailman/listinfo/perl" rel="noreferrer" target="_blank">http://listes.mongueurs.net/mailman/listinfo/perl</a><br>
> Attention, les archives sont publiques<br>
<br>
<br>
<br>
-- <br>
|\ _,,,---,,_ Patrice KARATCHENTZEFF<br>
ZZZzz /,`.-'`' -. ;-;;,_ mailto:<a href="mailto:patrice.karatchentzeff@gmail.com" target="_blank">patrice.karatchentzeff@gmail.com</a><br>
|,4- ) )-,_. ,\ ( `'-'<br>
'---''(_/--' `-'\_)<br>
</blockquote></div><br clear="all"><br><span class="gmail_signature_prefix">-- </span><br><div dir="ltr" class="gmail_signature"><div dir="ltr"><div><div dir="ltr"><div> |\ _,,,---,,_ Patrice KARATCHENTZEFF<br>ZZZzz /,`.-'`' -. ;-;;,_ mailto:<a href="mailto:patrice.karatchentzeff@gmail.com" target="_blank">patrice.karatchentzeff@gmail.com</a><br> |,4- ) )-,_. ,\ ( `'-' <br> '---''(_/--' `-'\_) <br></div></div></div></div></div>