[EtherCard] Envoyer une requete POST

Bonjour à tous, Je travail actuellement avec un module ethernet breakout board enc28j60 et un arduino MEGA 2560.

je cherche à envoyer des variables par méthode POST à un script PHP.
la méthode GET marche bien mais je préférerais utilisé la méthode POST.

Je dispose du script suivant :

#include <EtherCard.h>

static byte mymac[] = {0xDD,0xDD,0xDD,0x00,0x00,0x01};
char website[] PROGMEM = "192.168.100.22";

boolean x = true;

byte Ethernet::buffer[700];
static uint32_t timer;

static void response_callback (byte status, word off, word len) {
  
  Serial.print((const char*) Ethernet::buffer + off + 207);
}
 
void setup () {
 
  Serial.begin(57600);
  Serial.println("Client Demo");
  Serial.println();
 
  if (!ether.begin(sizeof Ethernet::buffer, mymac, 10))
    Serial.println( "Failed to access Ethernet controller");
 else
   Serial.println("Ethernet controller initialized");
 Serial.println();
 
  if (!ether.dhcpSetup())
    Serial.println("Failed to get configuration from DHCP");
  else
    Serial.println("DHCP configuration done");
 
  ether.printIp("IP Address:\t", ether.myip);
  ether.printIp("Netmask:\t", ether.mymask);
  ether.printIp("Gateway:\t", ether.gwip);
  Serial.println();
  
  ether.hisip[0] = 192;
  ether.hisip[1] = 168;
  ether.hisip[2] = 100;
  ether.hisip[3] = 22;
  ether.printIp("SRV IP:\t", ether.hisip);
  Serial.println("Loop :");
  delay(1000);
}
 
void loop() {
 
  ether.packetLoop(ether.packetReceive());
  
  if ((millis() > timer) && x == true) {
    timer = millis() + 5000;
    const char postval[] = "id=422";
    ether.httpPost(PSTR("/test/index2.php"), website, PSTR(""), postval, response_callback);
    x = false;
  }
}

et voici mon script php :

<?php

        if(isset($_POST["id"]))
                echo "id :" . $_POST["id"];
        elseif(isset($_GET["id"]))
                echo "id :" . $_GET["id"];
        else
                echo "nothing to show";
?>

Seulement, le problème est que mon arduino me retourne "nothing to show" au lieu de me retournée le nombre 422.

Je ne comprend pas d'où vient le problème.

Merci à tous.
Timiti29

PS : voici le prototype de la fonction httpPost :

void EtherCard::httpPost (prog_char *urlbuf, prog_char *hoststr, prog_char *additionalheaderline,const char *postval,void (*callback)(byte,word,word))

bonjour,
même réponse que dans ton autre post.
log apache?

mais réduit ton php en plus simple

<?php if(isset($_POST['id']) || isset($_GET['id']) ) { $id_post = $_POST['id']; $id_get = $_GET['id']; echo " post id : $id_post get id : $id_get"; } else{ echo "nothing to show"; } ?>

Re, concernant le code PHP je le trouve claire pour un exemple basique pour tester les variables POST et GET.

Ensuite concernant le fichier error.log, il est vide
et le fichier access.log contient une ligne :

192.168.100.100 - - [20/Oct/2013:21:05:42 +0200] "POST /test/index2.php HTTP/1.0" 200 226 "-" "-"

Il ne devrais pas y avoir les variables ?

Merci
Timiti29

timiti29:
Re, concernant le code PHP je le trouve claire pour un exemple basique pour tester les variables POST et GET.

Ensuite concernant le fichier error.log, il est vide
et le fichier access.log contient une ligne :

192.168.100.100 - - [20/Oct/2013:21:05:42 +0200] "POST /test/index2.php HTTP/1.0" 200 226 "-" "-"

Il ne devrais pas y avoir les variables ?

Merci
Timiti29

tu fais comme tu veux pour ton php, mais là, tu sais même pas ou ca bloque :wink:

ben non, vu que tu fais un POST, donc pas de variable, un GET oui.
trace les données du POST dans un fichier, ca sera plus simple ou dans la bdd

Je trouve ton code PHP tout a fait ok.
Mais comme pour le précédant, je suggère d'utiliser tcpdump

Tout a l'heure je n'avais pas la possibilité d'être plus clair sur l'utilisation de tcpdump mais là je suis de retour sur mon PC.

Le man est ici : tcpdump(1) man page | TCPDUMP & LIBPCAP mais aussi "man tcpdump" ou "tcpdump --help"

