Using the Service Bus via REST / HTTP

The new Service Bus Durable Messaging features introduced with the May 2011 CTP are really cool, and what's even better than a slew of new messaging features added to the AppFabric is the fact that many of them are accessible from clients on any platform using HTTP. In this post, I'm going to introduce you to using the Service Bus REST endpoint for Messaging; some of it might remind you of the October CTP, we'll be using Queues (so taking a look at David's post from Tuesday could be a good idea), and getting to grips with How Access Control Tokens work over HTTP would be a great primer, too.

A Preface to the RESTful Service Bus

Typically, users of the Service Bus download and install the AppFabric SDK, add a reference to Microsoft.ServiceBus and/or Microsoft.ServiceBus.Messaging and use the ServiceBusNamespaceClient to perform management operations (creating, enumerating and deleting any queues, topics or subscriptions) or the MessagingFactory to Send and Receive messages. Details like addressing and security are taken care of by the SDK: there's no need to get or renew Access Control Service tokens and no need to interact directly with the service - you just use the SDK. With the REST endpoint, you get a little closer to the metal which - in this geek's humble opinion - can be at least a little bit more fun!

Wherever possible, you'll want to use our SDK. It sheilds you from some of the underlying complexity of the service, may help to protect you as features change in future and - frankly - it's just a lot easier. That said, there are plenty of times when you won't be able to use the SDK, for example: when working on a non desktop .Net Framework version (like Windows Phone 7 or Silverlight); when working on non-microsoft platforms (like iOS, Android, Java, PHP or Ruby); and when working with older versions of the .Net Framework.

For convenience and consistency, the code samples in this post are shown in C# - that's not because you'd be writing in C# when using the Service Bus from iOS, PHP or Ruby, of course! I want to focus today on showing some of the basics of using our REST API from a language that many of you will be familiar with. That said, you can look forward to future posts in a wider variety of languages showing the awesome things you can do with Service Bus across platforms and devices.

There are 5 things I'll be covering in this post to get you started - please leave your feedback on areas you'd like have more detail, examples and guidance either in the comments (below) or the AppFabric CTP Forums.

  1. Get a security token from the Access Control Service
  2. Create a Queue in your service namespace
  3. Send a Message to the Queue
  4. Receive the Message from the Queue
  5. Delete the Queue

We're going to be busy - so make sure you have an account set up at the AppFabric Labs Portal and Lets Get Started!

Getting and Using a Security Token

Last Week, I provided some guidance on Getting and Understanding an Access Control Service Token via HTTP, so I won't provide a huge level of detail today on the topic. Suffice to say, the service bus requires that you present a WRAP access token in the HTTP Authorization Header, like this:

 Authorization: WRAP access_token=" <Your Token Here> "

Firstly, we'll get a token from ACS using the Issuer Name and Key which you can look up in the AppFabric Portal:

 string serviceNamespace = "contoso";
string issuerName  = "owner";
string issuerPassword = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa=";

string acsBaseAddress = "https://" + serviceNamespace + "-sb.accesscontrol.appfabriclabs.com/";

// Note that the scheme is Http
string relyingPartyAddress = "https://" + serviceNamespace + ".servicebus.appfabriclabs.com/";

// Create the body of the Post Request, formatted as a HTTP Form
string postData = "wrap_scope=" + Uri.EscapeDataString(relyingPartyAddress) +
                  "&wrap_name=" + Uri.EscapeDataString(issuerName) +
                  "&wrap_password=" + Uri.EscapeDataString(issuerPassword);

string authorizationToken;
using (WebClient acsWebClient = new WebClient())
{
    // The response contains the access token and its expiry time formatted as an HTTP 
    // Form like: wrap_access_token=<token>&wrap_expiry_time=2000
    string response = acsWebClient.UploadString(acsAddress, "POST", postData);

    string[] tokenVariables = response.Split('&');
    string[] tokenVariable = tokenVariables[0].Split('=');
    authorizationToken = Uri.UnescapeDataString(tokenVariable[1]);
}

The access token contains its expiry time (currently defaulting to 20 minutes), and you can keep using the same token over-and-over again until it expires. However, once the expiry time elapses you'll need to request a fresh token from the Access Control Service. Now we'll go ahead and create a WebClient to use for our calls to the service bus; we initialize it by correctly setting the Authorization header - you need this header to be present in any call you make to the service bus.

 WebClient webClient = new WebClient();
webClient.Headers["Authorization"] = "WRAP access_token=\"" + authorizationToken + "\"";

Creating a new Queue

In the October CTP, we introduced the idea of Namespace Management: an explicit, RESTful interface to Create, Enumerate and Delete durable Service Bus entities (in the May CTP these are: Queues, Topics and Subscriptions). That concept carries through to the May CTP with just a couple of changes. You still use the established RESTful pattern (HTTP GET to retrieve/enumerate; HTTP PUT to create; HTTP DELETE to remove) to interact with Atom Feeds and Entries; we've simplified things by combining the Management Namespace (formerly https://<your-namespace>-mgmt.servicebus.appfabriclabs.com/) with the Service Namespace (still https://<your-namespace>.servicebus.appfabriclabs.com) though.

