Essayer d’envoyer une requête POST au serveur local avec C

J’essaie actuellement d’envoyer une demande POST complète avec C sur mon serveur local, où ma page PHP consumra la demande et INSERT la demande dans la firebase database.

Si j’utilise le formulaire que j’ai créé pour l’insérer dans la firebase database, cela fonctionne parfaitement.

Mais j’essaie de faire la même demande POST mais en C pour INSERT INTO la firebase database. Je ne sais pas comment faire la demande POST . J’ai intercepté la demande avec Burp, donc je sais que la demande sera parfaite et qu’elle fonctionnera. Je ne sais tout simplement pas comment l’implémenter dans mon programme C.

J’ai inclus mon code C actuel pour envoyer la demande HTTP POST .

Je reçois une bonne réponse, mais rien ne s’insère dans la firebase database

 /* Create a TCP socket */ #include #include #pragma comment(lib,"ws2_32.lib") //Winsock Library int main(int argc , char *argv[]) { WSADATA wsa; SOCKET s; struct sockaddr_in server; char *message , server_reply[2000]; int recv_size; printf("\nInitialising Winsock..."); if (WSAStartup(MAKEWORD(2,2),&wsa) != 0) { printf("Failed. Error Code : %d",WSAGetLastError()); return 1; } printf("Initialised.\n"); //Create a socket if((s = socket(AF_INET , SOCK_STREAM , 0 )) == INVALID_SOCKET) { printf("Could not create socket : %d" , WSAGetLastError()); } printf("Socket created.\n"); server.sin_addr.s_addr = inet_addr("127.0.0.1"); server.sin_family = AF_INET; server.sin_port = htons(80); //Connect to remote server if (connect(s , (struct sockaddr *)&server , sizeof(server)) < 0) { puts("connect error"); return 1; } puts("Connected"); char* str2; char* str3; char* str5; char* str20; str2 = "POST /project2/public/addJoke.php HTTP/1.0\r\n"; str3 = "Content-Type: text/plain\r\n"; str20= "Content-Length: 12\r\n\r\n"; str5 = "joketext=ctest&jokedate=2018-01-01"; char * message2 = (char *) malloc(1 + strlen(str2)+ strlen(str3)+ strlen(str5) + strlen(str20)); strcpy(message2,str2); strcat(message2,str3); strcat(message2,str20); strcat(message2,str5); if( send(s , message2 , strlen(message2) , 0) < 0) { puts("Send failed"); return 1; } puts("Data Send\n"); //Receive a reply from the server if((recv_size = recv(s , server_reply , 2000 , 0)) == SOCKET_ERROR) { puts("recv failed"); } puts("Reply received\n"); //Add a NULL terminating character to make it a proper string before printing server_reply[recv_size] = '\0'; puts(server_reply); return 0; } 

Et voici mon fichier PHP qui reçoit la demande.

 if(isset($_POST['joketext'])){ try{ include __DIR__ . '/../includes/databaseconnection.php'; $title = 'Good Connection'; $sql = 'INSERT INTO jokes.jokes_tbl SET joketext = :joketext, jokedate = CURDATE(), authorid = :authorid'; $stmt = $pdo->prepare($sql); $stmt->bindValue(':joketext', $_POST['joketext']); $stmt->bindValue(':authorid', $_POST['authorid']); $stmt->execute(); header('location: jokeslist.php'); }catch(PDOException $err){ $title = 'Bad Connection'; $output = 'Bad Connection' . $err->getMessage() . ' in ' . $err->getFile() . ':' . $err->getLine(); } }else{ ob_start(); include __DIR__ . '/../templates/addJoke.html.php'; $output = ob_get_clean(); } include __DIR__ . '/../templates/layout.html.php'; 

J’ai intercepté la demande avec Burp, donc je sais que la demande sera parfaite et qu’elle fonctionnera .

Seulement ce n’est pas:

  message = "POST /project2/public/addJoke.php HTTP/1.1 ... upgrade-Insecure-Requests: 1 joketext=test200&authorid=1" 

Avec quelques notions de base sur HTTP, on peut constater qu’il n’existe aucun marqueur qui termine l’en-tête HTTP et commence le corps HTTP, c’est-à-dire qu’il manque une ligne vide entre l’en-tête et le corps. Cela signifie que joketext=test200&authorid=1 est traité par le serveur comme faisant partie de l’en-tête (bien que sa syntaxe soit invalide) et que, comme aucun marqueur de fin d’en-tête n’est utilisé, l’en-tête est considéré comme incomplet et, par conséquent, aucun corps n’est détecté. Le deuxième problème est que la fin de ligne que vous utilisez est probablement \n et non \r\n comme il se doit.

En outre, vous supposez que send enverra tout dans la mémoire tampon et ne recherchera que les erreurs:

  if( send(s , message , strlen(message) , 0) < 0) 

Seulement, send n'a pas une telle garantie. Au lieu de cela, vous devez vérifier le nombre d'octets réellement envoyés dans la valeur de retour et effectuer un autre send avec les données restantes (non envoyées). Pour les petits tampons comme celui-ci, vous n'aurez probablement besoin que d'un seul send mais vous rencontrerez des problèmes pour les tampons plus grands.

En général: HTTP est beaucoup plus complexe que vous ne le pensez en regardant à peine certaines requêtes HTTP. Il existe une norme pour une raison et quiconque code HTTP directement doit étudier et comprendre la norme. Examiner quelques demandes à titre d'exemple ne suffit pas, en particulier si l'on omet de regarder de près et qu'il manque donc des détails sur la nouvelle ligne de l'espace blanc, c'est-à-dire où elle appartient et en quoi consiste l'espace blanc.

EDIT: il semble que le PO ait lourdement modifié le code dans la question, ce qui pose de nouveaux problèmes:

 str2 = "POST /project2/public/addJoke.php HTTP/1.0\r\n"; str3 = "Content-Type: text/plain\r\n"; str20= "Content-Length: 12\r\n\r\n"; str5 = "joketext=ctest&jokedate=2018-01-01"; 

Il est évident que la longueur de 12 donnée dans str20 ne correspond pas à la longueur du corps réel dans str5 qui est 34. Et, le formulaire attend un Content-Type de l' application/x-www-form-urlencoded au lieu de text/plain . Les deux choses étaient correctes dans la question initiale mais sont maintenant fausses. Par conséquent, je vais répéter ma recommandation ci-dessus: "... quiconque codant directement HTTP doit étudier et comprendre la norme. Examiner quelques requêtes à titre d'exemple ne suffit pas ..."