Fonctionnalités HTTP

Durable Functions propose plusieurs fonctionnalités pour faciliter l’incorporation d’orchestrations et d’entités durables dans les workflows HTTP. Cet article décrit en détail certaines de ces fonctionnalités.

Exposition des API HTTP

Les orchestrations et les entités peuvent être appelées et gérées à l’aide de requêtes HTTP. L’extension Durable Functions expose les API HTTP intégrées. Elle fournit également des API pour interagir avec les orchestrations et les entités au sein des fonctions déclenchées via HTTP.

API HTTP intégrées

L’extension Durable Functions ajoute automatiquement un ensemble d’API HTTP à l’hôte Azure Functions. Ces API vous permettent d’interagir avec les orchestrations et les entités, ainsi que de les gérer, sans écrire de code.

Les API HTTP intégrées suivantes sont prises en charge.

Consultez l’article sur les API HTTP pour obtenir une description complète de toutes les API HTTP intégrées exposées par l’extension Durable Functions.

Découverte de l’URL de l’API HTTP

La liaison du client d’orchestration expose les API qui peuvent générer des charges utiles de réponse HTTP appropriées. Par exemple, elle peut créer une réponse contenant des liens vers des API de gestion pour une instance d’orchestration spécifique. Les exemples suivants présentent une fonction de déclencheur HTTP qui montre comment utiliser cette API pour une nouvelle instance d’orchestration :

// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the MIT License. See LICENSE in the project root for license information.

using System.Net.Http;
using System.Threading.Tasks;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.DurableTask;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.Extensions.Logging;

namespace VSSample
{
    public static class HttpStart
    {
        [FunctionName("HttpStart")]
        public static async Task<HttpResponseMessage> Run(
            [HttpTrigger(AuthorizationLevel.Function, methods: "post", Route = "orchestrators/{functionName}")] HttpRequestMessage req,
            [DurableClient] IDurableClient starter,
            string functionName,
            ILogger log)
        {
            // Function input comes from the request content.
            object eventData = await req.Content.ReadAsAsync<object>();
            string instanceId = await starter.StartNewAsync(functionName, eventData);

            log.LogInformation($"Started orchestration with ID = '{instanceId}'.");

            return starter.CreateCheckStatusResponse(req, instanceId);
        }
    }
}

Le démarrage d’une fonction d’orchestrateur à l’aide des fonctions de déclencheur HTTP présentées précédemment peut être effectué à l’aide d’un client HTTP quelconque. La commande curl suivante démarre une fonction d’orchestrateur nommée DoWork :

curl -X POST https://localhost:7071/orchestrators/DoWork -H "Content-Length: 0" -i

Voici un exemple de réponse pour une orchestration dont l’ID est abc123. Certains détails ont été supprimés pour plus de clarté.

HTTP/1.1 202 Accepted
Content-Type: application/json; charset=utf-8
Location: http://localhost:7071/runtime/webhooks/durabletask/instances/abc123?code=XXX
Retry-After: 10

{
    "id": "abc123",
    "purgeHistoryDeleteUri": "http://localhost:7071/runtime/webhooks/durabletask/instances/abc123?code=XXX",
    "sendEventPostUri": "http://localhost:7071/runtime/webhooks/durabletask/instances/abc123/raiseEvent/{eventName}?code=XXX",
    "statusQueryGetUri": "http://localhost:7071/runtime/webhooks/durabletask/instances/abc123?code=XXX",
    "terminatePostUri": "http://localhost:7071/runtime/webhooks/durabletask/instances/abc123/terminate?reason={text}&code=XXX"
}

Dans l’exemple précédent, chacun des champs se terminant par Uri correspond à une API HTTP intégrée. Vous pouvez utiliser ces API pour gérer l’instance d’orchestration cible.

Notes

Le format des URL de webhook dépend de la version de l’hôte Azure Functions que vous exécutez. L’exemple précédent a trait à l’hôte Azure Functions 2.0.

