Créer un gestionnaire
Envoyer les données des dépôts vers votre propre système. Un gestionnaire est une classe qui hérite de WebhookHandlerBase, compilée dans une DLL que l'application charge au démarrage. Vous n'avez pas à modifier ni à recompiler le webhook.
1. Créer le projet
Une bibliothèque de classes pour la même plateforme que le webhook, qui référence sa bibliothèque SESARWebHook.Core.NetCore et le SDK Secure Exchanges, dans la version qu'utilise le webhook (voir SESARWebHook.Core.NetCore.csproj) :
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net9.0-windows</TargetFramework>
</PropertyGroup>
<ItemGroup>
<!-- Fournis par le webhook à l'exécution : ne pas les copier avec le gestionnaire -->
<ProjectReference Include="..\SESARWebhookCore\SESARWebHook.Core.NetCore\SESARWebHook.Core.NetCore.csproj" Private="false" />
<PackageReference Include="SecureExchanges.NetCore" Version="26.4.20.2" ExcludeAssets="runtime" />
</ItemGroup>
</Project>
2. Écrire la classe
using System.Collections.Generic;
using System.Net.Http;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
using SecureExchangesSDK.Models.Messenging;
using SESARWebHook.Core;
using SESARWebHook.Core.Auth;
using SESARWebHook.Core.Models;
namespace Exemple.Gestionnaires
{
public class DossiersHandler : WebhookHandlerBase
{
// Un seul HttpClient pour toute la vie de l'application.
private static readonly HttpClient Http = new HttpClient();
private ApiKeyHelper _auth;
private string _endpoint;
public override string HandlerId => "mes-dossiers";
public override string DisplayName => "Mes dossiers";
public override void Initialize(Dictionary<string, string> settings)
{
base.Initialize(settings);
_endpoint = GetRequiredSetting("ApiUrl"); // appsettings.json
_auth = ApiKeyHelper.AsBearer(GetRequiredSetting("ApiKey")); // fichier de secrets
}
public override async Task<IntegrationResult> ProcessAsync(StoreManifest manifest, WebhookContext context)
{
var dossier = new
{
suivi = GetTrackingId(manifest), // identifiant stable : sert à écarter les doublons
objet = GetSubject(manifest),
fichiers = GetFileCount(manifest)
};
using var request = new HttpRequestMessage(HttpMethod.Post, _endpoint)
{
Content = new StringContent(JsonSerializer.Serialize(dossier), Encoding.UTF8, "application/json")
};
_auth.ApplyTo(request);
using var response = await Http.SendAsync(request);
return response.IsSuccessStatusCode
? IntegrationResult.Ok("Dossier transmis", HandlerId)
: IntegrationResult.Fail("Refus du système cible", $"HTTP {(int)response.StatusCode}", HandlerId);
}
}
}
Le webhook retient une classe si elle est publique, non abstraite, implémente IWebhookHandler et a un constructeur public sans paramètre. Son HandlerId fait partie de l'adresse : choisissez-le stable, en minuscules, sans espace.
Membres à connaître
| Membre | Rôle |
|---|---|
HandlerId, DisplayName |
Obligatoires. Description et Version sont facultatifs. |
Initialize(settings) |
Appelé une fois, à la première utilisation du gestionnaire. Appelez base.Initialize(settings) en premier. |
ProcessAsync(manifest, context) |
Appelé pour chaque dépôt. Renvoyez IntegrationResult.Ok ou IntegrationResult.Fail. |
ValidateConfigurationAsync, TestConnectionAsync |
Appelés par POST /api/handlers/{id}/test. Renvoient true par défaut. |
GetSetting, GetRequiredSetting, GetSettingBool, GetSettingInt |
Lisent les réglages et les secrets. GetRequiredSetting lève une exception si la valeur manque, sans la citer. |
GetSubject, GetRecipientEmails, GetFileCount, GetTrackingId, IsReply, DecodeBase64 |
Lisent le manifeste. |
La liste complète est dans la référence .NET.
Règles de conception
- Une instance pour toute la vie de l'application. Le gestionnaire est créé une fois, puis réutilisé, y compris pour des requêtes simultanées : ne gardez pas l'état d'un dépôt dans un champ.
- Un constructeur léger. Il s'exécute au chargement de la DLL et à chaque
GET /api/handlers. Mettez la préparation dansInitialize. - Moins de 60 secondes par dépôt, et des doublons acceptés : voir Configurer SESAR.
- Aucun renseignement personnel dans les journaux ni dans l'
IntegrationResult, qui est renvoyé tel quel dans la réponse HTTP. N'utilisez pascontext.RawPayloaden dehors du traitement : il contient le manifeste déchiffré. - Les exceptions levées dans
ProcessAsyncsont interceptées et renvoyées en échec, avec leur détail. Celles d'Initializene le sont pas : la requête reçoit une erreur 500.
3. Configurer
Les réglages vont dans appsettings.json, les secrets dans le fichier de secrets. Le gestionnaire reçoit les deux, fusionnés, dans ses Settings.
{
"Handler": {
"mes-dossiers": { "ApiUrl": "https://api.example.com/dossiers" }
}
}
{
"Handlers": {
"mes-dossiers": { "Secrets": { "ApiKey": "<votre clé d'API>" } }
}
}
4. Déployer
- Compilez le projet en Release.
- Copiez la DLL du gestionnaire, et ses propres dépendances seulement, dans le dossier des gestionnaires :
Handlers, dans le dossier de l'application, ou celui deHandlersPath. Les sous-dossiers ne sont pas lus. - Redémarrez l'application. Une DLL déjà chargée reste en mémoire jusqu'au redémarrage, et
POST /api/handlers/rescanne relit que le dossier par défaut. - Vérifiez qu'il apparaît dans
GET /api/handlers, puis testez-le avecPOST /api/handlers/mes-dossiers/test. - Dans SESAR, indiquez l'adresse
https://<serveur>/api/webhook/handler/mes-dossiers.
Si deux DLL déclarent le même HandlerId, la dernière chargée l'emporte, sans avertissement.
Attention
Un gestionnaire s'exécute dans le processus du webhook, avec tous ses droits, et peut lire tous les secrets de l'application. Ne déposez dans le dossier des gestionnaires que des DLL dont vous connaissez le code, et réservez l'écriture de ce dossier aux administrateurs.
Connecteur intégré : pour qui maintient sa propre version du webhook
Un connecteur intégré implémente IIntegrationConnector. Il n'est pas chargé depuis un dossier : il faut l'ajouter au projet, puis à StartupConfig.InitializeConnectors dans Program.cs (ConnectorRegistry.RegisterConnector<T>()), et recompiler le webhook. Le projet SESARWebHook.Connectors.Template.NetCore sert de modèle ; ses commentaires mentionnent encore Web.config, remplacé par appsettings.json.
Préférez un gestionnaire : il survit aux mises à jour du webhook sans fusion de code.