On one of my recent projects, a client application was required to place a message onto an Azure Service Bus using an HTTP endpoint rather than the Service Bus SDK and with the following constraints.
- The client is unable to generate the Service Bus SAS token.
- Service Bus Session Id needs to be set to the customer number found in the message to ensure ordered delivery by the consumer.
- Custom HTTP Request Headers may be used.
I decided upon a solution that uses Azure APIM to expose the Service Bus endpoint.
- The first step of this solution is to create an Azure Service Bus with a queue called 'apimqueue'.
Please refer below screenshot.
2. Next, click on created queue, navigate to Shared access policy, and add' apimqueuesend' with only Send claim.
3. Click on created shared access policies and copy the primary key for further use.
4. Next is to create an API using the 'Blank API' template, similar to what I have done below. Note the 'Web service URL' value is the base address of the Service Bus topic URL.
5. Enter the Name, give your service bus's web service URL, and click on create.
6. Add operation based on your request, like Post, and Get Methods.
Refer below screen after the created operation.
7. Next step is to add policies to added operation.
8. Add the below policy as shown in the above screen.
<policies>
<inbound>
<base />
<cache-lookup-value key="apimqueuesend" variable-name="apimqueuesend" />
<choose>
<when condition="@(context.Variables.GetValueOrDefault<string>("apimqueuesend") == null)">
<cache-store-value key="crmsbsas" value="@{
string resourceUri = "https://dwproject.servicebus.windows.net/apimqueue";
string keyName = "apimqueuesend";
string key = "saskey";
TimeSpan sinceEpoch = DateTime.UtcNow - new DateTime(1970, 1, 1);
var expiry = Convert.ToString((int)sinceEpoch.TotalSeconds + 120);
string stringToSign = System.Uri.EscapeDataString(resourceUri) + "\n" + expiry;
HMACSHA256 hmac = new HMACSHA256(Encoding.UTF8.GetBytes(key));
var signature = Convert.ToBase64String(hmac.ComputeHash(Encoding.UTF8.GetBytes(stringToSign)));
var sasToken = String.Format("SharedAccessSignature sr={0}&sig={1}&se={2}&skn={3}",
System.Uri.EscapeDataString(resourceUri),
System.Uri.EscapeDataString(signature), expiry, keyName);
return sasToken;
}" duration="10" />
<cache-lookup-value key="apimqueuesend" variable-name="apimqueuesend" />
</when>
</choose>
<set-backend-service base-url="https://dwproject.servicebus.windows.net" />
<rewrite-uri template="apimqueue/messages" />
<set-header name="Content-Type" exists-action="override">
<value>vnd.microsoft.servicebus.yml</value>
</set-header>
<set-header name="Authorization" exists-action="override">
<value>{{apimqueuesend}}</value>
</set-header>
<set-header name="BrokerProperties" exists-action="override">
<value>@{
var json = new JObject();
json.Add("MessageId", context.RequestId);
return json.ToString(Newtonsoft.Json.Formatting.None);
}</value>
</set-header>
<set-body>@{
JObject json = context.Request.Body.As<JObject>(preserveContent: true);
return JsonConvert.SerializeObject(json);
}</set-body>
</inbound>
<backend>
<base />
</backend>
<outbound>
<base />
</outbound>
<on-error>
<base />
<return-response>
<set-status code="200" reason="OK" />
</return-response>
</on-error>
</policies>
9. To test added policy, please navigate to test in the APIM section. Please give the required headers and JSON data and click on send.
10. Finally, Navigate to our queue and check whether the message has been received.