A queue can exist anywhere in your service namespace - you create it by putting the description of the queue to a 'vacant' uri in your namespace. We'll need to specify the correct content type for the request (Content-Type: application/atom+xml) then issue an HTTP PUT to the Uri of the new queue (using the secure, https scheme) containing the Atom Entry which defines it:

 // Note that the scheme is Https
string serviceAddress = "https://" + serviceNamespace + ".servicebus.appfabriclabs.com/";

string queueName = "MyFirstQueue";
string putData = @"<entry xmlns=""https://www.w3.org/2005/Atom"">
                     <title type=""text"">" + queueName + @"</title>
                     <content type=""application/xml"">
                       <QueueDescription xmlns:i=""https://www.w3.org/2001/XMLSchema-instance"" xmlns=""https://schemas.microsoft.com/netservices/2010/10/servicebus/connect"" />
                     </content>
                   </entry>";

string queueAddress = serviceAddress + queueName;

webClient.Headers["Content-Type"] = "application/atom+xml";
string response = webClient.UploadString(queueAddress, "PUT", putData);

The response to the request contains the Atom Entry for your newly created Queue (below) including all of the settable properties of the Queue Description. Updates to existing queues are not allowed, but you can include any of these properties in the Queue Description when you are creating a new queue.

 <entry xmlns="https://www.w3.org/2005/Atom">
  <id>https://willpe.servicebus.appfabriclabs.com/MyFirstQueue</id>
  <title type="text">MyFirstQueue</title>
  <published>2011-05-17T20:26:00Z</published>
  <updated>2011-05-17T20:26:00Z</updated>
  <author>
    <name>willpe</name>
  </author>
  <link rel="self" href="https://willpe.servicebus.appfabriclabs.com/MyFirstQueue"/>
  <content type="application/xml">
    <QueueDescription xmlns="https://schemas.microsoft.com/netservices/2010/10/servicebus/connect" xmlns:i="https://www.w3.org/2001/XMLSchema-instance">
      <LockDuration>PT30S</LockDuration>
      <MaxQueueSizeInBytes>104857600</MaxQueueSizeInBytes>
      <RequiresDuplicateDetection>false</RequiresDuplicateDetection>
      <RequiresSession>false</RequiresSession>
      <DefaultMessageTimeToLive>P10675199DT2H48M5.4775807S</DefaultMessageTimeToLive>
      <DeadLetteringOnMessageExpiration>false</DeadLetteringOnMessageExpiration>
      <DuplicateDetectionHistoryTimeWindow>PT10M</DuplicateDetectionHistoryTimeWindow>
    </QueueDescription>
  </content>
</entry>

Sending a Message to the Queue

Sending a message using the REST endpoint is really simple: just HTTP Post the body of the message to the Queue's incoming messages uri with the Authorization header in place (specifying the correct content type for the message's body):

 string messageBody = "Hello World!";
string sendAddress = serviceAddress + queueName + "/Messages";

webClient.Headers["Content-Type"] = "text/plain";
webClient.UploadString(sendAddress, "POST", messageBody);

Receiving a Message from the Queue

Messages can be received with either Peek Lock or Receive And Delete semantics; both are supported via REST, but for now we'll use Receive and Delete. Receiving in this mode is as simple as issuing a HTTP Delete request to the Head of the Message Queue with a receive timeout:

 string receiveAddress = serviceAddress + queueName + "/Messages/Head?timeout=30";
string receivedMessageBody = webClient.UploadString(receiveAddress, "DELETE", string.Empty);

The receivedMessageBody contains the plain text sent earlier (neat!) - you can also take a look at the Response Headers to find more properties of the message:

 X-MS-MESSAGE-ID: d78afc3299b54ab2bd0e97b183ab1f77
X-MS-DELIVERY-COUNT: 0
X-MS-SEQUENCE-NUMBER: 2
X-MS-SIZE: 12
Content-Type: text/plain

Deleting the Queue

Finally, it's time to delete the queue; this is acheived by a simple HTTP Delete to the Queue's Address:

 webClient.UploadString(queueAddress, "DELETE", string.Empty);

So, there we have it - a quick introduction to using the new REST features of AppFabric Service Bus Messaging. There's lots more you can do, and I'll be covering more of the features next week but it's never too early to send the team your feedback - visit the AppFabric CTP Forum and tell us what you think!

In particular, we'd love to hear from you around how you'll be using HTTP in Applications you build:

  • Which platforms and devices are you considering using Service Bus from?
  • Which feature(s) of the Service Bus are most important for us to support over HTTP to make your applications successful?

Take the HTTP Feature Survey to help shape the future of Service Bus!