Le plus simple est de mettre un filtre sur l'IP de ton Arduino : "tcpdump host 192.168.100.100"
Tu devrais voir passer les échanges DHCP puis la requette HTTP.
Je suis sous Windows avec Wireshark c'est plus facile mais tu devrais quand même pouvoir tout voir.

Il y a peut être des équivalents de Wireshark sous Linux mais je ne les connais pas.

La création de Linux | linuxcore.fr :grin:

Cool
Y'a des trucs bien chez les pingouins :smiley:
=> []

voila le resultat d'un tcpdump -i eth1 src 192.168.100.100 -vvv :

23:45:19.226273 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto UDP (17), length 310)
    192.168.100.100.bootpc > 255.255.255.255.bootps: [udp sum ok] BOOTP/DHCP, Request from dd:dd:dd:00:00:01 (oui Unknown), length 282, xid 0x36000000, Flags [none] (0x0000)
	  Client-Ethernet-Address dd:dd:dd:00:00:01 (oui Unknown)
	  Vendor-rfc1048 Extensions
	    Magic Cookie 0x63825363
	    DHCP-Message Option 53, length 1: Request
	    Client-ID Option 61, length 7: ether dd:dd:dd:00:00:01
	    Hostname Option 12, length 10: "Arduino-01"
	    Requested-IP Option 50, length 4: 192.168.100.100
	    Server-ID Option 54, length 4: Dj-Timiti29.local
	    Parameter-Request Option 55, length 3: 
	      Subnet-Mask, Default-Gateway, Domain-Name-Server
	    END Option 255, length 0
23:45:23.245479 ARP, Ethernet (len 6), IPv4 (len 4), Request who-has Dj-Timiti29.local tell 192.168.100.100, length 46
23:45:23.246613 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 44)
    192.168.100.100.2850 > Dj-Timiti29.local.http: Flags [S], cksum 0x3977 (correct), seq 2560, win 768, options [mss 550], length 0
23:45:23.247635 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 40)
    192.168.100.100.2850 > Dj-Timiti29.local.http: Flags [R.], cksum 0x732f (correct), seq 2704, ack 1077778582, win 1024, length 0
23:45:23.248140 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 44)
    192.168.100.100.2851 > Dj-Timiti29.local.http: Flags [S], cksum 0x3676 (correct), seq 3328, win 768, options [mss 550], length 0
23:45:23.249149 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 40)
    192.168.100.100.2851 > Dj-Timiti29.local.http: Flags [.], cksum 0x1dd5 (correct), seq 3329, ack 3273746590, win 1024, length 0
23:45:23.250353 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 182)
    192.168.100.100.2851 > Dj-Timiti29.local.http: Flags [P.], cksum 0xc357 (correct), seq 0:142, ack 1, win 1024, length 142
23:45:23.253076 IP (tos 0x0, ttl 64, id 43576, offset 0, flags [DF], proto TCP (6), length 40)
    192.168.100.100.2851 > Dj-Timiti29.local.http: Flags [FP.], cksum 0x1c5c (correct), seq 142, ack 227, win 1024, length 0
23:45:23.253900 IP (tos 0x0, ttl 64, id 43577, offset 0, flags [DF], proto TCP (6), length 40)
    192.168.100.100.2851 > Dj-Timiti29.local.http: Flags [FP.], cksum 0x1c5b (correct), seq 142, ack 228, win 1024, length 0

Merci
Timiti29

barbudor:
Cool
Y'a des trucs bien chez les pingouins :smiley:
=> []

HS
héhé plus qu'on ne croit :slight_smile: franchement du mal a revenir sur un windaub pour du dépannage

mais wireshark ne montre que les trames, pas ce qui est envoyé en données.
d'ou mon idée de mettre en fichier les données recues.

mais un truc me tarabusque quand même, la config de son apache.
j'ai bien peur qu'il prenne comme un Ddos ou autre les requêtes aussi proches et du coup bloque les données.
j'ai pas regardé la lib, mais ca me donne pas l'impression d'envoyer la variable "id" quelque part.

en suivant le process d'un post ca revient à ca
formulaire methode =POST
variable name=id
value = 3
submit

un GET est plus approprié pour éviter le formulaire, un lien suffit, chose impossible via un POST puisque les variables ne passent pas dans le lien, mais c'est mon avis perso.

