Section courante

A propos

Section administrative du site

ISAPI

Une application ISAPI est une DLL pour Windows NT. Le but principal de ISAPI est de fournir une interface alternative au CGI (Common Gateway Interface) plus couramment utilisé. Une application CGI est une application externe s'exécutant dans un processus distinct du serveur Web et est couramment utilisée pour fournir des services non fournis par le serveur HTTP (ou Web) ou définis par la spécification HTML. Vous pouvez utiliser une application CGI pour s'interfacer avec une base de données SQL Server, pour enregistrer des données à partir d'un formulaire HTML ou même pour insérer un compteur sur votre pager Web (comme les compteurs d'accès sur de nombreuses pages Web).

Étant donné que les applications CGI existent depuis plus longtemps, vous vous demandez peut-être pourquoi vous avez besoin (ou devriez vous soucier) d'une autre méthodologie pour fournir des fonctionnalités similaires. Vous vous demandez probablement quelle est la différence entre ISAPI et CGI. Après tout, les deux étendent les capacités de votre serveur Web en créant des extensions personnalisées, et les deux vous permettent d'écrire des extensions à l'aide de votre compilateur C ou C++ préféré. Eh bien, la principale différence entre ces deux interfaces peut se résumer en un mot : la performance !

Une application CGI versus une application ISAPI

Une application CGI s'exécute en tant que processus distinct. Cette situation signifie qu'à chaque fois que l'application est appelée, elle doit être chargée en mémoire, passée les paramètres client et exécutée. Ensuite, il doit renvoyer les données client au serveur HTTP. Si l'application est appelée plusieurs fois par différents clients simultanément, plusieurs copies de l'application résideront en mémoire en même temps, ce qui consomme des ressources système. Une application ISAPI, cependant, est assez différente d'une application CGI :

Quelques considérations relatives aux applications ISAPI

Bien qu'une bibliothèque de liens dynamiques ait ses avantages, elle présente également un inconvénient que vous devez prendre en compte : étant donné qu'une bibliothèque de liens dynamiques s'exécute dans le même espace d'adressage que l'application parente, une bibliothèque de liens dynamiques errante (telle que celle faisant référence à la mémoire sans discernement) peut provoquer l'échec de l'application parente ! Cette situation signifie qu'une application ISAPI mal écrite peut provoquer l'étouffement, le plantage et la mort cruelle et anormale de votre serveur Web. Vous devez vous préparer à l'éventualité en suivant ces suggestions :

L'interface ISAPI de base

Si vous avez effectué un développement Windows ou Windows NT, vous êtes peut-être déjà au courant de la multitude d'interfaces (ou des exigences pour implémenter une fonction souhaitée) définies par l'API de Windows ou de Windows NT. Une application ISAPI, aussi communément appelée ISA (Internet Server Application), n'est pas différente. Il nécessite également que vous utilisiez une interface spécifique. La première partie de cette interface, qui est facultative, est que l'application doit prendre en charge la définition de base d'une dynamique d'une bibliothèque de liens dynamiques. Par conséquent, il peut inclure une fonction appelée DLLMain étant appelée lorsque l'application est chargée ou déchargée par le système d'exploitation (Windows Server). Cette fonction fournit une initialisation et un nettoyage ISA spécifiques.

Une fois l'application chargée en mémoire, le serveur HTTP appelle la fonction GetExtensionVersion pour obtenir des informations spécifiques à la version. Si le numéro de version est acceptable, le serveur HTTP appelle ensuite la fonction HttpExtensionProc chaque fois qu'un client effectue une demande nécessitant cette ISA. Normalement, cette demande client est exécutée chaque fois qu'un client sélectionne une URL sous la forme de :

http:\\www.mondomaine.com/scripts/NomExtension.DLL?parametre

Vous pouvez remplacer respectivement votre propre nom de domaine, nom ISA et paramètres pour les valeurs DomainName, NomExtension.DLL et parametre dans l'URL. Par exemple, votre URL peut apparaître comme ceci :

http://www.gladir.com/scripts/sequelle?PasDeFonction

Pour vous donner une meilleure idée de cette interface requise, voici un schéma de l'architecture de base ISA :

