HTTP uç noktasına olayları alma

Bu makalede, olay aboneliğinden olay almak ve ardından olayları alıp seri durumdan çıkarmak için HTTP uç noktasının nasıl doğrulandığı açıklanır. Bu makalede tanıtım amacıyla bir Azure İşlevi kullanılır, ancak uygulamanın nerede barındırıldığına bakılmaksızın aynı kavramlar geçerlidir.

Dekont

Event Grid ile bir Azure İşlevi tetiklerken Event Grid Tetikleyicisi kullanmanızı öneririz. Event Grid ile Azure İşlevleri arasında daha kolay ve daha hızlı bir tümleştirme sağlar. Ancak, Azure İşlevleri Event Grid tetikleyicisinin barındırılan kodun Event Grid'e döndürülen HTTP durum kodunu denetlemesi gereken senaryoyu desteklemediğini unutmayın. Bu sınırlama göz önüne alındığında, bir Azure İşlevi üzerinde çalışan kodunuz event grid tarafından olay teslimi yeniden denemesi başlatmak için 5XX hatası döndüremez.

Önkoşullar

HTTP ile tetiklenen bir işleve sahip bir işlev uygulamasına ihtiyacınız vardır.

Bağımlılık ekleme

.NET'te geliştiriyorsanız NuGet paketi için Azure.Messaging.EventGridişlevinize bir bağımlılık ekleyin.

Diğer diller için SDK'lar SDK'ları Yayımlama başvurusu aracılığıyla kullanılabilir. Bu paketler, , StorageBlobCreatedEventDatave EventHubCaptureFileCreatedEventDatagibi EventGridEventyerel olay türlerine yönelik modellere sahiptir.

Uç nokta doğrulama

yapmak istediğiniz ilk şey olayları işlemektir Microsoft.EventGrid.SubscriptionValidationEvent . Bir kişi bir olaya her abone olursa Event Grid, veri yükünde bir validationCode ile uç noktaya bir doğrulama olayı gönderir. Uç noktanın geçerli olduğunu ve size ait olduğunu kanıtlamak için yanıt gövdesinde bunu geri yansıtmak için uç nokta gereklidir. Web Kancası ile tetiklenen bir İşlev yerine Event Grid Tetikleyicisi kullanıyorsanız uç nokta doğrulaması sizin için işlenir. Bir üçüncü taraf API hizmeti (Zapier veya IFTTT gibi) kullanıyorsanız doğrulama kodunu program aracılığıyla yankılayamayabilirsiniz. Bu hizmetler için, abonelik doğrulama olayında gönderilen bir doğrulama URL'sini kullanarak aboneliği el ile doğrulayabilirsiniz. Özelliğindeki bu URL'yi validationUrl kopyalayın ve REST istemcisi veya web tarayıcınız aracılığıyla bir GET isteği gönderin.

C# dilinde yöntemi, ParseMany() bir veya daha fazla olay içeren bir BinaryData örneği dizisine seri durumdan EventGridEventçıkarmak için kullanılır. Önceden yalnızca tek bir olayın seri durumdan çıkarıldığını biliyorsanız, bunun yerine yöntemini kullanabilirsiniz Parse .

Doğrulama kodunu program aracılığıyla yansıtmak için aşağıdaki kodu kullanın.

using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using System;
using Azure.Messaging.EventGrid;
using Azure.Messaging.EventGrid.SystemEvents;

namespace Function1
{
    public static class Function1
    {
        [FunctionName("Function1")]
        public static async Task<IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)] HttpRequest req,
            ILogger log)
        {
            log.LogInformation("C# HTTP trigger function processed a request.");
            string response = string.Empty;
            BinaryData events = await BinaryData.FromStreamAsync(req.Body);
            log.LogInformation($"Received events: {events}");

            EventGridEvent[] eventGridEvents = EventGridEvent.ParseMany(events);

            foreach (EventGridEvent eventGridEvent in eventGridEvents)
            {
                // Handle system events
                if (eventGridEvent.TryGetSystemEventData(out object eventData))
                {
                    // Handle the subscription validation event
                    if (eventData is SubscriptionValidationEventData subscriptionValidationEventData)
                    {
                        log.LogInformation($"Got SubscriptionValidation event data, validation code: {subscriptionValidationEventData.ValidationCode}, topic: {eventGridEvent.Topic}");
                        // Do any additional validation (as required) and then return back the below response
                        var responseData = new
                        {
                            ValidationResponse = subscriptionValidationEventData.ValidationCode
                        };

                        return new OkObjectResult(responseData);
                    }
                }
            }
            return new OkObjectResult(response);
        }
    }
}
module.exports = function (context, req) {
    context.log('JavaScript HTTP trigger function begun');
    var validationEventType = "Microsoft.EventGrid.SubscriptionValidationEvent";

    for (var events in req.body) {
        var body = req.body[events];
        // Deserialize the event data into the appropriate type based on event type
        if (body.data && body.eventType == validationEventType) {
            context.log("Got SubscriptionValidation event data, validation code: " + body.data.validationCode + " topic: " + body.topic);

            // Do any additional validation (as required) and then return back the below response
            var code = body.data.validationCode;
            context.res = { status: 200, body: { "ValidationResponse": code } };
        }
    }
    context.done();
};

