Skip to content

sp_invoke_external_rest_endpoint to Azure Queue results in poisonous message #11

Open
@drmssst

Description

@drmssst

From Azure SQL using sp_invoke_external_rest_endpoint a message is successfully queued in Azure Queue. The payload is <QueueMessage><MessageText>HelloWorld</MessageText></QueueMessage>.

When the Queue Triggered Azure function dequeues the message it ultimately lands in the poison queue.

If I take the same message, in this case HelloWorld, and add it via the portal (only works if the "Encode the message body in Base64" is checked), then the message successfully dequeues.

I've tried a variety of things to gain understanding of what is happening in the background, but I've run out of ideas.

This feels like an encoding problem. Any ideas on how best to solve this?

Below is some code if there is a desire to recreate the experience.
SQL Code (Azure SQL Database)

DECLARE @QueueMessage_XML nvarchar(max) = N'<QueueMessage><MessageText>HelloWorld</MessageText></QueueMessage>';
DECLARE @QueueMessage nvarchar(max) = @QueueMessage_XML;

DECLARE @Time datetime = SYSUTCDATETIME();
DECLARE @FormattedMoment nvarchar(50) = FORMAT(@Time, 'ddd, dd MMM yyyy HH:mm:ss' ) + ' GMT';

DECLARE @ContentType nvarchar(256) = N'"content-type":"application/xml"';
DECLARE @Accept nvarchar(256) = N'"accept":"application/xml"';
DECLARE @StorageApiMsVersion nvarchar(256) = N'"x-ms-version":"2023-11-03"';
DECLARE @MsDate nvarchar(256) = N'"x-ms-date":"' + @FormattedMoment + N'"';

DECLARE @HeadersArray table([HeaderItem] nvarchar(256) NOT NULL);
INSERT INTO @HeadersArray ([HeaderItem]) VALUES 
    (@ContentType), 
    (@Accept), 
    (@StorageApiMsVersion), 
    (@MsDate);
DECLARE @Headers nvarchar(4000) = N'{' + (SELECT STRING_AGG([HeaderItem], ',') FROM @HeadersArray) + N'}';

DECLARE @Method nvarchar(6) = N'POST';
DECLARE @TimeoutSeconds int = 30;
DECLARE @Response nvarchar(max) = N'';
DECLARE @VisibilityTimeoutSeconds int = 20;

DECLARE @AccountName nvarchar(256)  = N'stacctname';
DECLARE @QueueName nvarchar(256)  = N'request';
DECLARE @QueueEndpoint nvarchar(256)  = N'https://' + @AccountName + N'.queue.core.windows.net';

DECLARE @Url nvarchar(4000) = @QueueEndpoint + N'/' + @QueueName + N'/messages';

DECLARE @ReturnValue int = 0;
EXEC @ReturnValue = sp_invoke_external_rest_endpoint
  @url = @Url,
  @payload = @QueueMessage,
  @headers = @Headers,
  @method = @Method,
  @credential = [https://stacctname.queue.core.windows.net],
  @timeout = @TimeoutSeconds,
  @response = @Response OUTPUT;

SELECT @ReturnValue AS [ReturnValue], @Response AS [Response];

Azure Function App Code

  • Isolated
  • C# .NET 8
  • Visual Studio 2022 Version 17.9.0 Preview 1.0
using Azure.Storage.Queues.Models;
using Microsoft.Azure.Functions.Worker;
using Microsoft.Extensions.Logging;

namespace FunctionApp;

public class DequeueRequest(ILogger<DequeueRequest> logger)
{
    private readonly ILogger<DequeueRequest> _logger = logger;

    [Function(nameof(DequeueRequest))]
    public void Run([QueueTrigger("request", Connection = "AzureWebJobsStorage")] QueueMessage message)
    {
        //intentionally muted
        _ = message.Body;
    }
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions