<html data-lt-installed="true">
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  </head>
  <body style="padding-bottom: 1px;">
    <p>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>
    </p>
    <p>J'ai mis la même route dans une application Dancer crée avec le
      générateur par défaut.</p>
    <font face="monospace">params('body')-&gt;{login}; <br>
    </font><br>
    <font face="monospace">params('body')-&gt;{password};</font>
    <p><font face="monospace">
      </font></p>
    <div class="moz-cite-prefix"><br>
    </div>
    <div class="moz-cite-prefix">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>
    </div>
    <div class="moz-cite-prefix"><br>
    </div>
    <div class="moz-cite-prefix"><font face="monospace">my $post =
        from_json( request-&gt;body );<br>
        my $login = $post-&gt;{login};<br>
        my $password = $post-&gt;{password};<br>
      </font></div>
    <div class="moz-cite-prefix"><br>
    </div>
    <div class="moz-cite-prefix">Avec ceci, j'ai pu me "connecter" avec
      cURL, pas de soucis et le JSON est bien valide,  en utilisant :<br>
    </div>
    <div class="moz-cite-prefix"><br>
    </div>
    <div class="moz-cite-prefix">curl --header "Content-Type:
      application/json"   --request POST   --data
      '{"login":"PK","password":"PK"}'   <a class="moz-txt-link-freetext" href="http://localhost:5000/connect">http://localhost:5000/connect</a><br>
    </div>
    <div class="moz-cite-prefix"><br>
    </div>
    <div class="moz-cite-prefix">En espérant que cela puisse aider...<br>
    </div>
    <div class="moz-cite-prefix"><br>
    </div>
    <div class="moz-cite-prefix">On 08/06/2023 09:10, Patrice
      Karatchentzeff wrote:<br>
    </div>
    <blockquote type="cite"
cite="mid:CALbP57vAS8Tumj3btkFPDArKXLBhxquQXyuUMzJKVJCQkxiOow@mail.gmail.com">
      <pre class="moz-quote-pre" wrap="">Salut,

Je poste ici, un peu en désespoir de cause...

J'ai isolé mon problème, donc ce sera plus facile. Je cherche à me
connecter à un back-end Dancer2 avec un simple login+mot de passe
depuis une appli en Native React. Tout est hard-codé pour plus de
simplicité. Je poste une requête json (login+mot de passe) et le
serveur répond en json (connecté ou pas connecté selon la valeur de la
requête initiale).

J'ai un résultat bizarre. Je n'arrive pas à incriminer exactement le
responsable. Ça marchotte avec Firefox, mais foire avec Chrome.

Le problème identifié : la valeur de retour du json (donc côté
Dancer2) serait mal formattée. Firefox gueule, mais récupère le json
pourtant correctement. Chrome ne négocie rien du tout et s'arrête en
cours.