Test doğrulama yanıtı

Örnek olayı işlevin test alanına yapıştırarak doğrulama yanıtı işlevini test edin:

[{
  "id": "2d1781af-3a4c-4d7c-bd0c-e34b19da4e66",
  "topic": "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
  "subject": "",
  "data": {
    "validationCode": "512d38b6-c7b8-40c8-89fe-f46f9e9622b6"
  },
  "eventType": "Microsoft.EventGrid.SubscriptionValidationEvent",
  "eventTime": "2018-01-25T22:12:19.4556811Z",
  "metadataVersion": "1",
  "dataVersion": "1"
}]

Çalıştır'ı seçtiğinizde Çıkış 200 Tamam ve {"validationResponse":"512d38b6-c7b8-40c8-89fe-f46f9e9622b6"} gövdede olmalıdır:

Validation request

Validation output

Blob depolama olaylarını işleme

Şimdi işlevi sistem olayını işleyecek Microsoft.Storage.BlobCreated şekilde genişletelim:

using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using System;
using Azure.Messaging.EventGrid;
using Azure.Messaging.EventGrid.SystemEvents;

namespace Function1
{
    public static class Function1
    {
        [FunctionName("Function1")]
        public static async Task<IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)] HttpRequest req,
            ILogger log)
        {
            log.LogInformation("C# HTTP trigger function processed a request.");
            string response = string.Empty;
            BinaryData events = await BinaryData.FromStreamAsync(req.Body);
            log.LogInformation($"Received events: {events}");

            EventGridEvent[] eventGridEvents = EventGridEvent.ParseMany(events);

            foreach (EventGridEvent eventGridEvent in eventGridEvents)
            {
                // Handle system events
                if (eventGridEvent.TryGetSystemEventData(out object eventData))
                {
                    // Handle the subscription validation event
                    if (eventData is SubscriptionValidationEventData subscriptionValidationEventData)
                    {
                        log.LogInformation($"Got SubscriptionValidation event data, validation code: {subscriptionValidationEventData.ValidationCode}, topic: {eventGridEvent.Topic}");
                        // Do any additional validation (as required) and then return back the below response

                        var responseData = new
                        {
                            ValidationResponse = subscriptionValidationEventData.ValidationCode
                        };
                        return new OkObjectResult(responseData);
                    }
                    // Handle the storage blob created event
                    else if (eventData is StorageBlobCreatedEventData storageBlobCreatedEventData)
                    {
                        log.LogInformation($"Got BlobCreated event data, blob URI {storageBlobCreatedEventData.Url}");
                    }
                }
            }
            return new OkObjectResult(response);
        }
    }
}
module.exports = function (context, req) {
    context.log('JavaScript HTTP trigger function begun');
    var validationEventType = "Microsoft.EventGrid.SubscriptionValidationEvent";
    var storageBlobCreatedEvent = "Microsoft.Storage.BlobCreated";

    for (var events in req.body) {
        var body = req.body[events];
        // Deserialize the event data into the appropriate type based on event type  
        if (body.data && body.eventType == validationEventType) {
            context.log("Got SubscriptionValidation event data, validation code: " + body.data.validationCode + " topic: " + body.topic);

            // Do any additional validation (as required) and then return back the below response
            var code = body.data.validationCode;
            context.res = { status: 200, body: { "ValidationResponse": code } };
        }

        else if (body.data && body.eventType == storageBlobCreatedEvent) {
            var blobCreatedEventData = body.data;
            context.log("Relaying received blob created event payload:" + JSON.stringify(blobCreatedEventData));
        }
    }
    context.done();
};

