Récuperer la valeur retournée après un HTTP POST
yodark
Membre
Bonjour,
Ma question est très simple, comment faire pour récuperer le contenu d'une page web retrounée après un POST ? J'ai le code source suivant :
la variable connectionResponse ne contient pas le retour HTTP de ma requete. Je voudrais pouvoir récuperer le toute dans un String
Ma question est très simple, comment faire pour récuperer le contenu d'une page web retrounée après un POST ? J'ai le code source suivant :
httpBodyString=[[NSMutableString alloc] initWithFormat:@"radiobutton=1&boutton=1&rndnocheck=0"];<br />urlString=[[NSMutableString alloc] initWithString:@"www.site.com"];<br /> url=[[NSURL alloc] initWithString:urlString];<br /> [urlString release];<br /> <br /> NSMutableURLRequest *urlRequest=[NSMutableURLRequest requestWithURL:url];<br /> [url release];<br /> [urlRequest setHTTPMethod:@"POST"];<br /> [urlRequest setHTTPBody:[httpBodyString dataUsingEncoding:NSISOLatin1StringEncoding]];<br /> [httpBodyString release];<br /> <br /> NSURLConnection *connectionResponse = [[NSURLConnection alloc] initWithRequest:urlRequest delegate:self];<br /> if (!connectionResponse)<br /> {<br /> NSLog(@"Failed to submit request");<br /> }<br /> else<br /> {<br /> NSLog(@"Request submitted %@",connectionResponse);<br /> <br /> }<br />
la variable connectionResponse ne contient pas le retour HTTP de ma requete. Je voudrais pouvoir récuperer le toute dans un String
Connectez-vous ou Inscrivez-vous pour répondre.
Réponses
ça te met le contenu de la page dans ton NSString que tu peux ensuite parser.
initWithContentsOfURL:@www.site.com?getvariable=mavariable encoding
Comment l'utiliser avec POST?
Puisque d'après ton code, tu utilises NSURLConnection en asynchrone, alors il faut que la méthode delegate connection:didReceiveResponse: soit implémentée.
Ce delegate est appelé quand la réponse au POST est reçue.
En paramètre, cette méthode reçoit un argument de classe NSHTTPURLResponse par lequel tu pourras récupérer le contenu de la réponse HTTP au POST.
Je dois mettre quoi dans returningResponse ? Je dois quand même initer NSURLConnection ? "connectionResponse" ne répond pas à cette méthode sendSynchronousRequest
Tu l'appelles avec :
(tu t'en fous, ce sont des objets qui sont auto-released si définis lors du processus)
Il n'y a pas de NSURLConnection à initier, c'est une méthode de classe (donc qui ne s'appelle pas sur une instance !)
J'essaie de me connecter à un site, la connexion marche, mais la page retournée par le site (NSData) me dit que je n'ai pas saisi mon identifiant...
et
Est-ce que je saisi bien le user et le password dans mon urlRequest ?
login et password sont bien entendu saisis correctement.
En effet tu définis les valeurs pour "login" et "passwrd"... en tant que "HTTPHeaders", or les headers c'est pour décrire ta requête du genre son Content-Type, sa méthode GET ou POST, ... mais pas les données que tu envoies.
Il faut donc si tu veux passer les données en POST que tu passes une chaà®ne du genre "login=....&passwrd=..." dans le body de ta requête, via un [tt][urlRequest setHTTPBody:...][/tt].
Après pour construire ce body proprement, faut juste faire gaffe au échappements de caractères. Le plus simple étant de faire :
Même si je me demande s'il n'existe pas dans la classe NSDicitonary une façon de demander la représentation "key1=value1&key2=value2&..." typique de l'utilisation dans des URLs ou des données POST, car dans ce cas ça serait plus propre de construire le dictionary et récupérer cette forme encodée à partir de ce dernier... Mais bon pour ton besoin ça devrait suffire.
Oui c'est bien passwrd.
C'est exactement ce que je veux faire. AH bein je viens de voir ta réponse !
Je trouve cela vraiment plus logique, je me demandais le rapport entre les headers et les variables envoyées qui font effectivement partie du body !
Je teste et je te tiens au courant.
Merci Ali !
Merci encore.
Pour faire les choses proprement, je me suis taillé un Controller de loging (URLLoggerController) vers un site Internet qui se charge donc d'envoyer la requête POST et qui contient aussi les méthodes delegate de NSURLCONNECTION.
Maintenant, au moment d'erreurs ou autre dans ces méthodes delegate, je voudrais envoyer des messages à la classe qui instancie ce nouveau controlleur et qui le nourrit.
Par exemple, quand un utilisateur est connecté, ça ne suffit pas de passer une variable d'instance (un BOOL) à YES dans le contrôleur de loging.
En effet, la méthode qui vérifie son état est appelée trop tôt dans mon code de la classe principale. En fait, elle doit être appelée pendant que le code de URLCONNECTION s'éxecute dans un autre thread en parallèle je pense...?
Du coup, ma classe principale ne voit pas le BOOL à YES.
J'ai donc pensé (de mémoire) à utiliser le NotificationCenter qui pourrait poster une notification depuis ma méthode delegate et observer ça dans la classe principale. Je crois aussi de mémoire qu'il est gourmand en mémoire le notificationCenter...
Bon, en fait, je voulais savoir si c'était une bonne façon de faire.
Merci.
1) Les notifications
2) Les delegates
Sachant qu'il n'est pas rare non plus que dans les frameworks Apple on trouve les 2 combinés, ou une méthode de delegate qui par défaut si non implémentée émet une notification par exemple.
Perso je ne suis pas gros utilisateur des NSNotifications, je trouve plus joli le paradigme delegate. Rien ne t'empêche donc de te créer ton propre delegate, je fais ça souvent pour ma part, et en plus avec des protocoles formels (j'aime pas les protocoles informels, en plus c'est has-been ça a été créé juste parce qu'à l'époque y'avait pas les mots clés @optional, mais maintenant que ça existe en Obj-C 2, j'utilise que des protocoles formels c'est 100x plus propre)
En gros ça donne qqch comme ça :
1) Pour ta classe URLLoggerController
2) Puis dans la classe qui instancie ton URLLoggerController :
J'ai ajouté mon protocole, mon objet delegate, et ma méthode delegate.
Cela me paraà®t plus "objet" que la notification.
Juste une chose :
J'ai dû viré les signatures de "id delegate" avec le protocole dans le .h de URLLoggerController. En effet, je n'ai pas trouvé d'astuce me permettant de décrire le protocole avant @interface, car dans ce cas-là il ne trouve pas la classe URLLoggerController qui est déclarée après... et qui est utilisée dans la déclaration de la méthode du protocole.
Donc j'ai déclaré le protocole après @interface, ce qui donne au final :
Note bien, que j'ai dû virer <URLLoggerControllerDelegate> après "id" puisqu'il ne le trouve pas avant...
Il suffit (astuce que tu ne semblais pas connaà®tre donc ) de rajouter ceci juste avant de déclarer le @protocol URLLoggerControllerDelegate : et du coup tu pourras remettre la déclaration du @protocol avant la déclaration de @interface URLLoggerController... et donc remettre les déclarations du delegate avec id<URLLoggerControllerDelegate> et non plus juste "id".
Bon en fait j'ai fait exprès de pas le mettre de suite ce @class, pour que tu réalises l'erreur et comprenne mieux du coup l'intérêt et l'astuce de le rajouter... (comment ça c'est pas crédible ? )
J'avais déjà vu ce @class fût un temps, mais je ne me souvenais pas de sa fonction par rapport à un #import.
En tout cas, merci.
Sinon, je vais p-e passer sur une requête synchrone, ça paraà®t plus logique pour un logging. Puisque de toute façon, je ne peux pas faire le reste sans être logué. N'est-ce pas ?
Heu ceci dit l'inconvénient d'une requête synchrone c'est qu'elle te bloque ton interface le temps de l'accès au réseau etc... donc pas si intéressant que ça.
De toute façon c'est plutôt à la partie interface de gérer cette partie "je peux rien faire tant que je suis pas loggué", désactivant des contrôles tant que tu ne t'es pas logué, par exemple...
Donc moi je garderai l'aspect asynchrone du logging, qui peut te permettre par exemple d'afficher une roue qui tourne pour montrer l'activité (...hum... ) en attendant que le site te réponde si le logging a marché ou pas. Quitte quand tu veux faire une requête à ton site pour laquelle tu sais que tu as besoin d'une connection, si isConnected=NO alors tu mémorises la requête dans une variable d'instance tampon, et tu demandes le logging... et une fois le logging effectué avec susscès, tu lances ta requête mémorisée dans ton ivar tampon pour l'exécuter automatiquement après le logging, enfin ce genre d'astuce quoi.
Allé au boulot !
Pour la roue qui tourne, c'est déjà fait. ;-)