Magazine Internet

PHP : Créer un client HTTP

Publié le 25 juillet 2009 par Methylbro

PHP : Créer un client HTTPMaintenant que vous connaissez les principes de base du protocole HTTP, nous allons pouvoir nous pencher ensemble sur la création d'un petit client HTTP directement écris en PHP.

En effet, comme nous l'avons déjà vu dans un des billets traitant de la fonction mail() et protocole SMTP en PHP il est très facile d'implémenter des petits clients en tout genre grâce aux fonctions réseaux fournies par le langage.

Nous allons donc de nouveau utiliser un socket mais cette fois ci pour nous connecter à un serveur HTTP afin d'y exécuter toute sorte de requêtes.

Comme j'ai pour habitude de manipuler des objets ; nous allons donc créer une nouvelle classe que nous appellerons ClientHTTP.

Les prés requis technique seront bien évidement de pouvoir dialoguer avec notre serveur HTTP. Nous devrons donc dans un premier temps prévoir des méthodes nous permettant de nous connecter à un serveur ; de lui envoyer une requête et de lire le résultat de celle-ci. Nous prévoirons donc les méthodes open(), write() et read().

Ensuite, il faudra proposer une méthode qui servira d'interface pour l'exécution d'une nouvelle requête. C'est la méthode request() qui jouera ce rôle.

Voici donc à quoi devrait ressembler notre petite classe ClientHTTP :

class ClientHTTP {
private function open() {}
private function write($data) {}
private function read() {}
public function __construct($server_name, $server_port=80) {}
public function request($method, $page='/', $headers=null) {}
}

La méthode open()

La première chose que l'on devra faire lors de l'exécution d'une requête HTTP, c'est avant toute chose se connecter au serveur HTTP concerné. Pour ce faire en PHP, nous allons ouvrir un socket vers le serveur cible. C'est le rôle que devra jouer la méthode open().

Nous considérons en revanche que le nom du serveur ainsi que le port à utiliser son des informations au préalablement connues pour la classe (nous verrons plus loin que nous traiterons ces informations lors de l'appel du constructeur).

private function open() {
$this->socket = fsockopen($this->server_name, $this->server_port);
}

Comme vous pouvez le constater ; une fois le socket ouvert, nous stockons la ressource vers le flux concerné dans la propriété $socket de notre classe.

La méthode write()

Maintenant que nous avons les moyens d'établir une connexion ; nous devons nous donner les moyens de communiquer avec le serveur. Pour commencer, voyons comment envoyer des requêtes à destination du serveur. C'est le rôle de la méthode write().

Pour envoyer des informations au serveur, c'est tout simple. Il nous suffit d'écrire dans le flux au préalablement ouvert par la méthode open(). Pour cela, comme pour tout autre flux en PHP, nous utiliserons la fonction fwrite() (ou son alias fputs()).

private function write($data) {
fwrite($this->socket, $data);
}

Le contenu de la requête à destination du serveur est tout simplement à passé dans le paramètre $data ; vous l'aurez bien compris.

La méthode read()

Il ne nous reste plus qu'une problématique technique à résoudre. La lecture des réponses envoyées par le serveur. C'est ce que nous allons voir avec la méthode read().

private function read() {
$result = null;
while(!feof($this->socket)) $result.= fgets($this->socket);
return $result;
}

Dans cette méthode, nous allons lire l'ensemble des lignes que nous retourne le serveur HTTP et les retourner sous la forme d'une chaîne de caractères concaténée. Rien de plus simple encore une fois car en PHP un flux se manipule comme un fichier. Nous pouvons donc faire appel aux fonctions feof() et fgets().

Le Constructeur

Nous avons désormais de quoi résoudre tous les impératifs technique qui vont se poser à nous grâce à ces quelques méthodes. Nous devrons cependant penser à bien ouvrir le socket à destination du serveur HTTP. C'est le rôle que nous allons déléguer au constructeur de notre classe.

public function __construct($server_name, $server_port=80) {
$this->setServerName($server_name)
->setServerPort($server_port)
->open();
}

Je ne vais pas m'attarder sur les méthodes setServerName() et setServerPort() qui sont, vous vous en doutez, de simple accesseurs aux propriétés de classe correspondantes. Pour voir comment les déclarer ; reportez-vous à l'exemple complet joint à ce billet.

La méthode request()

Il ne nous reste désormais plus qu'une seule chose à faire. Préparer notre requête HTTP sous la forme d'une chaîne de caractères et la passer en paramètre à notre méthode write() avant de pouvoir récupérer le résultat retourné par le serveur grâce à la méthode read().

public function request($method, $page='/', $headers=null) {
$this->write($method.' '.$page." HTTP/1.0\r\n" . ((is_array($headers)) ? self::implode_headers($headers)."\r\n\r\n" : "\r\n"));
return $this->read();
}

La méthode statique implode_headers() n'est pas importante en soit. Je ne vais pas m'attarder dessus. Elle transforme juste le tableau $headers contenant les informations à passer dans la requête en une chaîne de caractère répondant aux standards du protocole HTTP. Pour plus de détails, reportez-vous à l'exemple complet joint à ce billet.

Exemple simple d'utilisation

Nous voici donc fin prêt, avec tous les éléments nécessaires pour utiliser notre petit client HTTP écrit en PHP.

Pour tester que tout fonctionne à merveille, nous pouvons commencer par télécharger la page d'accueil du site d'orange, orange.fr :

$test = new ClientHTTP('orange.fr');
echo $test->request('GET');

Ces quelques lignes devrait donc nous retourner le résultat suivant :

HTTP/1.1 200 OK
Date: Mon, 13 Jul 2009 13:14:12 GMT
Server: Apache
Connection: close
Content-Type: text/html

Conclusion

Il va de soit que cette classe n'est qu'un exemple. Un rapide tour d'horizon pour montrer ce qu'il est possible de faire avec PHP. C'est loin d'être un exemple à suivre à la lettre pour l'utiliser au sein d'un script.

Cependant vous pourrez constater au travers de cet exemple qu'un minimum de connaissances et de maîtrise des protocoles les plus courants ne sont pas des atouts inutiles. Bien au contraire ; bien trop souvent méprisés il s'agit des bagages essentiels à tout vrai développeur.


Retour à La Une de Logo Paperblog

A propos de l’auteur


Methylbro 17 partages Voir son blog

l'auteur n'a pas encore renseigné son compte l'auteur n'a pas encore renseigné son compte