Comme vous pouvez le voir dans le schéma précédent, il y a un espace d'adressage dans le serveur HTTP et l'application serveur Internet s'exécute. Le serveur HTTP communique avec l'ISA à l'aide d'un bloc de contrôle d'extension (ECB). Un pointeur vers l'ECB est passé à la fonction HttpExtensionProc chaque fois qu'un client effectue une demande. Il appartient à la fonction HttpExtensionProc d'analyser la structure ECB et de déterminer la demande du client et d'effectuer le traitement approprié. La fonction HttpExtensionProc est similaire à la fonction principale d'une application C utilisée comme extension CGI, mais au lieu de recevoir son entrée en utilisant stdin, comme le fait une application C, le stdout pour renvoyer les données traitées au client, la fonction HttpExtensionProc utilise les fonctions WriteClient ou ServerSupportFunction. Dans la fonction HttpExtensionProc, vous pouvez utiliser n'importe quelle API de Win32. Il fournit un moyen d'étendre le serveur HTTP pour effectuer presque toutes les tâches. Le Microsoft dbWeb, par exemple, est une application ISAPI. Le Microsoft dbWeb est utilisé pour fournir une interface ODBC au serveur HTTP afin que vos clients puissent insérer, supprimer, mettre à jour ou interroger vos bases de données compatibles ODBC à l'aide de leur navigateur Web. Voici les six fonctions définies pour un ISA :

Nom Description
GetExtensionVersion Cette fonction permet de fournir des informations spécifiques à la version au serveur HTTP.
HttpExtensionProc Cette fonction permet d'effectuer le vrai travail de l'extension ISA.
GetServerVariable Cette fonction permet de fournir un accès aux variables d'environnement prédéfinies.
ReadClient Cette fonction permet de demander des données supplémentaires du client lorsque le tampon de données ECB ne peut pas contenir toutes les données.
WriteClient Cette fonction permet de renvoyer les données au client.
ServerSupportFunction Cette fonction permet de fournir des fonctions générales ainsi que des fonctions spécifiques au serveur HTTP à l'ISA.

La fonction GetExtensionVersion

La fonction GetExtensionVersion informe le serveur HTTP de l'adéquation de l'extension. En substance, lorsque la fonction est appelée par le serveur HTTP, elle est passée sous la forme d'un pointeur vers une structure HSE_VERSION_INFO. Cette structure contient les versions majeures et mineures du serveur HTTP que l'extension prend en charge, ainsi qu'une description textuelle de l'extension de serveur. L'ISA doit remplir la structure HSE_VERSION_INFO avec ces informations de version lorsqu'il est appelé par le serveur HTTP. La fonction est utilisée pour empêcher un ISA obsolète d'être chargé sur un serveur HTTP non compatible. La syntaxe de fonction est la suivante :

BOOL WINAPI GetExtensionVersion(HSE_VERSION_INFO *pVer);

La structure HSE_VERSION_INFO dans httpext.h est définit selon la syntaxe suivante :

typedef struct _HSE_VERSION_INFO {
   DWORD struct dwExtensionVersion;
   CHAR lpszExtensionDesc[HSE_MAX_EXT_DLL_NAME_LEN];
} HSE_VERSION_INFO, *LPHSE_VERSION_INFO";

La définition HSE_MAX_EXT_DLL_NAME_LEN est définie sur une valeur de 256 caractères, ce qui vous fournit un espace de nom de 255 caractères car vous devez laisser de la place pour le terminateur nul de la chaîne de caractères. Lorsque cette fonction est appelée, elle doit remplir la structure HSE_VERSION_INFO et retourner TRUE (1) en cas de succès ou FALSE (0) en cas d'échec. L'élément dwExtensionVersion peut être rempli à l'aide des macros HIWORD et LOWORD. Le numéro de version majeur est contenu dans le mot bas de l'élément dwExtensionVersion.

La fonction HttpExtensionProc

Chaque fois que le client (le navigateur Web) effectue une requête nécessitant l'ISA, la fonction HttpExtensionProc de l'ISA est appelée et transmet un pointeur vers une structure ECB. La structure ECB est définie dans l'entête HTTPEXT.H comme EXTENSION_CONTROL_BLOCK et a les éléments résumés dans le tableau suivant la syntaxe. La syntaxe de la fonction HttpExtensionProc est la suivante :

DWORD WINAPI HttpExtensionProc(EXTENSION_CONTROL_BLOCK *pEcb);

Voici les différents champs de la structure EXTENSION_CONTROL_BLOCK :