Test Blobu Oluşturma olay işleme

Bir Blob depolama olayını test alanına yerleştirip çalıştırarak işlevin yeni işlevselliğini test edin:

[{
  "topic": "/subscriptions/{subscription-id}/resourceGroups/Storage/providers/Microsoft.Storage/storageAccounts/xstoretestaccount",
  "subject": "/blobServices/default/containers/testcontainer/blobs/testfile.txt",
  "eventType": "Microsoft.Storage.BlobCreated",
  "eventTime": "2017-06-26T18:41:00.9584103Z",
  "id": "831e1650-001e-001b-66ab-eeb76e069631",
  "data": {
    "api": "PutBlockList",
    "clientRequestId": "6d79dbfb-0e37-4fc4-981f-442c9ca65760",
    "requestId": "831e1650-001e-001b-66ab-eeb76e000000",
    "eTag": "0x8D4BCC2E4835CD0",
    "contentType": "text/plain",
    "contentLength": 524288,
    "blobType": "BlockBlob",
    "url": "https://example.blob.core.windows.net/testcontainer/testfile.txt",
    "sequencer": "00000000000004420000000000028963",
    "storageDiagnostics": {
      "batchId": "b68529f3-68cd-4744-baa4-3c0498ec19f0"
    }
  },
  "dataVersion": "",
  "metadataVersion": "1"
}]

İşlev günlüğünde blob URL'si çıkışını görmeniz gerekir:

2022-11-14T22:40:45.978 [Information] Executing 'Function1' (Reason='This function was programmatically called via the host APIs.', Id=8429137d-9245-438c-8206-f9e85ef5dd61)
2022-11-14T22:40:46.012 [Information] C# HTTP trigger function processed a request.
2022-11-14T22:40:46.017 [Information] Received events: [{"topic": "/subscriptions/{subscription-id}/resourceGroups/Storage/providers/Microsoft.Storage/storageAccounts/xstoretestaccount","subject": "/blobServices/default/containers/testcontainer/blobs/testfile.txt","eventType": "Microsoft.Storage.BlobCreated","eventTime": "2017-06-26T18:41:00.9584103Z","id": "831e1650-001e-001b-66ab-eeb76e069631","data": {"api": "PutBlockList","clientRequestId": "6d79dbfb-0e37-4fc4-981f-442c9ca65760","requestId": "831e1650-001e-001b-66ab-eeb76e000000","eTag": "0x8D4BCC2E4835CD0","contentType": "text/plain","contentLength": 524288,"blobType": "BlockBlob","url": "https://example.blob.core.windows.net/testcontainer/testfile.txt","sequencer": "00000000000004420000000000028963","storageDiagnostics": {"batchId": "b68529f3-68cd-4744-baa4-3c0498ec19f0"}},"dataVersion": "","metadataVersion": "1"}]
2022-11-14T22:40:46.335 [Information] Got BlobCreated event data, blob URI https://example.blob.core.windows.net/testcontainer/testfile.txt
2022-11-14T22:40:46.346 [Information] Executed 'Function1' (Succeeded, Id=8429137d-9245-438c-8206-f9e85ef5dd61, Duration=387ms)

Ayrıca bir Blob depolama hesabı veya Genel Amaçlı V2 Depolama hesabı oluşturarak, olay aboneliği ekleyerek ve uç noktayı işlev URL'sine ayarlayarak da test edebilirsiniz:

Function URL

Özel olayları işleme

Son olarak işlevi bir kez daha genişleterek özel olayları da işleyebilmesini sağlar.

Etkinliğiniz Contoso.Items.ItemReceivediçin bir denetim ekleyin. Son kodunuz şöyle görünmelidir:

using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using System;
using Azure.Messaging.EventGrid;
using Azure.Messaging.EventGrid.SystemEvents;