J'ai pour projet d'envoyer des requetes SQL, je pensse que pour une telle utilisation, une methode POST est plus approprié.
(j'ai pas envie d'avoir des conversions d'espace etc...)

consernant la configuration d'apache, elle est d'origine, je n'est rien modifié depuis l'installation.

Merci
Timiti29

dans un premier temps passe par un GET pour vérifier si ca passe.
peut être un bug dans la lib, qui sait?

De toute évidence, j'ai du oublié une paramètre de ligne de commande pour obtenir le contenu des paquets.
Il faut d'ailleurs peut être demander à tcpdump de faire un fichier pcap (capture) et ensuite l'exploiter avec un autre soft
Ou alors prendre Wireshark puisqu'il y a une version Linux

N'en déplaise à Infobarquee, on peut voir l'intégralité d'une conversation TCP non cryptée dans Wireshark avec "Follow TCP stream"
Cf la copie d'écran ci dessous
Faut dire que sous Windaube on est faignant de la console, alors forcément les utilitaires nous machent le travail :grin:

barbudor:
De toute évidence, j'ai du oublié une paramètre de ligne de commande pour obtenir le contenu des paquets.
Il faut d'ailleurs peut être demander à tcpdump de faire un fichier pcap (capture) et ensuite l'exploiter avec un autre soft
Ou alors prendre Wireshark puisqu'il y a une version Linux

N'en déplaise à Infobarquee, on peut voir l'intégralité d'une conversation TCP non cryptée dans Wireshark avec "Follow TCP stream"
Cf la copie d'écran ci dessous
Faut dire que sous Windaube on est faignant de la console, alors forcément les utilitaires nous machent le travail :grin:

gnarf gnarf gnarf, :slight_smile:
je viens de lire justement cette option dans wireshark qui est dispo aussi sous nunux.
là tu fais sur un GET, teste avec un POST via un formulaire pour voir si on trace la variable.
pas installé le prog encore sur mon nunux.

Pfff
j'ai dis que j'était faignant
Enfin, voilà : on voit très bien passer les variables avec Wireshark

oki,
je me coucherai moins benet ce soir :slight_smile: mais pas pour autant que tu me redonne gout à windaub, héhéhé.
donc, notre ami, n'a plus qu'a faire la même chose pour vérifier les trames envoyées.

Bonjour, J'ai fait quelques tests, les voici :

Fenêtre Follow TCP Stream avec une utilisation POST de l'arduino :

POST /test/index2.php HTTP/1.0
Host: 192.168.100.22


Accept: */*
Content-Length: 1
Content-Type: application/x-www-form-urlencoded

%HTTP/1.1 200 OK
Date: Tue, 22 Oct 2013 15:30:45 GMT
Server: Apache/2.2.22 (Ubuntu)
X-Powered-By: PHP/5.4.9-4ubuntu2.3
Vary: Accept-Encoding
Content-Length: 15
Connection: close
Content-Type: text/html

nothing to show

Puis le contenue de la même fenêtre toujour en POST mais avec un formulaire html sur le PC.
(j'ai bien le résultat attendue sur le navigateur)

POST /test/index2.php HTTP/1.1
Host: localhost
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: fr,fr-fr;q=0.8,en-us;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Referer: http://localhost/test/index.php
Cookie: __atuvc=2%7C32; fda0c6158220e9c88fb60796995d97d0=nc6un7948pth64r8k3u0m3kq63
Connection: keep-alive
Content-Type: application/x-www-form-urlencoded
Content-Length: 6

id=422HTTP/1.1 200 OK
Date: Tue, 22 Oct 2013 15:39:23 GMT
Server: Apache/2.2.22 (Ubuntu)
X-Powered-By: PHP/5.4.9-4ubuntu2.3
Vary: Accept-Encoding
Content-Encoding: gzip
Content-Length: 27
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Content-Type: text/html

...........LQ.212..x..H....

et avec l'arduino en methode GET :

GET /test/index2.php?id=422 HTTP/1.0
Host: 192.168.100.22
Accept: text/html

HTTP/1.1 200 OK
Date: Tue, 22 Oct 2013 15:41:33 GMT
Server: Apache/2.2.22 (Ubuntu)
X-Powered-By: PHP/5.4.9-4ubuntu2.3
Vary: Accept-Encoding
Content-Length: 7
Connection: close
Content-Type: text/html

id :422

Le problème doit venir de la librairie non ?

Voici la fonction qui semble géré les requêtes HTTP : (dans le fichier tcpip.cpp)

static word www_client_internal_datafill_cb(byte fd) {
  BufferFiller bfill = EtherCard::tcpOffset();
  if (fd==www_fd) {
    if (client_postval == 0) {
      bfill.emit_p(PSTR("GET $F$S HTTP/1.0\r\n"
                        "Host: $F\r\n"
                        "$F\r\n"
                        "\r\n"), client_urlbuf,
                                 client_urlbuf_var,
                                 client_hoststr, client_additionalheaderline);
    } else {
      prog_char* ahl = client_additionalheaderline;
      bfill.emit_p(PSTR("POST $F HTTP/1.0\r\n"
                        "Host: $F\r\n"
                        "$F$S\r\n"
                        "Accept: */*\r\n"
                        "Content-Length: $D\r\n"
                        "Content-Type: application/x-www-form-urlencoded\r\n"
                        "\r\n"
                        "$S"), client_urlbuf,
                                 client_hoststr,
                                 ahl != 0 ? ahl : PSTR(""),
                                 ahl != 0 ? "\r\n" : "",
                                 strlen(client_postval),
                                 client_postval);
    }
  }
  return bfill.position();
}

