1. Protocole HTTP. Introduction
Je voudrais tout de suite clarifier une petite chose. Le terrible mot protocole n'est rien de plus qu'un accord de nombreuses personnes, juste à un moment donné, les gens ont décidé : « Faisons-le ainsi, et alors tout ira bien. Il n’y a rien à craindre, tout est tout simplement scandaleux et nous allons maintenant révéler cette honte. Alors, qu’est-ce que le protocole HTTP et à quoi sert-il ?
1.1 Client et serveur
Il n’y a pas de miracles dans le monde, et surtout dans le monde de la programmation et d’Internet ! Acceptez cela comme une vérité inébranlable. Et si le programme ne fonctionne pas ou ne fonctionne pas comme souhaité, il est fort probable qu'il soit mal écrit ou qu'il contienne des erreurs. Alors, comment le navigateur demande-t-il au serveur de lui envoyer quoi que ce soit ? Oui, très simple ! Vous avez juste besoin de vous détendre un peu et de commencer à profiter du processus :-)
1.2. Écrire notre première requête HTTP
Si vous pensez que tout est trop compliqué, vous vous trompez. L'homme est conçu de telle manière qu'il n'est tout simplement pas capable de créer quelque chose de complexe, sinon il s'y confondra lui-même :-) Donc, il y a un navigateur et il y a un serveur Web. Le navigateur est toujours l'initiateur de l'échange de données. Un serveur Web n'enverra jamais simplement quelque chose à quelqu'un pour qu'il envoie quelque chose au navigateur - le navigateur doit le demander. La requête HTTP la plus simple pourrait ressembler à ceci :
OBTENIR http : //www.php.net/ HTTP/1.0rnrn
* GET (traduit de l'anglais signifie « get ») - le type de requête, le type de requête peut être différent, par exemple POST, HEAD, PUT, DELETE (nous en examinerons certains ci-dessous).
* http://www.php.net/ - URI (adresse) à partir de laquelle nous souhaitons recevoir au moins certaines informations (naturellement, nous espérons connaître la page HTML).
* HTTP/1.0 - le type et la version du protocole que nous utiliserons pour communiquer avec le serveur.
* rn - la fin de la ligne, qui doit être répétée deux fois, pourquoi cela deviendra clair un peu plus tard.
Tu peux faire cette demande très simple. Exécutez le programme telnet.exe, entrez www.php.net comme hôte, spécifiez le port 80 et tapez simplement cette demande en appuyant deux fois sur Entrée comme rnrn. En réponse, vous recevrez du code HTML page d'accueil site www.php.net.
1.3 Structure de la demande
Voyons en quoi consiste une requête HTTP. Tout est assez simple. Commençons par le fait qu'une requête HTTP est un texte tout à fait significatif. En quoi cela consiste-t-il dans le cas général ? Nous considérerons le protocole HTTP 1.0. Donc :
Ligne de demande [Général - En-tête | Demande - En-tête | Entité - En-tête ] rn [ Entité - Corps ]
* Request-Line - ligne de demande
*
Format : "Méthode Request-URI HTTP-Versionrn"
* Méthode - la méthode par laquelle la ressource Request-URI sera traitée peut être GET, POST, PUT, DELETE ou HEAD.
* Request-URI - relatif ou référence absolue vers une page avec un ensemble de paramètres, par exemple /index.html ou http://www.myhost.ru/index.html ou /index.html?a=1&b=qq. Dans ce dernier cas, le serveur recevra une requête avec un ensemble de variables a et b avec les valeurs correspondantes, et le signe « & » - une esperluette - sert de séparateur entre les paramètres.
* HTTP-Version - version du protocole HTTP, dans notre cas "HTTP/1.0".
Nous sommes extrêmement intéressés par les méthodes de traitement GET et POST. Avec la méthode GET, vous pouvez simplement transmettre des paramètres au script, et avec la méthode POST, vous pouvez émuler la soumission d'un formulaire.
Pour la méthode GET, l'URI de requête peut ressembler à ceci : "/index.html?param1=1¶m2=2".
* General-Header - la partie principale de l'en-tête.
Format:
Ne peut avoir que deux paramètres : Date ou Pragma. Date - Date de Greenwich au format « Jour de la semaine, Jour Mois Année HH:MM:SS GMT », par exemple « Mar 15 novembre 1994 08:12:31 GMT » - date de création de la demande. Pragma peut avoir une seule valeur sans cache, ce qui désactive la mise en cache des pages.
* Request-Header - partie de l'en-tête qui décrit la demande.
Request-Header peut avoir les paramètres suivants : Autoriser, Autorisation, De, Si-Modifié-Depuis, Référent, Agent Utilisateur.
Dans ce chapitre, nous ne considérerons pas le paramètre Authorization, car il est utilisé pour accéder à des ressources privées, ce qui n'est pas très souvent nécessaire. Vous pouvez apprendre à créer vous-même un en-tête d'accès autorisé sur www.w3c.org.
* Autoriser - définit les méthodes de traitement acceptables.
Format : "Autoriser : GET | HEADn".
Le paramètre est ignoré lors de la spécification de la méthode de traitement POST dans Request-Line. Spécifie les méthodes de traitement des demandes acceptables. Les serveurs proxy ne modifient pas le paramètre Allow et celui-ci atteint le serveur inchangé.
* Depuis - adresse e-mail qui a envoyé la demande.
Format : "De : adderssrn".
Par exemple, « De : [email protégé]".
* If-Modified-Since - indique que la requête n'a pas été modifiée depuis tel ou tel moment.
Format : « Si-Modifié-Depuis : datern »
Utilisé uniquement pour la méthode de traitement GET. La date est spécifiée en GMT dans le même format que pour le paramètre Date dans le General-Header.
* Référent - un lien absolu vers la page à partir de laquelle la demande a été initiée, c'est-à-dire un lien vers la page à partir de laquelle l'utilisateur est arrivé sur la nôtre.
Format : "Référent : URL".
Exemple : « Référent : www.host.ru/index.htmln ».
* Agent utilisateur - type de navigateur.
Par exemple : « Agent utilisateur : Mozilla/4.0n »
* Entity-Header - partie de l'en-tête qui décrit les données Entity-Body.
Cette partie de la requête spécifie les paramètres qui décrivent le corps de la page. Entity-Header peut contenir les paramètres suivants : Allow, Content-Encoding, Content-Length, Content-Type, Expires, Last-Modified, extension-header.
* Autoriser - un paramètre similaire à Autoriser de l'en-tête général.
* Content-Encoding - Type d'encodage des données Entité-Corps.
Format : "Encodage de contenu : x-gzip | x-compress | autre type".
Exemple : « Content-Encoding : x-gzipn ». Le caractère "|" désigne le mot « ou », c'est-à-dire ceci ou cela ou cela, etc.
Un autre type peut indiquer comment les données sont codées, par exemple pour la méthode POST : "Content-Encoding: application/x-www-form-urlencodedn".
* Content-Length - le nombre d'octets envoyés à l'Entity-Body. La valeur Content-Length a une signification complètement différente pour les données envoyées au format MIME, où elle agit comme un paramètre pour décrire une partie des données - "externe/entité-corps". Les nombres valides sont des entiers à partir de zéro.
Exemple : « Longueur du contenu : 26457n ».
* Content-Type - type de données transmises.
Par exemple : "Content-Type : text/htmln".
* Expire - Heure à laquelle la page doit être supprimée du cache du navigateur.
Format : « Expire : daté ». Le format de date est le même que celui du paramètre Date de General-Header.
* Dernière modification - heure dernier changement données envoyées.
Format : "Dernière modification : datée". Le format de date est le même que celui du paramètre Date de General-Header.
* Extension-header - partie de l'en-tête, qui peut être destinée, par exemple, à être traitée par un navigateur ou un autre programme qui reçoit le document. Dans cette partie, vous pouvez décrire vos paramètres au format "ParameterName: Parametervaluen". Ces paramètres seront ignorés si le programme client ne sait pas comment les traiter.
Par exemple : « Cookie : r=1rn » - définit les cookies connus pour la page.
Et maintenant, après des paroles aussi terribles, essayons de nous calmer un peu et de comprendre de quoi nous avons besoin ? Naturellement, nous comprendrons avec des exemples.
Imaginons que nous devions obtenir une page du site en passant des cookies, sinon nous serons simplement envoyés comme invités non invités, et de plus, on sait que vous n'êtes autorisé à accéder à cette page qu'après avoir visité la page principale du site.
2 Méthode GET
Écrivons notre demande.
OBTENIR http :
Hébergeur : www. site. courir
Cookie : revenu = 1rn
rn
Cette requête nous indique que nous souhaitons obtenir le contenu de la page http://www.site.ru/news.html en utilisant la méthode GET. Le champ Hôte indique que cette page se trouve sur le serveur www.site.ru, le champ Référent indique que nous sommes venus chercher des nouvelles de la page principale du site, et le champ Cookie indique qu'on nous a attribué tel ou tel cookie. Pourquoi les champs Hôte, Référent et Cookie sont-ils si importants ? Parce que les programmeurs normaux, lors de la création de sites dynamiques, vérifient les champs de données qui apparaissent dans les scripts (y compris PHP) sous forme de variables. À quoi ça sert? Afin, par exemple, d'éviter que le site ne soit cambriolé, c'est-à-dire ils n'ont pas configuré de programme pour le téléchargement automatique, ou pour qu'une personne visitant le site y accède toujours uniquement à partir de la page principale, etc.
Imaginons maintenant que nous devions remplir les champs du formulaire sur la page et envoyer une demande à partir du formulaire, qu'il y ait deux champs dans ce formulaire : login et mot de passe (login et mot de passe) - et, bien sûr, nous connaissons le login et mot de passe.
OBTENIR http : //www.site.ru/news.html?login=Petya%20Vasechkin&password=qq HTTP/1.0rn
Hébergeur : www. site. courir
Référent : http : //www.site.ru/index.htmlrn
Cookie : revenu = 1rn
rn
Notre identifiant est "Petya Vasechkin" Pourquoi devrions-nous écrire Petya%20Vasechkin ? Ceci est dû au fait Symboles spéciaux peuvent être reconnus par le serveur comme des signes de la présence d'un nouveau paramètre ou de la fin d'une requête, etc. Par conséquent, il existe un algorithme pour coder les noms des paramètres et leurs valeurs afin d'éviter les situations d'erreur dans la requête. Description complète Cet algorithme peut être trouvé ici, et PHP possède les fonctions rawurlencode et rawurldecode pour l'encodage et le décodage respectivement. Je voudrais noter que PHP effectue le décodage lui-même si des paramètres codés ont été transmis dans la requête. Ceci conclut le premier chapitre de ma connaissance du protocole HTTP. Dans le prochain chapitre, nous examinerons la création de requêtes comme POST (traduit de l'anglais par « envoyer »), qui sera beaucoup plus intéressante, car exactement ce type request est utilisé lors de l’envoi de données à partir de formulaires HTML.
3. Méthode POST.
Dans le cas d'une requête HTTP POST, il existe deux options pour transférer des champs à partir de formulaires HTML, à savoir l'utilisation des algorithmes application/x-www-form-urlencoded et multipart/form-data. Les différences entre ces algorithmes sont assez significatives. Le fait est que le premier type d'algorithme a été créé il y a longtemps, alors que le langage HTML ne prévoyait pas encore la possibilité de transférer des fichiers via des formulaires HTML. Examinons donc ces algorithmes avec des exemples.
3.1 Type de contenu : application/x-www-form-urlencoded.
Nous écrivons une requête similaire à notre requête GET pour transférer le login et le mot de passe, qui a été abordée dans le chapitre précédent :
POST http : //www.site.ru/news.html HTTP/1.0rn
Hébergeur : www. site. courir
Référent : http : //www.site.ru/index.htmlrn
Cookie : revenu = 1rn
Contenu - Type : application / x - www - formulaire - urlencodedrn
Contenu - Durée : 35mn
rn
Nous voyons ici un exemple d'utilisation des champs d'en-tête Content-Type et Content-Length. Content-Length indique combien d'octets la zone de données occupera, qui est séparée de l'en-tête par un autre saut de ligne rn. Mais les paramètres qui étaient auparavant placés dans le Request-URI pour une requête GET sont désormais dans le Entity-Body. On voit qu'ils se forment exactement de la même manière, il suffit de les écrire après le titre. Je veux souligner encore une chose point important, rien n'empêche, simultanément à l'ensemble des paramètres dans l'Entity-Body, de placer des paramètres avec d'autres noms dans le Request-URI, par exemple :
POST http : //www.site.ru/news.html?type=user HTTP/1.0rn
.....
rn
login = Petya % 20Vasechkin & mot de passe = qq
3.2 Type de contenu : multipart/form-data
Dès que le monde Internet a compris qu'il serait intéressant d'envoyer des fichiers via des formulaires, le consortium W3C s'est mis à affiner le format de requête POST. À cette époque, le format MIME (MultiPurpose Internet Mail Extensions - extensions de protocole multi-usages pour la création Messages électroniques), donc, pour ne pas réinventer la roue, nous avons décidé d'utiliser une partie de ce format de génération de messages pour création d'un POST requêtes dans le protocole HTTP.
Quelles sont les principales différences entre ce format et le type application/x-www-form-urlencoded ?
La principale différence est que l'Entité-Corps peut désormais être divisée en sections séparées par des frontières (limite). Ce qui est le plus intéressant, c'est que chaque section peut avoir son propre en-tête pour décrire les données qui y sont stockées, c'est-à-dire en une seule requête, vous pouvez transférer des données de différents types (comme dans Lettre postale Vous pouvez transférer des fichiers simultanément avec du texte).
Alors, commençons. Reprenons le même exemple avec le transfert du login et du mot de passe, mais maintenant dans un nouveau format.
POST http : //www.site.ru/news.html HTTP/1.0rn
Hébergeur : www. site. courir
Référent : http : //www.site.ru/index.htmlrn
Cookie : revenu = 1rn
Contenu - Durée : 209rn
rn
-- 1BEF0A57BE110FD467Arn
Contenu - Disposition : forme - données ; nom = "login" rn
rn
Petya Vasechkinrn
-- 1BEF0A57BE110FD467Arn
Contenu - Disposition : forme - données ; nom = "mot de passe" rn
rn
qqrn
-- 1BEF0A57BE110FD467A -- rn
Comprenons maintenant ce qui est écrit. :-) J'ai délibérément mis en évidence certains caractères rn en gras afin qu'ils ne se confondent pas avec les données. Si vous regardez attentivement, vous remarquerez le champ limite après Content-Type. Ce champ spécifie le séparateur de section - bordure. Une chaîne composée de lettres et de chiffres latins, ainsi que de quelques autres symboles (malheureusement, je ne me souviens plus lesquels) peut être utilisée comme bordure. Dans le corps de la requête, « -- » est ajouté au début de la limite, et la requête se termine par une limite à laquelle les caractères « -- » sont également ajoutés à la fin. Notre demande comporte deux sections, la première décrit le champ de connexion et la seconde décrit le champ du mot de passe. Content-Disposition (le type de données dans la section) indique qu'il s'agira de données du formulaire et le champ de nom spécifie le nom du champ. C'est là que se termine l'en-tête de section et ce qui suit est la zone de données de section dans laquelle la valeur du champ est placée (pas besoin d'encoder la valeur !).
Je voudrais attirer votre attention sur le fait que vous n'avez pas besoin d'utiliser Content-Length dans les en-têtes de section, mais dans l'en-tête de la requête, vous devriez le faire et sa valeur est la taille de l'intégralité du corps d'entité, qui apparaît après le deuxième rn. Longueur du contenu suivante : 209rn. Ceux. Entity-Body est séparé de l'en-tête par un saut de ligne supplémentaire (qui peut également être vu dans les sections).
Écrivons maintenant une demande de transfert d'un fichier.
POST http : //www.site.ru/postnews.html HTTP/1.0rn
Hébergeur : www. site. courir
Référent : http : //www.site.ru/news.htmlrn
Cookie : revenu = 1rn
Type de contenu : multipart/form-data ; limite = 1BEF0A57BE110FD467Arn
Contenu - Durée : 491rn
rn
-- 1BEF0A57BE110FD467Arn
Contenu - Disposition : forme - données ; nom = "news_header" rn
rn
Exemple d'actualité
-- 1BEF0A57BE110FD467Arn
Contenu - Disposition : forme - données ; nom = "fichier_actualités" ; nom de fichier = "news.txt" rn
Contenu - Type : application / octet - streamrn
Contenu - Transfert - Encodage : binairern
rn
Voici les nouvelles,
qui est dans le fichier d'actualités. txtrn
-- 1BEF0A57BE110FD467A -- rn
DANS dans cet exemple la première section envoie le titre de l'actualité et la deuxième section envoie le fichier news.txt. Si vous êtes attentif, vous verrez les champs nom de fichier et Type de contenu dans la deuxième section. Le champ filename spécifie le nom du fichier envoyé et le champ Content-Type spécifie le type de ce fichier. Application/octet-stream indique qu'il s'agit d'un flux de données standard, et Content-Transfer-Encoding: Binary indique qu'il s'agit de données binaires, non codées d'aucune façon.
Un point très important. La plupart des scripts CGI sont écrits personnes intelligentes, ils aiment donc vérifier le type du fichier entrant, qui est dans Content-Type. Pour quoi? Le plus souvent, le téléchargement de fichiers sur des sites Web est utilisé pour recevoir des images du visiteur. Ainsi, le navigateur lui-même essaie de déterminer le type de fichier que le visiteur souhaite envoyer et insère le Content-Type approprié dans la requête. Le script le vérifie à réception, et, par exemple, s'il ne s'agit pas d'un gif ou d'un jpeg, il l'ignore ce fichier. Par conséquent, lors de la création d'une requête « manuellement », veillez à ce que la valeur Content-Type soit la plus proche du format du fichier transféré.
Image/gif pour gif
image/jpeg pour jpeg
image/png pour png
image/tiff pour tiff (qui est extrêmement rarement utilisé, le format est trop volumineux)
Dans notre exemple, une requête est générée dans laquelle fichier texte. Une demande de transfert d'un fichier binaire est générée de la même manière.
4. Post-scriptum.
Je pense que cela ne vaut pas la peine de parler en détail de l'envoi de requêtes au serveur. Il s'agit de pure technologie RHP :-). Il suffit de lire attentivement la section sur les fonctions permettant de travailler avec les sockets, ou sur les fonctions du module CURL dans la documentation officielle PHP.
D’après ce qui précède, j’espère que la raison de la question est désormais claire : « Comment puis-je générer une requête POST à l’aide de la fonction d’en-tête ? » - sans signification. La fonction header(string) ajoute une entrée uniquement à l’en-tête de la requête, mais pas au corps de la requête.
Dos |