.NET Services March 2009 CTP - Service Bus Routers And Queues - Part 3: The REST Queue Protocol

[If this text looks vaguely familiar you’ve read the HttpQueueSample Readme doc from the SDK. Good job!]

Here is the Service Bus Queue REST protocol. I apologize if this is a bit dry, but I want to give you the bare protocol facts first and will follow-up with code samples later. Look at the HTTP Queue SDK sample if you can’t wait for code ;-)

You can find the HTTP Queue sample in the SDK install path under .\Samples\ServiceBus\ExploringFeatures\Queues\HttpMessages\

The beauty of REST is that there’s a uniform interface. It’s all just GET, POST, PUT, DELETE, a set of resources, and a rigorous application of the RFC2616 / HTTP 1.1 rules. That doesn’t make the description particularly entertaining, but it does yield a pretty consistent interaction model:

Authorization

All Queue operations require the client to be appropriately authorized. The client must therefore acquire an lightweight identity token from the Microsoft .NET Access Control Service using the .NET Services solution name and the solution password and include the acquired token with each request. The tokens are added to requests using the X-MS-Identity-Token HTTP header. The value for this header is a short-lived token which can be used for a period of up to 8 hours and must be acquired from the .NET Access Control Service. We strongly encourage you to guard the acquired tokens in the same fashion as you would guard a credential and you should not openly expose them unprotected on the network or web-pages or embedded in a Flash or Silverlight application.

The request for acquiring the token is an HTTPS GET on the URI https://accesscontrol.windows.net/issuetoken.aspx?u={solutionName}\&p={solutionPassword} whereby you replace the arguments for solution name and the solution password with your .NET Services solution credentials. If a token is successfully issued to you the request returns with a 200 (OK) status code and contains a text/plain entity body with a short, base64 encoded token hash as a single line of text, which you for the value of the X-MS-Identity-Token header.

Creating a Queue

A Queue is created on the Service Bus in four simple steps. I’ve discussed most of this in the post on Queue Policies:

  1. Select a name in the Service Bus naming hierarchy where the Queue should be located, i.e. https:// mysolution .servicebus.windows.net/myapp/q1

  2. Create a Queue policy and define the desired properties of the Queue.

  3. Embed the Queue policy into an ATOM 1.0 <atom:entry> as an extension and POST the entry to the designated Queue URI with the content-type application/atom+xml;type=entry. The request must carry an X-MS-Identity-Token header and the respective identity must have 'Manage' permission on for scope covering the Queue URI.

  4. If the queue was successfully created, the POST request returns with a 201 'created' status code along with a Location header. The response entity body contains the effective Queue policy as applied to the name by the Service Bus.

    The location header contains the queue's management URI that you need to retain in your application state to have access to the queue's metadata and management functions. If the queue could not be created successfully, the request may yield the following status codes:

    • 400 - Bad Request. The policy was malformed or invalid.

    • 403 - Forbidden. The client did not provide a X-MS-Identity-Token header, the provided token is no longer valid for use, or the provided identity is not authorized to create a Queue at this location.

    • 409 - Conflict.  There is already a Queue with an incompatible policy at the given location or the location is occupied by a Router or a Service Bus listener.

    • 415 - Unsupported Media Type. The request did not carry the required content-type header.

    • 500 - Internal Server Error. The processing failed to to a condition internal to the Service Bus service.

REST Anatomy of a Queue

Each Queue has five distinct types of resources: Policy, Tail, Head, Locks, and Control. The concrete URIs are discoverable using the Service Registry's Atom Publishing protocol. you should not make any assumptions about the particular format of the URIs spelled out below since the particular format might change.

The Atom 1.0 entry shown below is also enclosed in the response entity body of the create request (POST) explained above. A Queue's representation in the registry feed as seen when doing a GET (discovery-) request on the queue's parent URI is commonly as follows:

 <feed xmlns="https://www.w3.org/2005/Atom">
  ...
  <entry>
    <id>{id}</id>
    <title type="text">MyHttpQueue</title>
    <updated>{date}</updated>
    <link rel="alternate" href="https://solution.servicebus.windows.net/myapp/q1" />
    <link rel="self" href="https://solution.servicebus.windows.net/myapp/q1!(queue)" />
    <link rel="queuehead" href="https://solution.servicebus.windows.net/myapp/q1!(queue/head)" />
    <link rel="queuecontrol" href="https://solution.servicebus.windows.net/myapp/q1!(queue/control)" />
    <QueuePolicy xmlns="https://schemas.microsoft.com/ws/2007/08/connect">
      <Discoverability>Public</Discoverability>
      <ExpirationInstant>{expiration}</ExpirationInstant>
    </QueuePolicy>
  </entry>
</feed>
Managing The Queue

<link rel="self" href="https://solution.servicebus.windows.net/myapp/q1!(queue)" />

