Définition et utilisation des en-têtes SOAP

De RAD Studio
Aller à : navigation, rechercher

Remonter à Utilisation de services Web - Index

Le codage SOAP d'une requête en direction de votre application de service Web et de la réponse de celle-ci comprend un ensemble de noeuds d'en-tête. Certains d'entre eux, tels que l'en-tête SOAP Action, sont générés et interprétés automatiquement. Toutefois, vous pouvez également définir vos propres en-têtes pour personnaliser la communication entre votre serveur et ses clients. Généralement, ces en-têtes contiennent des informations associées à l'ensemble de l'interface invocable ou même à l'ensemble de l'application, plutôt que seulement à la méthode qui fait l'objet d'un message particulier.

Pour chaque en-tête à définir, créez un descendant de Soap.InvokeRegistry.TSOAPHeader. TSOAPHeader est un descendant de TRemotable. Par conséquent, les objets d'en-tête SOAP sont simplement des types particuliers d'objets distants. Comme dans le cas de n'importe quel objet distant, vous pouvez ajouter des propriétés publiées à votre descendant de TSOAPHeader pour représenter les informations communiquées par votre en-tête. Après avoir défini une classe d'en-tête SOAP, vous devez la recenser dans le registre des types distants. Notez qu'à la différence des autres classes distantes, qui sont recensées automatiquement lorsque vous recensez une interface invocable qui les utilise, vous devez explicitement écrire du code pour recenser vos types d'en-têtes.

Définition de classes d'en-têtes

TSOAPHeader définit deux propriétés qui permettent de représenter les attributs du noeud d'en-tête SOAP. Ce sont MustUnderstand et Actor. Lorsque l'attribut MustUnderstand a pour valeur True, le destinataire d'un message qui comprend l'en-tête doit le reconnaître. Si le destinataire ne peut pas interpréter un en-tête possédant l'attribut MustUnderstand, il doit annuler l'interprétation de l'ensemble du message. Une application peut ignorer sans risque les en-têtes qu'elle ne reconnaît pas si leur attribut MustUnderstand n'est pas défini. L'utilisation de MustUnderstand est qualifiée par la propriété Actor. Actor représente une URI qui identifie l'application destinataire de l'en-tête. Par conséquent, si votre application de service Web transfère les requêtes à un autre service afin qu'elles subissent un traitement complémentaire, certains des en-têtes des messages client peuvent être aiguillés vers cet autre service. Si ces en-têtes comprennent l'attribut MustUnderstand, vous ne devez pas annuler la requête même si votre application ne comprend pas l'en-tête. Votre application est uniquement concernée par ces en-têtes qui fournissent son URL en guise de paramètre Actor.