Pour obtenir une description de toutes les API HTTP intégrées, consultez la Référence sur l’API HTTP.

Suivi de l’opération asynchrone

La réponse HTTP mentionnée précédemment est conçue pour faciliter l’implémentation d’API asynchrones HTTP longues avec Durable Functions. Ce modèle est parfois appelé modèle d’interrogation du consommateur. Le flux client/serveur fonctionne comme suit :

  1. Le client émet une requête HTTP pour démarrer un processus à long terme, tel qu’une fonction d’orchestrateur.
  2. Le déclencheur HTTP cible retourne une réponse HTTP 202 avec un en-tête Location dont la valeur est « statusQueryGetUri ».
  3. Le client interroge l’URL figurant dans l’en-tête Location. Le client continue à voir des réponses HTTP 202 avec un en-tête Location.
  4. Lorsque l’exécution de l’instance se termine ou échoue, le point de terminaison dans l’en-tête Location retourne HTTP 200.

Ce protocole permet de coordonner les processus de longue durée avec des clients ou services externes qui peuvent interroger un point de terminaison HTTP et suivre l’en-tête Location. Les implémentations cliente et serveur de ce modèle sont intégrées dans les API HTTP de Durable Functions.

Notes

Par défaut, toutes les actions basées sur HTTP fournies par Azure Logic Apps prennent en charge le modèle d’opération asynchrone standard. Cette fonctionnalité permet d’incorporer une fonction durable de longue durée dans un flux de travail Logic Apps. Pour plus d’informations sur la prise en charge des modèles HTTP asynchrones par Logic Apps, voir la documentation sur les actions de flux de travail et les déclencheurs Azure Logic Apps.

Notes

Il est possible d’interagir avec des orchestrations à partir de n’importe quel type de fonction, pas seulement des fonctions déclenchées par HTTP.

Pour plus d’informations sur la façon de gérer les orchestrations et les entités à l’aide d’API clientes, voir l’article Gestion d’instance.

Utilisation des API HTTP

Comme décrit dans Contraintes de code des fonctions d’orchestrateur, les fonctions d’orchestrateur ne peuvent pas effectuer d’E/S directement. Au lieu de cela, elles appellent généralement des fonctions d’activité qui effectuent les opérations d’E/S.

Depuis Durable Functions 2.0, les orchestrations sont en mesure de consommer en mode natif les API HTTP à l’aide d’une liaison de déclencheur d’orchestration.

L’exemple de code suivant montre une fonction d’orchestrateur C# qui exécute une requête HTTP sortante :

[FunctionName("CheckSiteAvailable")]
public static async Task CheckSiteAvailable(
    [OrchestrationTrigger] IDurableOrchestrationContext context)
{
    Uri url = context.GetInput<Uri>();

    // Makes an HTTP GET request to the specified endpoint
    DurableHttpResponse response = 
        await context.CallHttpAsync(HttpMethod.Get, url);

    if (response.StatusCode >= 400)
    {
        // handling of error codes goes here
    }
}

L’action « call HTTP » vous permet d’effectuer les actions suivantes dans vos fonctions d’orchestrateur :

  • Appeler les API HTTP directement à partir des fonctions d’orchestration, avec certaines limitations mentionnées ci-après.
  • Prendre en charge automatiquement les modèles d’interrogation d’état HTTP 202 côté client.
  • Utiliser les identités managées Azure pour effectuer des appels HTTP autorisés à d’autres points de terminaison Azure.

La capacité à consommer les API HTTP directement à partir des fonctions d’orchestrateur est conçue à titre de commodité pour un certain ensemble de scénarios courants. Vous pouvez implémenter toutes ces fonctionnalités vous-même à l’aide de fonctions d’activité. Dans de nombreux cas, les fonctions d’activité peuvent vous offrir plus de souplesse.

Gestion des cas HTTP 202