Champ Type Flux Description
cbSize DWORD Entrée Ce champ permet d'indiquer la taille d'une structure ECB.
dwVersion DWORD Entrée Ce champ permet d'indiquer le numéro de version IIS pris en charge par cette extension. Le numéro de version majeure est contenu dans le mot haut et le numéro de version mineure est contenu dans le mot bas. Vous pouvez utiliser les macros HIWORD et LOWORD pour obtenir les numéros de version majeure et mineure.
ConnID HCONN Entrée Ce champ permet d'indiquer un numéro unique attribué par le serveur HTTP. Ce numéro ne doit pas être modifié.
dwHttpStatusCode DWORD Sortie Ce champ permet d'indiquer l'état de la transaction terminée en cours à renvoyer au serveur HTTP.
lpszLogData CHAR Sortie Ce champ permet d'indiquer une chaîne de caractères terminée par un zéro de HSE_LOG_BUFFER_LEN (actuellement définie comme 80 caractères) à insérer dans le journal du serveur HTTP.
lpszMethod LPSTR Entrée Ce champ permet d'indiquer une chaîne de caractères terminée par null contenant la méthode utilisée par le client pour cette transaction. Il s'agit de la même valeur que la variable REQUEST_METHOD de CGI.
lpszQueryString LPSTR Entrée Ce champ permet d'indiquer une chaîne de caractères terminée par un caractère nul contenant les informations de la requête. C'est la même chose que la variable QUERY_STRING de CGI.
lpszPathInfo LPSTR Entrée Ce champ permet d'indiquer une chaîne de caractères à terminaison nulle, contenant les informations de chemin supplémentaires fournies au client. C'est la même chose que la variable PATH_INFO de CGI.
lpszPathTranslated LPSTR Entrée Ce champ permet d'indiquer une chaîne de caractères terminée par un caractère nul contenant le chemin traduit. C'est la même chose que la variable PATH_TRANSLATED de CGI.
cbTotalBytes DWORD Entrée Ce champ permet d'indiquer le nombre total d'octets reçus du client. C'est la même chose pour la variable CONTENT_LENGTH de CGI.
cbAvailable DWORD Entrée Ce champ permet d'indiquer le nombre d'octets disponibles, sur le total défini par cbTotalBytes, contenu dans la mémoire tampon pointée par lpdData.
lpbData LPBYTE Entrée Ce champ permet d'indiquer un pointeur vers un tampon, de taille cbAvailable, contenant les données envoyées par le client.
lpszContentType LPSTR Entrée Ce champ permet d'indiquer une chaîne de caractères terminée par un nul contenant le type de données envoyées par le client. C'est la même chose que la variable CONTENT_TYPE de CGI.

Il appartient à la fonction HttpExtensionProc d'analyser le ECB pour déterminer ce que le client demande. Ces informations seront contenues dans l'élément ECB de lpszQueryString. Toutes les données supplémentaires seront contenues dans le tampon pointé par l'élément lpdData. Si la mémoire tampon est trop petite pour contenir toutes les données telles que définies par l'élément cbTotalBytes, la fonction HttpExtensionProc peut récupérer les données supplémentaires à l'aide de la fonction ReadClient. Lorsque le HttpExtensionProc a terminé son traitement, il doit envoyer les données résultantes (au format HTML) au client à l'aide de la fonction WriteClient ou ServerSupportFunction. Il doit renvoyer un code d'état au serveur HTTP à la fin. L'état peut être l'un des suivants :

Constante Description
HSE_STATUS_SUCCESS Le code d'état spécifie que l'ISA a terminé sa tâche avec succès et que le serveur HTTP peut se déconnecter et libérer des ressources système en déchargeant l'ISA.
HSE_STATUS_SUCCESS_AND_KEEP_CONN Ce code d'état spécifie que l'ISA a terminé sa tâche, mais que le serveur HTTP doit garder l'ISA actif en mémoire si le client prend en charge les connexions persistantes. Le code d'état HSE_STATUS_SUCCESS_AND_KEEP_CONN ne doit être utilisé que si l'ISA a envoyé un entête keep-alive au client.
HSE_STATUS_PENDING Le code d'état spécifie que l'ISA a mis la demande en file d'attente pour traitement et qu'il informera le serveur HTTP lorsque la demande sera terminée à l'aide de ServerSupportFunction avec le paramètre dwHSERequest défini sur HSE_REQ_DONE_WITH_SESSION.
HSE_STATUS_ERROR Ce code d'état spécifie que l'ISA a rencontré une erreur en essayant de terminer sa tâche et que le serveur HTTP peut se déconnecter et libérer des ressources système en téléversant l'ISA.

