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.
![Azure Service Bus through APIM and generating a SAS Token]()
![Azure Service Bus through APIM and generating a SAS Token]()
2. Next, click on created queue, navigate to Shared access policy, and add' apimqueuesend' with only Send claim.
![Azure Service Bus through APIM and generating a SAS Token]()
![Azure Service Bus through APIM and generating a SAS Token]()
3. Click on created shared access policies and copy the primary key for further use.
![Azure Service Bus through APIM and generating a SAS Token]()
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.
![Azure Service Bus through APIM and generating a SAS Token]()
5. Enter the Name, give your service bus's web service URL, and click on create.
![Azure Service Bus through APIM and generating a SAS Token]()
6. Add operation based on your request, like Post, and Get Methods.
![Azure Service Bus through APIM and generating a SAS Token]()
Refer below screen after the created operation.
![Azure Service Bus through APIM and generating a SAS Token]()
7. Next step is to add policies to added operation.
![Azure Service Bus through APIM and generating a SAS Token]()
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.
![Azure Service Bus through APIM and generating a SAS Token]()
![Azure Service Bus through APIM and generating a SAS Token]()
​​​​​​​10. Finally, Navigate to our queue and check whether the message has been received.
![Azure Service Bus through APIM and generating a SAS Token]()