L’API « call HTTP » peut implémenter automatiquement le côté client du modèle d’interrogation de consommateur. Si une API appelée renvoie une réponse HTTP 202 avec un en-tête Location, la fonction d’orchestrateur interroge automatiquement la ressource Location jusqu’à recevoir une réponse autre que 202. Cette réponse est celle renvoyée au code de la fonction d’orchestrateur.

Notes

  1. Les fonctions d’orchestrateur prennent également en charge en mode natif le modèle d’interrogation de consommateur côté serveur, comme décrit dans Suivi de l’opération asynchrone. Cette prise en charge signifie que les orchestrations au sein d’une application de fonction peuvent facilement coordonner les fonctions d’orchestrateur dans d’autres applications de fonction. Cela est similaire au concept de sous-orchestration, mais avec la prise en charge des communications entre applications. Cette prise en charge s’avère particulièrement utile pour le développement d’applications de type microservice.
  2. En raison d'une limitation temporaire, le modèle d'interrogation HTTP intégré n'est pas actuellement disponible en JavaScript/TypeScript et Python.

Identités managées

Durable Functions prend en charge en mode natif les appels aux API qui acceptent des jetons Microsoft Entra pour l’autorisation. Cette prise en charge utilise des identités managées Azure pour acquérir ces jetons.

Le code suivant est un exemple de fonction d’orchestrateur. La fonction qui effectue des appels authentifiés pour redémarrer une machine virtuelle à l’aide de l’API REST Machines virtuelles d’Azure Resource Manager.

[FunctionName("RestartVm")]
public static async Task RunOrchestrator(
    [OrchestrationTrigger] IDurableOrchestrationContext context)
{
    string subscriptionId = "mySubId";
    string resourceGroup = "myRG";
    string vmName = "myVM";
    string apiVersion = "2019-03-01";
    
    // Automatically fetches an Azure AD token for resource = https://management.core.windows.net/.default
    // and attaches it to the outgoing Azure Resource Manager API call.
    var restartRequest = new DurableHttpRequest(
        HttpMethod.Post, 
        new Uri($"https://management.azure.com/subscriptions/{subscriptionId}/resourceGroups/{resourceGroup}/providers/Microsoft.Compute/virtualMachines/{vmName}/restart?api-version={apiVersion}"),
        tokenSource: new ManagedIdentityTokenSource("https://management.core.windows.net/.default"));
    DurableHttpResponse restartResponse = await context.CallHttpAsync(restartRequest);
    if (restartResponse.StatusCode != HttpStatusCode.OK)
    {
        throw new ArgumentException($"Failed to restart VM: {restartResponse.StatusCode}: {restartResponse.Content}");
    }
}

Dans l’exemple précédent, le paramètre tokenSource est configuré pour acquérir des jetons Microsoft Entra pour Azure Resource Manager. Les jetons sont identifiés par l’URI de ressource https://management.core.windows.net/.default. Cet exemple part du principe que l’application de fonction actuelle s’exécute localement ou a été déployée en tant qu’application de fonction avec une identité managée. L’identité locale ou l’identité managée est supposée avoir l’autorisation de gérer des machines virtuelles dans le groupe de ressources spécifié myRG.

Lors de l’exécution, la source de jeton configurée retourne automatiquement un jeton d’accès OAuth 2.0. La source ajoute ensuite le jeton en tant que jeton du porteur à l’en-tête Authorization de la demande sortante. Ce modèle constitue une amélioration par rapport à l’ajout manuel d’en-têtes d’autorisation aux requêtes HTTP pour les raisons suivantes :

  • L’actualisation des jetons est gérée automatiquement. Vous n’avez pas à vous soucier des jetons expirés.
  • Les jetons ne sont jamais stockés dans l’état d’orchestration durable.
  • Vous n’êtes pas obligé d’écrire du code pour gérer l’acquisition des jetons.

Vous trouverez un exemple plus complet dans l’exemple « RestartVMs » C# précompilé.

