Requete/Reponse HTTP

NigokiNigoki Membre
00:00 modifié dans API UIKit #1
Hello  <3 <br />
J'ai besoin de développer des mini webservices vers des scripts php sur un serveur web.

Doc d'apple en main, je suis les exemples que l'on peut trouver ici

J'ai du ajouter à  mon projet les framework CoreServices et CoreFoundation, et voici mon code résultant :

<br />+(void)createAccount {<br /><br />	NSString *uniqueIdentifier = [Tools uniqueIdentifier];<br />	NSString *inital_credit = @&quot;200&quot;;<br />	Account *acc = [[Account alloc] initWithFile];<br />	<br />	<br />	NSString *url2 = [[NSString alloc] initWithFormat:@&quot;http://XXX.XX.com/createaccount.php?phonenumber=%@&amp;password=%@&amp;pseudo=%@&amp;iphoneid=%@&amp;initial_credit=%@&quot;, acc.phone, acc.password, acc.login, uniqueIdentifier, inital_credit];	<br />	<br />NSLog(url2);<br />	CFURLRef urlRef = CFURLCreateWithString(kCFAllocatorDefault, (CFStringRef)url2, NULL);<br />	<br />	CFHTTPMessageRef request = CFHTTPMessageCreateRequest(kCFAllocatorDefault, CFSTR(&quot;GET&quot;), urlRef , kCFHTTPVersion1_1);<br />	<br />	CFReadStreamRef readStream = CFReadStreamCreateForHTTPRequest(kCFAllocatorDefault, request);<br />	CFReadStreamOpen(readStream);<br />	<br />	CFHTTPMessageRef response = CFReadStreamCopyProperty(readStream, kCFStreamPropertyHTTPFinalRequest);<br />	NSLog((NSString *)CFHTTPMessageCopyResponseStatusLine(response));<br />	NSLog((NSString *)CFHTTPMessageGetResponseStatusCode(response));<br />	CFDataRef data = CFHTTPMessageCopyBody(response);<br />	NSLog(@&quot;blob&quot;);<br /><br />	CFReadStreamClose(readStream);<br />	<br />	CFRelease(response);<br />	CFRelease(urlRef);<br />	CFRelease(request);<br />	[acc release];<br />	[url2 release];<br />	NSLog(@&quot;end&quot;);<br />}<br />


Ma console me donne ça :
<br />2009-05-13 17:43:46.159 XX[2310:20b] http://XX.XX.com/createaccount.php?phonenumber=0625684854&amp;password=blob&amp;pseudo=toto28&amp;iphoneid=00000000-0000-1000-8000-001FF3448B6F&amp;initial_credit=200<br />2009-05-13 17:43:46.165 XX[2310:20b] GET /createaccount.php?phonenumber=06256899999&amp;password=blob&amp;pseudo=toto28&amp;iphoneid=00000000-0000-1000-8000-001FF3448B6F&amp;initial_credit=200 HTTP/1.1<br />2009-05-13 17:43:46.166 XX[2310:20b] blob<br />2009-05-13 17:43:46.166 XX[2310:20b] end<br />


Mes problèmes sont les suivants  :why?:
-ça fonctionne pas  :) Je sais meme pas si la requete aboutie (je n'ai pas la main sur les scripts php)
-Je ne sais pas lire un CFDataRef (j'ai essayer bêtement dans le passer dans NSLog mais rien)
-Si je lance la fonction une deuxieme fois, l'appli crache  :adios!:

je tâtonne un max, si vous connaissez une méthodologie sur l'HTTP iphone, je suis preneur !  o:)

Réponses

  • kaseykasey Membre
    00:00 modifié #2
    Heu personnellement j'ai une classe toute faite (et toute simple) pour mes requêtes HTTP :

    CDLSynchrone.h :

    //<br />//&nbsp; CDLSynchrone.h<br />//&nbsp; TestDownloadSynchro<br />//<br />//&nbsp; Created by Kasey on 30/07/08.<br />//&nbsp; Copyright 2008 __MyCompanyName__. All rights reserved.<br />//<br /><br />#import &lt;Cocoa/Cocoa.h&gt;<br /><br />@interface CDLSynchrone : NSObject {<br />	NSString *m_result ;	<br />}<br /><br />-(NSError *)startDownloadWithUrl: (NSString *)url ;<br />-(NSString *)getresult ;<br /><br />@end
    


    CDLSynchrone.m :

    //<br />//&nbsp; CDLSynchrone.m<br />//&nbsp; TestDownloadSynchro<br />//<br />//&nbsp; Created by Kasey on 30/07/08.<br />//&nbsp; Copyright 2008 __MyCompanyName__. All rights reserved.<br />//<br /><br />#import &quot;CDLSynchrone.h&quot;<br /><br />@implementation CDLSynchrone<br /><br />-(NSError *)startDownloadWithUrl: (NSString *)url<br />{<br />	NSURL			*m_url;<br />	NSError			*m_error;<br />&nbsp; &nbsp; NSData			*m_data;<br />	NSURLResponse	*m_response;<br />		<br />	m_url = [NSURL URLWithString:url];<br />	<br />	NSURLRequest *m_request = [NSURLRequest requestWithURL:m_url cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:60.0];<br />	<br />	m_data = [NSURLConnection sendSynchronousRequest:m_request returningResponse:&amp;m_response error:&amp;m_error]; <br />	<br />	NSString *result ;<br />	<br />	result = [[[NSString alloc] initWithData:m_data encoding:NSUTF8StringEncoding] autorelease];<br />	<br />	m_result = result ;<br />	<br />	return m_error ;<br />}<br /><br /><br />-(NSString *)getresult<br />{<br />	return m_result ;<br />}<br />@end<br />
    


    Elle est toute simple et pas optimisée (elle me sers juste a faire des tests) mais si tu l'améliore un peux je pense qu'elle peut te servir de base :)

    J'attend avec plaisir vos remarques sur mon code !!!
  • allianallian Membre
    00:00 modifié #3
    pour le moment j'en ait pas besoin mais je pense que sur la fin de mon app cela me saura utile, je vais continuer à  garder un oe“il sur ce topic 
  • NigokiNigoki Membre
    00:00 modifié #4
    C'est dingue !

    Ca parait tellement facile comme ça, j'ai du louché sur la doc pour avoir trouvé le chapitre des NSReadStream  et pas le tout simple NSURLConnection.

    Merci à  toi kasey  o:)
  • AliGatorAliGator Membre, Modérateur
    00:00 modifié #5
    Pensez à  lire les Programming Guides et pas que les API References !

    Dans l'iPhone Dev Center par exemple, si on va voir dans la iPhone Reference Library et qu'on choisit le topic à  gauche "Networking & Internet", on a tout plein de docs.
    Un sacré paquet de ces docs sont des docs des classes directement, donc si vous savez quelle classe utiliser et cherchez à  connaà®tre son API et ses méthodes, c'est ça qu'il faut aller voir.
    Mais si vous ne savez pas quelles classes utiliser et comment tous ces outils communiquent les uns avec les autres, ou voir des bouts de code d'exemple, il y a aussi !
    Astuce : cliquez sur "Set Filters" dans la page qui affiche les résultats du sujet "Networking and Internet", et dans la partie "Resource Types" ne cochez que ce qui vous intéresse comme type de document (dans ce cas, il est utile de cocher toute la colonne sauf "Reference", donc d'avoir les "Coding HowTo's", les "Getting Started", les "Guides" et les "Sample Code").

    Là  vous aurez facilement accès alors aux documents génériques et guides qui présentent les concepts dans leur ensemble (qu'est ce qu'une requête réseau, une réponse, quelles classes Cocoa se chargent de ça, comment faire telle ou telle tache spécifique, des exemples de code...), c'est donc par ici qu'il faut commencer quand on veut travailler sur un sujet qu'on ne connaà®t pas (soit sur le principe général, soit qu'on n'a encore jamais fait ça avec Cocoa), par exemple les requêtes HTTP ;)
  • AliGatorAliGator Membre, Modérateur
    00:00 modifié #6
    dans 1242250955:
    J'attend avec plaisir vos remarques sur mon code !!!
    Et bien mes petits conseils : le code est correct, mais tu ne suis pas les conventions de nommage utilisés par Apple, et ça déroute.
    1) Pourquoi ne pas directement faire retourner m_result par ta méthode startDownloadWithURL ?
    2) Dans ce cas, tu passes la NSError en paramètre "OUT", comme c'est le cas pour la plupart des méthodes Apple (où l'on passe un pointeur vers une NSError* (donc un NSError**) qui sera rempli par l'erreur le cas échéant)
    3) En plus tu as nommé ton accesseur "getresult" alors que les conventions pour un getter c'est de ne pas utiliser le mot "get" au début, qui n'est utilisé que dans les rares cas où la valeur est retournée par référence via un paramètre, et non en retour de fonction (des méthodes comme "getBuffer:count:" typiquement où tu passes un buffer C en paramètre car c'est à  toi de l'allouer avant d'appeler la méthode qui va te le remplir)


    Je propose donc la modification suivante à  ton code, dis-moi ce que tu en penses  ;)

    CDLSynchrone.h :
    #import &lt;Cocoa/Cocoa.h&gt;<br /><br />@interface CDLSynchrone : NSObject {<br />}<br />-(NSString*)downloadURL:(NSString *)urlString error:(NSError **)error;<br />@end
    


    CDLSynchrone.m :
    #import &quot;CDLSynchrone.h&quot;<br /><br />@implementation CDLSynchrone<br /><br />-(NSString*)downloadURL:(NSString *)urlString error:(NSError **)error<br />{<br />	NSURLRequest* request = [NSURLRequest requestWithURL:[NSURL URLWithString:urlString] cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:60.0];<br />	<br />	NSData* data = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:error]; <br />	<br />	return [[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding] autorelease];<br />}<br />@end<br />
    


    Plus simple, non ?
  • kaseykasey Membre
    00:00 modifié #7
    Oui redoutablement plus simple en effet :)

    Je pense que je vais essayé de m'imposer un peu plus de rigeur... Que ma classe soit destinée a faire quelques tests basiques ou pas les bonnes habitudes sont toujours de mise :)

    Pour ce qui est des questions :
    1) J'ai fait beaucoup de bricolages sur cette classe elle a été modifiée plusieurs fois pour retourner directement un NSData ou une string.
    2) Génial l'implémentation de la gestion d'erreur je suis intéressé par la façon dont tu fait celle-ci
    3) C'est noté. La manie d'utiliser les conventions m_ pour les variables membres et de nommer les fonctions par get et set viens de la façon dont on m'as appris a programmer sous visualc++ en cours.
Connectez-vous ou Inscrivez-vous pour répondre.