La fonction GetServerVariable

La fonction GetServerVariable obtient des informations sur la connexion ou des informations sur le serveur HTTP. La fonction est définie comme suit :

BOOL WINAPI GetServerVariable(HCONN hConn, LPSTR lpszVariableName, LPVOID lpvBuffer, LPDWORD lpdwSizeofBuffer);

Les paramètres de la fonction sont définis comme suit :

Nom Description
hConn Ce paramètre permet d'indiquer la connexion à identificateur de descripteur Handle.
lpszVariableName Ce paramètre permet d'indiquer le nom de la variable CGI souhaitée :
Nom Description
ALL_HTTP Ce nom de variable permet d'indiquer tous les entêtes HTTP n'étant pas analysés dans l'une des autres variables répertoriées dans ce tableau.
AUTH_PASS Ce nom de variable permet d'indiquer le mot de passe fourni par le client. Le mot de passe sera une chaîne de caractères terminée par un nul.
AUTH_TYPE Ce nom de variable permet d'indiquer le type d'autorisation utilisé. Si l'utilisateur a été authentifié par le serveur, la valeur de retour sera Basic. Sinon, l'entrée ne sera pas présente.
CONTENT_LENGTH Ce nom de variable permet d'indiquer le nombre d'octets que le script peut sauf recevoir du client.
CONTENT_TYPE Ce nom de variable permet d'indiquer le type de contenu des informations fournies dans la requête POST.
GATEWAY_INTERFACE Ce nom de variable permet d'indiquer le niveau de révision de la spécification CGI.
HTTP_ACCEPT Ce nom de variable permet d'indiquer les informations d'entête HTTP à usage spécial.
PATH_INFO Ce nom de variable permet d'indiquer les informations de chemin d'ajout telles que données par le client.
PATH_TRANSLATED Ce nom de variable est identique à PATH_INFO, mais sans traduction de chemin virtuel.
QUERY_STRING Ce nom de variable permet d'indiquer les informations après le «?» dans une requête de script.
REMOTE_ADDR Ce nom de variable permet d'indiquer l'adresse IP du client.
REMOTE_HOST Ce nom de variable permet d'indiquer le nom d'hôte du client.
REMOTE_USER Ce nom de variable permet d'indiquer le nom d'utilisateur fourni par le client et autorisé par le serveur.
REQUEST_METHOD Ce nom de variable permet d'indiquer la méthode de requête HTTP.
SCRIPT_NAME Ce nom de variable permet d'indiquer le nom du script en cours d'exécution.
SERVER_NAME Ce nom de variable permet d'indiquer le nom du serveur (ou l'adresse IP) tel qu'il doit apparaître dans les URL auto-référencées.
SERVER_PORT Ce nom de variable permet d'indiquer le port TCP/IP sur lequel la demande a été reçue.
SERVER_PROTOCOL Ce nom de variable permet d'indiquer le nom et la version de la requête.
SERVER_SOFTWARE Ce nom de variable permet d'indiquer le nom et le numéro de version du serveur Web sous lequel l'extension IIS s'exécutant.
lpvBuffer Ce paramètre permet d'indiquer un pointeur vers un tampon pour contenir les données définies par la variable CGI.
lpdwSizeOfBuffer Ce paramètre permet d'indiquer la taille du tampon vers lequel pointe lpvBuffer. Lorsque la fonction retourne, ce paramètre contient la longueur des données renvoyées, y compris le terminateur nul.

La fonction ReadClient

La fonction ReadClient obtient des données supplémentaires du client lorsque le bloc entier de données ne rentrera pas dans le pointeur de tampon par lpdData dans le bloc ECB. La définition de la fonction a la syntaxe suivante :

BOOL ReadClient(HCONN hConn, LPVOID lpvBuffer, LPDWORD lpdwSize);

Les paramètres de la fonction sont définis comme suit :

Nom Description
hConn Ce paramètre permet d'indiquer l'identificateur de descripteur de connexion.
lpvBuffer Ce paramètre permet d'indiquer un pointeur vers un tampon. Ce tampon sera utilisé pour contenir les données renvoyées par la requête de lecture.
lpdwSizeOfBuffer Ce paramètre permet d'indiquer la taille du tampon vers lequel pointe lpvBuffer. Lorsque la fonction retourne, ce paramètre contient la longueur des données renvoyées.

La fonction WriteClient

La fonction WriteClient envoie des données au client. La définition de la fonction a la syntaxe suivante :