The "self" link in the entry above is the queue's management URI that allows you to interact with the queue's policy.

  • To renew a queue and extend its expiration you PUT an updated Atom 1.0 entry with the effective policy and an updated ExpirationInstant value to the "self" URI.  The "self" URI is the same URI as the one returned in the Location header returned by the create POST explained above. The request will yield a 200 status code if the renewal is successful. It will yield a 404 if the queue no longer exists.

  • To delete a queue you issue a DELETE request on  the queue's management URI. The Delete request is sent without any entity body and MUST have a Content-Length header that is set to zero (0). Not setting this header will yield a 411 status code. The request yields a 204 response if the queue was deleted successfully.

Enqueue

<link rel="alternate" href="https://solution.servicebus.windows.net/myapp/q1" />

The "alternate" link refers to the tail of the queue. The Queue's tail resource is where senders submit messages into the Queue. The queue's tail URI is identical to the URI where the queue was initially created. The queue's tail endpoint accepts requests with any HTTP Content-Type and any HTTP method except GET, HEAD, and OPTIONS.

The endpoint should be considered a 'delegate' of the message recipient and not the resource that the respective operations have an immediate effect on. That means that the HTTP method applied to the Queue tail doesn’t have any particular semantic. If a message has been successfully accepted into the queue, the request returns a 202 status code. Otherwise it will return a 500

Dequeue and Peek/Lock

<link rel="queuehead" href="https://solution.servicebus.windows.net/myapp/q1!(queue/head)" />

The "queuehead" link refers to the head of the Queue. The Queue's head resource is where receivers retrieve messages from the queue. It is modeled as a resource whose current representation corresponds to the message(s) that reside at the head of the queue and which is/are next in line to be retrieved by consumers. Permitted operations on the head are:

  • DELETE:  Delete performs a destructive read on the queue whereby the message(s) at the head of the queue are permanently deleted and returned as the entity body of the response to the request. The content type and formatting of the response depends on a set of query parameters that are discussed below. The DELETE request's response status code is 200 if at least one message could be retrieved and deleted from the queue and the message content is enclosed in the response's entity body. The response status code is 204if no message could be retrieved/deleted.
  • POST: Post creates a lock on the message(s) at the head of the queue and returns the locked messages. Locked messages are temporarily removed from the head of the queue for a period of 1 minute during which time the receiver can decide whether to return the message to the head of the queue or whether to permanently delete it. The POST request's response status code is 200 if at least one message could be retrieved and locked on the queue and the message content is enclosed in the response's entity body. The response status code is 204if no message could be retrieved/locked.
Releasing and Deleting Peek/Lock Message Locks

Any retrieved, peek/locked message (POST on “queuehead”) contains an HTTP header X-MS-Message-Lock whose value is a URI. The following operations can be performed on this URI:

  • DELETE: The message has been accepted/processed by the receiver and the lock shall be deleted. The deletion of the lock discards the message permanently from the queue. The Delete request is sent without any entity body and MUST have a Content-Length header that is set to zero (0). Not setting this header will yield a 411 status code. The request yields a 204 response if the lock was deleted successfully.
  • PUT:   The message has been not been accepted/processed by the receiver and the message shall be put back at the head of the queue. This operation transitions the lock from the locked state into the unlocked state which releases the message back into the queue. The lock itself is discarded afterwards. The Put request is sent without any entity body and MUST have a Content-Length header that is set to zero (0). Not setting this header will yield a 411 status code. The request yields a 204 response if the lock was released successfully.
Options for Dequeue and Peek/Lock

The DELETE and POST operation have a set of options that are expressed as query parameters appended to the queue's head URI. The options are the same for both operations:

  • timeout= value - The value is a numerical value (expressed in seconds) that indicates how long the client is willing to wait for the polling request to complete. The value should not exceed 60 seconds and a value of 30 seconds is a safer choice with intermediate proxies in place. If the timeout expires and no message is available, the request completes with a 204 response code. The default value is zero (0), which means that the request returns immediately.

  • maxmessages=value - Indicates how many messages the client is willing to accept in a single response. The default is 1. The service will return at most 10 messages at a time and a value greater than zero requires encoding=multipart (see below)

  • encoding=value - There are three supported encoding modes for the REST retrieval model

    • asreply - The request stored in the Queue is mapped onto the response to the DELETE/POST request returning the message from the queue. This option requires maxmessages=1 or omission of the maxmessages option.

    • single - The request stored in the queue is returned as a complete HTTP request frame on the response to the DELETE/POST request using Content-Type application/http . This option requires maxmessages=1 or omission of the maxmessages option.

    • multipart - The request(s) stored in the queue are returned as a complete HTTP request frames on the response to the DELETE/POST request using Content-Type multipart/mixed with MIME parts of Content-Type application/http .

Queue Content Control

<link rel="queuecontrol" href="https://solution.servicebus.windows.net/myapp/q1!(queue/control)" />

The "queuecontrol" link refers to the control resource provides information about the status of the queue and allows for purging all of the queue's contents. The control resource is present in the current CTP, but you cannot perform any operations on it.