namespace Function1
{
    public static class Function1
    {
        [FunctionName("Function1")]
        public static async Task<IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)] HttpRequest req,
            ILogger log)
        {
            log.LogInformation("C# HTTP trigger function processed a request.");
            string response = string.Empty;
            BinaryData events = await BinaryData.FromStreamAsync(req.Body);
            log.LogInformation($"Received events: {events}");

            EventGridEvent[] eventGridEvents = EventGridEvent.ParseMany(events);

            foreach (EventGridEvent eventGridEvent in eventGridEvents)
            {
                // Handle system events
                if (eventGridEvent.TryGetSystemEventData(out object eventData))
                {
                    // Handle the subscription validation event
                    if (eventData is SubscriptionValidationEventData subscriptionValidationEventData)
                    {
                        log.LogInformation($"Got SubscriptionValidation event data, validation code: {subscriptionValidationEventData.ValidationCode}, topic: {eventGridEvent.Topic}");
                        // Do any additional validation (as required) and then return back the below response

                        var responseData = new
                        {
                            ValidationResponse = subscriptionValidationEventData.ValidationCode
                        };
                        return new OkObjectResult(responseData);
                    }
                    // Handle the storage blob created event
                    else if (eventData is StorageBlobCreatedEventData storageBlobCreatedEventData)
                    {
                        log.LogInformation($"Got BlobCreated event data, blob URI {storageBlobCreatedEventData.Url}");
                    }
                }
                // Handle the custom contoso event
                else if (eventGridEvent.EventType == "Contoso.Items.ItemReceived")
                {
                    var contosoEventData = eventGridEvent.Data.ToObjectFromJson<ContosoItemReceivedEventData>();
                    log.LogInformation($"Got ContosoItemReceived event data, item SKU {contosoEventData.ItemSku}");
                }
            }
            return new OkObjectResult(response);
        }
    }
}
module.exports = function (context, req) {
    context.log('JavaScript HTTP trigger function begun');
    var validationEventType = "Microsoft.EventGrid.SubscriptionValidationEvent";
    var storageBlobCreatedEvent = "Microsoft.Storage.BlobCreated";
    var customEventType = "Contoso.Items.ItemReceived";

    for (var events in req.body) {
        var body = req.body[events];
        // Deserialize the event data into the appropriate type based on event type
        if (body.data && body.eventType == validationEventType) {
            context.log("Got SubscriptionValidation event data, validation code: " + body.data.validationCode + " topic: " + body.topic);

            // Do any additional validation (as required) and then return back the below response
            var code = body.data.validationCode;
            context.res = { status: 200, body: { "ValidationResponse": code } };
        }

        else if (body.data && body.eventType == storageBlobCreatedEvent) {
            var blobCreatedEventData = body.data;
            context.log("Relaying received blob created event payload:" + JSON.stringify(blobCreatedEventData));
        }

        else if (body.data && body.eventType == customEventType) {
            var payload = body.data;
            context.log("Relaying received custom payload:" + JSON.stringify(payload));
        }
    }
    context.done();
};

Özel olay işlemeyi test etme

Son olarak işlevinizin artık özel olay türünüzü işleyebildiğini test edin:

[{
    "subject": "Contoso/foo/bar/items",
    "eventType": "Contoso.Items.ItemReceived",
    "eventTime": "2017-08-16T01:57:26.005121Z",
    "id": "602a88ef-0001-00e6-1233-1646070610ea",
    "data": { 
            "itemSku": "Standard"
            },
    "dataVersion": "",
    "metadataVersion": "1"
}]

Ayrıca portaldan CURL ile özel bir olay göndererek veya Postman gibi bir uç noktaya POST yapabilen herhangi bir hizmet veya uygulamayı kullanarak özel bir konuya göndererek bu işlevi canlı olarak test edebilirsiniz. İşlev URL'si olarak uç noktanın ayarlandığı özel bir konu ve olay aboneliği oluşturun.

İleti üst bilgileri

İleti üst bilgilerinde aldığınız özellikler şunlardır:

Özellik adı Açıklama
aeg-subscription-name Olay aboneliğinin adı.
aeg-delivery-count Olay için yapılan deneme sayısı.
aeg-event-type

Olayın türü.

Aşağıdaki değerlerden biri olabilir:

  • SubscriptionValidation
  • Bildirim
  • SubscriptionDeletion
aeg-metadata-version

Olayın meta veri sürümü.

Event Grid olay şeması için bu özellik meta veri sürümünü temsil eder ve bulut olay şeması için belirtim sürümünü temsil eder.

aeg-data-version

Olayın veri sürümü.

Event Grid olay şeması için bu özellik veri sürümünü temsil eder ve bulut olay şeması için geçerli değildir.

aeg-output-event-id Event Grid olayının kimliği.

Sonraki adımlar