Voici le code isolé en react native (désolé, GMail ne veut pas
d'attaché en javascript) :

% cat App.js
import React, { useState, useEffect } from 'react';
import {
  View,
  Text,
} from 'react-native';

const ipAddress     = "192.168.1.103";
const portAddress   ="5000";
const httpProtocol  = "http";
const uriBase       = httpProtocol + "://" + ipAddress + ":" + portAddress ;


function App() {

  const jsonReader = { 'login':"PK", 'password':"PK" };
  let string = JSON.stringify(jsonReader);

  const [message, setMessage] = useState("disconnected");

  const submitConnectAsync2 = async () =&gt; {
    return fetch(
            uriBase + '/connect', {
      //'<a class="moz-txt-link-freetext" href="http://jsonplaceholder.typicode.com/posts">http://jsonplaceholder.typicode.com/posts</a>', {
    mode: 'no-cors', // beurk...
    method: 'POST',
    headers: {
          'Accept' : 'application/json',
          'Content-Type' : 'application/json',
    },
    body: JSON.stringify(jsonReader),
      })
      .then( (response) =&gt; {
          //response.text();
    response.json();
          //console.log("Response:", response.text());
    console.log("Response:", response.json());
          console.log("Fin de l'envoi");
      })
      .then(text =&gt; {
        console.log(`Received ${JSON.stringify(text)}`);
          console.log("text :", text);
        //let json = JSON.parse(text);
        //setMessage(json);
        console.log("Coucou2");
      })
      .then( (json) =&gt; {
          setMessage("Connecté à la main");
          console.log("(1) connection state:", message);
          console.log("Fin de la réception");
      })
      .catch( error =&gt; {
    console.log("Transaction error:", error);
    //console.log("body:", JSON.stringify(jsonReader));
    //console.log("response:", response.son());
    //console.log("json:", json);
      });
  };
  console.log("(2) connection state:", message);

  useEffect(() =&gt; {
    submitConnectAsync2();
  }, []);


 return (
   &lt;View style={{flex:1,backgroundColor:"white"}}&gt;
     &lt;Text&gt;
       {message}
     &lt;/Text&gt;
   &lt;/View&gt;
  );


}

export default App;

Voici le code côté Dancer2 :

% cat server.pm
package server;
use Dancer2;

set session =&gt; "Simple";
set serializer =&gt; 'JSON';

hook 'before' =&gt; sub {
    response_header 'Access-Control-Allow-Origin' =&gt; '*';
};

post '/connect' =&gt; sub {
  my $post = from_json( request-&gt;body );
  debug request-&gt;body;
  my $login    = params('body')-&gt;{login};
  my $password = params('body')-&gt;{password};
  debug "\t\t login : $login   password : $password";
  if ( ($login eq 'PK') &amp;&amp; ($password eq 'PK') ) {
    # nothing possible to add after sending a request
    debug "\t\t Valid login and password : state connected\n";
    session user =&gt; $login;
    debug "\t\t", ({"ConnectionState" =&gt; "connected"});
    my %state = ( ConnectionState =&gt; "connected" );
    debug "\t\t", %state;
    #send_as JSON =&gt; ({"ConnectionState" =&gt; "connected"});
    send_as JSON =&gt; \%state;
  }
  else {
    debug "\t\t Invalid login and password : state unconnected\n";
    debug "\t\t", ({"ConnectionState" =&gt; "unconnected"});
    send_as JSON =&gt; ({"ConnectionState" =&gt; "unconnected"});
  };
};

true;

(le hook ne sert à rien, puisque je désactive le CORS dans l'envoi)
Il faut aussi ajouter dans le fichier de conf

% cat config.yml
logger: Console

engines:
  logger:
    Console:
      log_level: core

pour activer les debug, sinon remplacer par des print perl suffit.

Le serveur « semble » fonctionner correctement :

% curl --header "Content-Type: application/json" \
  --request POST \
  --data '{"login":"PK","password":"PK"}' \
  <a class="moz-txt-link-freetext" href="http://localhost:5000/connect">http://localhost:5000/connect</a>
{"ConnectionState":"connected"}

% curl --header "Content-Type: application/json" --request POST --data
'{"login":"PK","password":""}' <a class="moz-txt-link-freetext" href="http://localhost:5000/connect">http://localhost:5000/connect</a>
{"ConnectionState":"unconnected"}

% curl --header "Content-Type: application/json" --request POST
<a class="moz-txt-link-freetext" href="http://localhost:5000/connect">http://localhost:5000/connect</a>
{"ConnectionState":"unconnected"}

% curl  <a class="moz-txt-link-freetext" href="http://localhost:5000/connect">http://localhost:5000/connect</a>
{"status":404,"title":"Error 404 - Not Found","message":"/connect"}

% curl --header "Content-Type: application/json" --request POST
<a class="moz-txt-link-freetext" href="http://localhost:5000/connect">http://localhost:5000/connect</a>
{"ConnectionState":"unconnected"}

Le débogueur de Firefox gueule sur le retour de json :

08:44:52,153 (2) connection state: disconnected App.js:58
08:44:52,407 Response:
Promise { &lt;state&gt;: "pending" }
App.js:36
08:44:52,408 Fin de l'envoi App.js:37
08:44:52,408 Received undefined App.js:40
08:44:52,408 text : undefined App.js:41
08:44:52,408 Coucou2 App.js:44
08:44:52,409 (1) connection state: disconnected App.js:48
08:44:52,409 Fin de la réception App.js:49
08:44:52,409 (2) connection state: Connecté à la main App.js:58
08:44:52,413 Uncaught (in promise) SyntaxError: JSON.parse: unexpected
end of data at line 1 column 1 of the JSON data

La promesse n'est pas tenue, le response.json semble mal formaté.
Pourtant, dans l'onglet Réseau, j'ai bien la négociation correcte et
il lit correctement la réponse ! Ça fonctionne en changeant les
valeurs des logins/mot de passe.

Le log de Dancer2 est en phase : tout semble se passer correctement...
sauf que je ne peux pas récupérer en interne la valeur de
response.json comme le montre la sortie console de FF. L'erreur est
donc « exacte » si je puis m'exprimer ainsi.

Chrome est plus brutal.

(2) connection state: disconnected
App.js:36 Response: Promise {&lt;rejected&gt;: SyntaxError: Unexpected end of input
    at <a class="moz-txt-link-freetext" href="http://localhost:19006/static/js/bundle.js:54:43">http://localhost:19006/static/js/bundle.js:54:43</a>}
App.js:37 Fin de l'envoi
App.js:40 Received undefined
App.js:41 text : undefined
App.js:44 Coucou2
App.js:48 (1) connection state: disconnected
App.js:49 Fin de la réception
App.js:58 (2) connection state: Connecté à la main
App.js:34 Uncaught (in promise) SyntaxError: Unexpected end of input
(at App.js:34:1)
    at App.js:34:1
App.js:36 Uncaught (in promise) SyntaxError: Unexpected end of input
(at App.js:36:1)
    at App.js:36:1

et il y a plus logiquement aucun échange dans l'onglet Réseau. Dancer2
renvoie alors bien un 404.

Je nage complètement. Le code native semble correct et a l'air de
fonctionner chez les autres. J'ai réinstallé node/nvm/native... et
Dancer2 semble fonctionner correctement. J'ai même essayé avec un
serveur en ligne, sans plus de succès, ce qui me laisse penser que
Dancer2 n'est pas en cause. J'ai aussi essayé toutes les versions de
nvm :(

Bref, je ne sais plus qui incriminer, à part moi !

Un œil neuf serait aussi bienvenu qu'un conseil...

Merci

PK


PS : pour installer mon exemple en native :

% npx install expo-cli
% npx create-expo-app App
% cd App
Remplacer App.js par mon exemple
% nps expo install react-dom react-native-web @expo/webpack-config
% npx expo start -- -c
taper w pour le serveur

Changer la valeur des IP pour adapter à votre réseau !

</pre>
    </blockquote>
    <pre class="moz-signature" cols="72">-- 
Sébastien Feugère</pre>
  </body>
  <lt-container></lt-container>
</html>