BOOL WriteClient(HCONN hConn, LPVOID lpvBuffer, LPDWORD lpdwSize, DWORD dwReserved);

Les paramètres de la fonction sont définis comme suit :

Nom Description
hConn Ce paramètre permet d'indiquer l'identificateur de descripteur de connexion.
lpvBuffer Ce paramètre permet d'indiquer un pointeur vers un tampon. Ce tampon sera utilisé pour contenir les données envoyées au client. Normalement, ce sera une série de HTML, de balises et de données.
lpdwSizeOfBuffer Ce paramètre permet d'indiquer la taille du tampon vers lequel pointe lpvBuffer. Si une chaîne de caractères terminée par un caractère nul doit être envoyée au client dans son intégralité, cette valeur doit être définie à l'aide de la valeur renvoyée par l'appel de fonction strlen(lpvBuffer). Lorsque la fonction WriteClient retourne, ce paramètre contient la longueur des données envoyées au client.
dwReserved Ce paramètre permet d'indiquer que le paramètre est réservé pour une utilisation future.

La fonction ServerSupportFunction

La fonction ServerSupportFunction renvoie les données à un client de la même manière que la fonction WriteClient. Cependant, il informe également le serveur HTTP de l'état de l'opération que la fonction WriteClient ne peut pas faire. La définition de la fonction a la syntaxe suivante :

BOOL ServerSupportFunction(HCONN hConn, DWORD dwHSERequest, LPVOID lpvBuffer, LPDWORD lpdwSizeOfBuffer, LPDWORD lpdwDataType);

Les paramètres de la fonction sont définis comme suit :

Nom Description
hConn Ce paramètre permet d'indiquer l'identificateur de descripteur de connexion.
dwHSERequest Ce paramètre permet d'indiquer le type de demande à envoyer au client. Il peut s'agir d'un type de demande personnalisé, utilisant une valeur supérieure à celle définie par HSE_REQ_END_RESERVED, ou de l'une des valeurs prédéfinies à usage général suivantes :
Valeur Description
HSE_REQ_SEND_URL_REDIRECT_RESP Ce paramètre permet d'indiquer qu'un message 302 URL redirect doit être envoyé au client. Il revient à spécifier l'URI:URL dans un entête de script CGI. Si cette valeur est utilisée, le lpvBuffer doit pointer vers une chaîne de caractères terminée par null contenant l'URL.
HSE_REQ_SEND_URL Ce paramètre permet d'indiquer que les données associées à une URL soient envoyées au client comme s'il avait explicitement sélectionné l'URL. Le lpvBuffer doit pointer vers une chaîne de caractères terminée par null contenant l'URL.
HSE_REQ_SEND_RESPONSE_HEADER Ce paramètre permet d'indiquer qu'un entête de réponse de serveur HTTP complet doit être envoyé au client. L'application doit ajouter des informations supplémentaires, telles que le type de contenu, la longueur du contenu, un \r\n (paire retour chariot/saut de ligne) et toute autre information supplémentaire.
HSE_REQ_MAP_URL_TO_PATH Ce paramètre permet d'indiquer que le lpdvBuffer contiendra un chemin d'accès logique lorsque le ServerSupportFunction est exécuté, et que le lpdvBuffer aura un chemin d'accès physique correspondant au nom logique à la fin.
lpvBuffer Ce paramètre permet d'indiquer un pointeur vers une mémoire tampon contenant la chaîne de caractères d'état terminée par null (telle que 402-Payment required) à renvoyer au client. Si cette valeur est NULL, le code d'état par défaut (200 OK) sera envoyé au client.
lpdwSizeOfBuffer Ce paramètre permet d'indiquer la taille du tampon vers lequel pointe lpvBuffer. Si une chaîne de caractères terminée par un caractère nul doit être envoyée au client dans son intégralité, cette valeur doit être définie à l'aide de la valeur renvoyée par l'appel de fonction strlen(lpvBuffer). Lorsque la fonction ServerSupportFunction retourne, lpdwSizeOfBuffer contient la longueur des données de l'ensemble envoyées au client.
lpDataType Ce paramètre permet d'indiquer un pointeur vers une chaîne de caractères données terminée par un zéro à ajouter à l'entête. Il s'agit d'une chaîne de caractères facultative, et si ce champ est NULL, l'entête se terminera par un \r\n.


Dernière mise à jour : Jeudi, le 15 avril 2021