Les identités managées ne sont pas limitées à la gestion des ressources Azure. Vous pouvez utiliser des identités managées pour accéder à n’importe quelle API acceptant des jetons du porteur Microsoft Entra, notamment à des services Azure de Microsoft et à des applications web de partenaires. Une application web d’un partenaire peut même être une autre application de fonction. Pour obtenir la liste des services Azure de Microsoft qui prennent en charge l’authentification avec Microsoft Entra ID, voir Services Azure qui prennent en charge l’authentification Microsoft Entra.

Limites

La prise en charge intégrée de l’appel des API HTTP est une fonctionnalité de commodité. Elle ne convient pas pour tous les scénarios.

Les requêtes HTTP envoyées par les fonctions d’orchestrateur et leurs réponses sont sérialisées et conservées en tant que messages dans le fournisseur de stockage Durable Functions. Ce comportement persistant de mise en file d’attente garantit la fiabilité et la sécurité des appels HTTP pour la relecture d’orchestration. Toutefois, le comportement persistant de mise en file d’attente présente également des limitations :

  • Chaque requête HTTP implique une latence supplémentaire par rapport à un client HTTP natif.
  • Selon le fournisseur de stockage configuré, les messages de requête ou de réponse volumineux peuvent nuire considérablement aux performances de l’orchestration. Par exemple, lorsque vous utilisez Stockage Azure, les charges utiles HTTP qui sont trop volumineuses pour être contenues dans les messages de la file d’attente Azure sont compressées et stockées dans le stockage d’objets blob Azure.
  • Les charges utiles de streaming, segmentées et binaires ne sont pas prises en charge.
  • La possibilité de personnaliser le comportement du client HTTP est limitée.

Si l’une de ces limitations risque d’avoir un impact sur votre cas d’utilisation, envisagez plutôt d’utiliser des fonctions d’activité et des bibliothèques clientes HTTP spécifiques d’un langage pour effectuer des appels HTTP sortants.

Notes

Si vous êtes un développeur .NET, vous vous demandez peut-être pourquoi cette fonctionnalité utilise les types DurableHttpRequest et DurableHttpResponse au lieu des types HttpRequestMessage et HttpResponseMessage.

Ce choix de conception est intentionnel. La principale raison est que les types personnalisés permettent de s’assurer que les utilisateurs ne font pas de suppositions incorrectes concernant les comportements pris en charge du client HTTP interne. Les types spécifiques de Durable Functions permettent également de simplifier la conception des API. Ils peuvent également rendre plus facilement disponibles des fonctionnalités spéciales telles que l’intégration d’identité managée et le modèle d’interrogation de consommateur.

Extensibilité (.NET uniquement)

La personnalisation du comportement du client HTTP interne de l’orchestration est possible par injection de dépendances .NET Azure Functions. Cette possibilité peut s’avérer utile pour effectuer des changements de comportement minimes. Elle peut également s’avérer utile pour le test unitaire du client HTTP en injectant des objets fictifs.

L’exemple suivant illustre l’utilisation de l’injection de dépendances pour désactiver la validation de certificat TLS/SSL pour des fonctions d’orchestrateur qui appellent des points de terminaison HTTP externes.

public class Startup : FunctionsStartup
{
    public override void Configure(IFunctionsHostBuilder builder)
    {
        // Register own factory
        builder.Services.AddSingleton<
            IDurableHttpMessageHandlerFactory,
            MyDurableHttpMessageHandlerFactory>();
    }
}

public class MyDurableHttpMessageHandlerFactory : IDurableHttpMessageHandlerFactory
{
    public HttpMessageHandler CreateHttpMessageHandler()
    {
        // Disable TLS/SSL certificate validation (not recommended in production!)
        return new HttpClientHandler
        {
            ServerCertificateCustomValidationCallback =
                HttpClientHandler.DangerousAcceptAnyServerCertificateValidator,
        };
    }
}

Étapes suivantes