Merci.
Timiti29

essaye de changer tous les

HTTP/1.0\r\n"

par

HTTP/1.1\r\n"

et vire les cookies qui doivent aussi poser soucis

De toute évidence il y a une ligne vide en trop dans le cas de la commande POST qui fait que le serveur interprète cela comme la fin de l'entête et le "Accept" est alors vu comme des data.

Dans le code de la lib, pour le cas du POST, je vois :

prog_char* ahl = client_additionalheaderline;
bfill.emit_p(PSTR("POST $F HTTP/1.0\r\n"
"Host: $F\r\n"
"$F$S\r\n"
"Accept: /\r\n"
"Content-Length: $D\r\n"
"Content-Type: application/x-www-form-urlencoded\r\n"
"\r\n"
"$S"), client_urlbuf,
client_hoststr,
ahl != 0 ? ahl : PSTR(""),
** ahl != 0 ? "\r\n" : "",**
strlen(client_postval),
client_postval);

Donc si client_additionalheaderline est une variable NULL alors la lib insère une ligne vide à cet endroit.

Or tu n'as pas la dernière version car ceci a été corrigé dans le code sous GitHub :

prog_char* ahl = client_additionalheaderline;
bfill.emit_p(PSTR("POST $F HTTP/1.0\r\n"
"Host: $F\r\n"
"$F$S"
"Accept: /\r\n"
"Content-Length: $D\r\n"
"Content-Type: application/x-www-form-urlencoded\r\n"
"\r\n"
"$S"), client_urlbuf,
client_hoststr,
ahl != 0 ? ahl : PSTR(""),
ahl != 0 ? "\r\n" : "",
strlen(client_postval),
client_postval);

Allez, zou. Va faire une tour sur GitHub : GitHub - njh/EtherCard: EtherCard is an IPv4 driver for the ENC28J60 chip, compatible with Arduino IDE

Je vais essayer, quel cookies ? y'a pas de cookies sur un arduino (je vois pas ou il pourrais les stocker)
J'ai essayer avec HTTP/1.1\r\n" mais sa na fait aucun changement.

Sinon j'ai retélécharger la librairie, je ne voit pas de changement, j'ai donc remodifier manuellement afin d'enlever le \r\n.
J'ai à présent un nothing to show.

Voila le résultat dans Wireshark :

POST /test/index2.php HTTP/1.0
Host: 192.168.100.22

Accept: */*
Content-Length: 1
Content-Type: application/x-www-form-urlencoded

%HTTP/1.1 200 OK
Date: Tue, 22 Oct 2013 19:45:48 GMT
Server: Apache/2.2.22 (Ubuntu)
X-Powered-By: PHP/5.4.9-4ubuntu2.3
Vary: Accept-Encoding
Content-Length: 15
Connection: close
Content-Type: text/html

nothing to show

Les variables non pas l'aire d’êtres envoyés.
Merci
Timiti29

Je persiste, la version qui est sur GitHub n'a pas le "\r\n" après $F$S

En fait je pense qu'en plus y'a une erreur dans ton code (qui provient peut être d'un mauvais exemple)
Mais le 3eme paramètre additionalheaderline devrait être NULL plutot que PSTR("")

PST("") est non null
Donc

   "$F$S"
...
  ahl != 0 ? ahl : PSTR(""),
  ahl != 0 ? "\r\n" : "",

$F$S devient additionalheaderline suivit de "\r\n" c'est à dire "" suivit de "\r\n" donc une ligne vide

Si additionalheaderline est null on passe dans le 2eme cas du ? et $F$S devient "" suivit de "" soit rien du tout, même pas un retour à la ligne donc on continue ensuite sur "Accept:"

En résumé :

  • Il faut la dernière version de la lib qui utilise $F$S au lieu de $F$S\r\n
  • il faut que le 3eme paramètre de httpPost() soit NULL au lieu de PSTR("")