Une fois que vous avez défini et recensé les classes d'en-têtes, votre application peut les utiliser. Lorsque votre application reçoit une requête, les en-têtes de ce message sont automatiquement convertis dans les descendants de TSOAPHeader correspondants que vous avez définis. Votre application identifie la classe d'en-tête appropriée en établissant une correspondance entre le nom du noeud d'en-tête et le nom de type que vous avez utilisé lors du recensement de la classe ou un nom que vous fournissez en recensant la classe d'en-tête avec le registre d'invocation. Tous les en-têtes pour lesquels l'application ne trouve pas de correspondance dans le registre des types distants sont ignorés (ou, si leur attribut MustUnderstand a pour valeur True, l'application génère une erreur SOAP).

Envoi et réception d'en-têtes

Vous pouvez accéder aux en-têtes que votre application reçoit par le biais de l'interface Soap.InvokeRegistry.ISOAPHeaders. Vous pouvez obtenir cette interface de deux façons : à partir d'une instance de TInvokableClass ou, si vous implémentez votre interface invocable sans utiliser TInvokableClass, en appelant la fonction globale GetSOAPHeaders.

Utilisez la méthode Get de ISOAPHeaders pour accéder aux en-têtes d'après leur nom. Par exemple :


TServiceImpl.GetQuote(Symbol: string): Double;
var
  Headers: ISOAPHeaders;
  H: TAuthHeader;
begin
  Headers := Self as ISOAPHeaders;
  Headers.Get(AuthHeader, TSOAPHeader(H)); { Retrieve the authentication header }
  try
    if H = nil then
      raise ERemotableException.Create("SOAP header for authentication required");
    { code here to check name and password }
  finally
    H.Free;
  end;
  { now that user is authenticated, look up and return quote }
end;

Si vous souhaitez inclure tous les en-têtes dans la réponse de votre application à un message de requête, vous pouvez utiliser la même interface. ISOAPHeaders définit une méthode Send pour ajouter les en-têtes dans la réponse sortante. Il vous suffit de créer une instance de chaque classe d'en-tête qui corresponde à un en-tête à envoyer, de définir ses propriétés et d'appeler Send :

TServiceImpl.GetQuote(Symbol: string): Double;
var
  Headers: ISOAPHeaders;
  H: TQuoteDelay;
  TXSDuration Delay;
begin
  Headers := Self as ISOAPHeaders;
  { code to lookup the quote and set the return value }
  { this code sets the Delay variable to the time delay on the quote }
  H := TQuoteDelay.Create;
  H.Delay := Delay;
  Headers.OwnsSentHeaders := True;
  Headers.Send(H);
end;

Gestion des en-têtes de types scalaires

Certains services Web définissent et utilisent des en-têtes qui sont des types simples (comme entier ou chaîne) au lieu d'une structure complexe correspondant à un type distant. Toutefois, la prise en charge par Delphi des en-têtes SOAP nécessite que vous utilisiez un descendant de TSOAPHeader pour représenter les types d'en-têtes. Vous pouvez définir des classes d'en-têtes pour les types simples en traitant la classe TSOAPHeader comme une classe holder. C'est-à-dire que le descendant de TSOAPHeader possède une propriété publiée unique qui est le type de l'en-tête réel. Pour signaler que la représentation SOAP n'a pas besoin d'inclure un noeud pour le descendant de TSOAPHeader, appelez la méthode RegisterSerializeOptions du registre de types distants (après avoir recensé le type d'en-tête) et attribuez à votre type d'en-tête une option xoSimpleTypeWrapper.


Communication de la structure de vos en-têtes aux autres applications

Si votre application définit des en-têtes, vous devez permettre à ses clients d'accéder à ces définitions. Si ces clients sont également écrits en Delphi, vous pouvez partager l'unité qui définit et recense vos classes d'en-têtes avec l'application client. Toutefois, vous pouvez également permettre aux autres clients de connaître les en-têtes que vous utilisez. Pour permettre à votre application d'exporter les informations sur ses classes d'en-têtes, vous devez recenser celles-ci dans le registre d'invocation. Le recensement d'une classe d'en-tête associe aussi cette classe à un nom d'en-tête défini dans un espace de nommage.

A l'image du code qui recense votre interface invocable, le code qui recense une classe d'en-tête à exporter est ajouté à la section initialization de l'unité de sa définition. Utilisez la fonction globale InvRegistry pour obtenir une référence au registre d'invocation et appeler sa méthode RegisterHeaderClass en indiquant l'interface à laquelle l'en-tête est associé :


initialization
  InvRegistry.RegisterInterface(TypeInfo(IMyWebService)); {register the interface}
  InvRegistry.RegisterHeaderClass(TypeInfo(IMyWebService), TMyHeaderClass); {and the header}
end.
static void RegTypes()
{
  // register the invokable interface:
  InvRegistry()->RegisterInterface(__delphirtti(IMyService), "", "");
// register the header to be used with it:
  InvRegistry()->RegisterHeaderClass(__delphirtti(IMyService), __classid(TMyHeader));
}
#pragma startup RegTypes 32

Vous pouvez limiter l'en-tête à un sous-ensemble des méthodes de l'interface par des appels suivants à la méthode RegisterHeaderMethod.

Remarque :  La clause uses de la section implémentation doit comprendre l'unité InvokeRegistry afin que l'appel de la fonction InvRegistry soit défini.

Une fois que vous avez recensé votre classe d'en-tête avec le registre d'invocation, sa description est ajoutée aux documents WSDL lorsque vous publiez votre service Web.


Remarque :  Ce recensement de votre classe d'en-tête avec le registre d'invocation s'ajoute au recensement de cette classe avec le registre des types distants.

Voir aussi