Using Windows Azure Service Bus from Ruby Apps
This article provides information on working with the Windows Azure AppFabric Service Bus from the Ruby programming language. This article assumes that you are familiar with Ruby, and have access to the Windows Azure AppFabric labs site (AppFabricLabs.com.) For more information on Ruby, see ruby-lang.org.
Introduction
Using Azure AppFabric Service Bus Queues from Ruby is easy. However, it’s not as easy to get started using as it should be because most of the guidance available is written for .NET developers using the .NET libraries provided with the Windows Azure AppFabric SDK. While there are packages for using Windows Azure Storage from Ruby (WAZ-Storage), there’s currently no equivalent for the AppFabric Service Bus. In addition, the AppFabric Queues May CTP requires authentication via ACS v2, for which there is also currently no library.
Sure, for both the basics are building a REST client, but when it comes to the details such as what Ruby packages to use to communicate in ways that mimic what is done in the .NET samples, things may become more confusing than they need to be, primarily owing to a lack of documentation on this.
This blog will walk thru the high level pieces you need in order to leverage AppFabric Queues from Ruby. We will focus on leveraging Queues directly, but provide a complete library that includes support for Topics and Subscriptions (as well as code samples that show how to use them from Ruby).
We will also show how to implement a client in Ruby; the steps taken serve to illustrate what one would need to perform from other non-.NET languages which offer a REST enabled client – we intentionally try to keep the Ruby specifics to a minimum and emphasize the more universal REST aspects.
Example Scenario – A Simple Rails App
To drive the implementation, let’s think through a simple scenario that would be common for a Ruby on Rails application (see the figure below). Let’s say we have a web page that takes some input representing work to be performed and pushes it to an AppFabric Queue. A backend process pulls the enqueued item from the queue and processes it. In this blog, we show how you would build the communication for both sending messages to the queue from the web app and retrieving messages from the queue from within the worker process.
Want to Play Along?
Before we dive in, feel free to set yourself to follow along with the sample code, we won’t show too much code in the blog in an effort to emphasize the approach, but the sample contains the complete code. If you are a .NET developer programming in Visual Studio 2010, Ruby may be unfamiliar- but the setup is easy and we encourage you to try out the provided sample code. If you are an experienced Ruby developer, you can skip over the first of the setup steps and directly go to downloading and running the code (Steps 3 and 4).
Quick Environment Setup
- Ensure you have created your AppFabric ServiceBus namespace. Follow the instructions here.
- Download and Install Ruby 1.8.7. We suggest getting a distribution from RubyInstaller.org
- Next, install the Rails-Client gem (a gem is like an assembly or library). This gem provides a handy REST enabled Client that is used by the source code we provide to interact with the ACS and AppFabric Queue services. To install it, after installing Ruby, fire up a command prompt and run the following command:
gem install rest-client
- The sample code as stand-alone Ruby files or the IronRuby (see the notes for additional information) project are available with this publication for download. .
- Open Program.rb and set your service namespace, service identity name and service identity password at the top, based on the values you acquired after setting up your namespace.
- Run the code by opening a command prompt (cmd.exe,) and navigating to the directory where you extracted the sample code, and then execute the following command:
ruby Program.rb
-
You should see output similar to the following:
Using scope URI of http://RubyQueue.servicebus.appfabriclabs.com
Authenticating via ACS
net.windows.servicebus.action=Listen%2cManage%2cSend&http%3a%2f%2fschemas.micros
oft.com%2faccesscontrolservice%2f2010%2f07%2fclaims%2fidentityprovider=https%3a%
2f%2fRubyQueue-sb.accesscontrol.appfabriclabs.com%2f&Audience=http%3a%2f%2fRubyQ
ueue.servicebus.appfabriclabs.com&ExpiresOn=1308769516&Issuer=https%3a%2f%2fruby
queue-sb.accesscontrol.appfabriclabs.com%2f&HMACSHA256=RqUmM7TYUd3KuA44V7n%2bOHV
dNTaQC11nmfOnubxwH8s%3d
Queue Management – Create Queue
……….
Overview of the Sample Code
The sample library has a handful of files providing support for Queues, Topics and Subscriptions. For this blog we will focus on these 4 ruby files that provide support for Queues:
-
Under the WAZ\AppFabric\ folder
- AccessControl.rb – helper library for using ACS v2 from Ruby to acquire Simple Web Tokens used in communicating with Queues.
- QueueClient.rb – helper library for sending messages to and receiving messages from Azure AppFabric Queues May 2011 CTP.
- QueueManagement.rb – helper library for creating, enumerating and deleting Queues with the Azure AppFabric Queues May 2011 CTP.
- Note 1: There are no hard coded paths in Program.rb. This folder structure is how Ruby deals with namespaces.
-
Note 2: The sample code is not repackaged as a GEM…since it’s not a library per se, but rather sample code that could become a good library.
- AccessControl.rb – helper library for using ACS v2 from Ruby to acquire Simple Web Tokens used in communicating with Queues.
-
Program.rb – a simple console application that walks thru all operations you might want to perform with Queues using REST:
- Authenticating with ACS to get a Simple Web Token
- Creating a new Queue
- Getting a single Queue Description
- Enumerating all Queues
- Sending a message to a Queue
- Atomically receiving and deleting the message
- Peek lock receiving a message
- Unlocking a peek-locked message
- Deleting a peek-locked message
- Deleting a Queue
- How to enable communication inspection with Fiddler by configuring the proxy
Note that the sample library is focused on using simple Queues and does not demonstrate how to use Topics or Subscriptions (though it is readily extended to this).
Sidebar – What about IronRuby?
IronRuby 1.1.3 provides Visual Studio integration for Ruby 1.9.2, but it does not implement the complete Ruby specification- and the limitations prevent running our sample code. You can, however, benefit from the syntax coloring and project templates by installing IronRuby and using it to edit your code or to read thru the samples we provide– just be sure to run your code using a more complete Ruby interpreter (like the one from RubyInstaller.org). An interesting aside, if you prefer to use IronRuby, you *could* theoretically use the .NET client assemblies for the Service Bus (as IronRuby enables you to call .NET code from Ruby), so you would probably not use the Rest Client we demonstrate here. For convenience, we include the sample code as an IronRuby project as well.
Sidebar – Can you run Ruby within Windows Azure?
What’s more, if you want to cloud host this code (or any Ruby on Rails application) you are completely able to within a Windows Azure Worker Role. I do plan to provide the sample code in a future blog, for now I list out the general steps below:
- Create a Visual Studio Cloud Project
- Include the Rails Application & Ruby Runtime Binaries in the Role (or install the runtime with a startup task)
- Create RoleEntryPoint that launches a Process which executes the ruby program or web server (like WEBrick) and keeps it alive (it can simply periodically check if the process is still running).
- Configure input endpoints to map to the ports on which the web server (e.g., WEBrick) is listening.
The link http://archive.msdn.microsoft.com/railsonazure has some additional details around this.
Send and Receive Communication
Let’s take a closer look at how communication actually happens in order for both the Ruby on Rails web application and the worker process to communicate with the Service Bus Queue in the manner described in the over view. The AppFabric Queues offer two approaches for receiving data from a Queue: one that retrieves and deletes the messages in a single operation and another that that enables you to lock a message and decide later whether to delete it or return it to the queue. We will look at both but begin by looking at the simpler case which retrieves and deletes a message from the queue as a single operation as shown in the figure below. The details of each step will be described in the sections that follow.
- ACS is the security mechanism for controlling interaction with the Service Bus. The Ruby logic running within the Rails web app needs to acquire an Access Token from the AppFabric Access Control service in order to use the Service Bus.
- ACS returns the token in the form of a Simple Web Token within the body of the response.
- The Ruby logic needs to extract just the WRAP SWT from the response and place it in the Authorization header when making a POST against the Queue. The payload of the message is wrapped in an entry and sent as the body of the POST.
- If successful, the Queue returns a 201 Created status code.
- Meanwhile, the Worker Process running some Ruby code also needs to request an access token from ACS.
- ACS provides the SWT in the same way as before.
- To retrieve and delete a message as an atomic operation, the worker process sends a DELETE request to the Queue, including the access token in the authorization header.
- When a message is present, a response with a code of 200 OK is returned, along with a body that contains the entry payload. The worker process can then take action on this message, which is no longer present in the queue.
Let’s take a look at the details behind this pattern of communication, starting with the authentication with ACS.
Authenticating via ACS
Before you can make your first call against AppFabric Queues, you will need to be able to authenticate with ACS. Let’s take a look at what it takes to perform some basic authentication with ACS using Ruby. The approach is to use ACS’s support for Simple Web Tokens.
This amounts to constructing a request that looks like the following:
Sample ACS Token Request
POST https://rubytest-sb.accesscontrol.appfabriclabs.com/WRAPv0.9/ HTTP/1.1
Accept: */*; q=0.5, application/xml
Content-Type: application/x-www-form-urlencoded
Accept-Encoding: gzip, deflate
Content-Length: 140
Host: rubytest-sb.accesscontrol.appfabriclabs.com
wrap_name=owner&wrap_password=xwCOTgOHT%2Fw8daI9mhCA8Vm0SlKYPKZojYfYCafsRaU%3D&wrap_scope=http%3A%2F%2Frubytest.servicebus.appfabriclabs.com
Within this request the key items are to:
- Use a POST verb
- Set the Content-Type header to:
application/x-www-form-urlencoded - Target the WRAP endpoint of ACS, at:
https://{serviceNamespace}-sb.accesscontrol.appfabriclabs.com/WRAPv0.9/
- Include your namespace’s Issuer as the wrap_name in the body
- Include your namespace’s Key as wrap_password in the body.
- Include your namespace as the wrap_scope in the body.
Next, you need to extract the token from the response. The complete response looks like the following:
Sample ACS Token Response
HTTP/1.1 200 OK
Cache-Control: private
Content-Type: application/x-www-form-urlencoded; charset=us-ascii
Server: Microsoft-IIS/7.0
Set-Cookie: ASP.NET_SessionId=sjnd1145ejbpynmkcmtdlj55; path=/; HttpOnly
X-AspNetMvc-Version: 2.0
X-AspNet-Version: 2.0.50727
X-Powered-By: ASP.NET
Date: Mon, 30 May 2011 19:08:48 GMT
Content-Length: 544
wrap_access_token=net.windows.servicebus.action%3dListen%252cManage%252cSend%26http%253a%252f%252fschemas.microsoft.com%252faccesscontrolservice%252f2010%252f07%252fclaims%252fidentityprovider%3dhttps%253a%252f%252frubytest-sb.accesscontrol.appfabriclabs.com%252f%26Audience%3dhttp%253a%252f%252frubytest.servicebus.appfabriclabs.com%26ExpiresOn%3d1306783728%26Issuer%3dhttps%253a%252f%252frubytest-sb.accesscontrol.appfabriclabs.com%252f%26HMACSHA256%3d7u4ZYF2M%252fX8qLg2meV2xASQT00np536D6JaSEKjAB%252bI%253d&wrap_access_token_expires_in=1200
The value you are after for the access token is only the portion that follows wrap_access_token and does not include the wrap_access_token_expires value. You also have to URL-decode this value. From the previous request, the final decoded SWT value we are after looks like:
net.windows.servicebus.action=Listen%2cManage%2cSend&http%3a%2f%2fschemas.microsoft.com%2faccesscontrolservice%2f2010%2f07%2fclaims%2fidentityprovider=https%3a%2f%2frubytest-sb.accesscontrol.appfabriclabs.com%2f&Audience=http%3a%2f%2frubytest.servicebus.appfabriclabs.com&ExpiresOn=1306783739&Issuer=https%3a%2f%2frubytest-sb.accesscontrol.appfabriclabs.com%2f&HMACSHA256=ebfBpf%2fCKEoIxEqXzFtImTv2Z8Zk9NhqHvtjB%2fKv8b0%3d
Ruby Code
The Ruby code which implements this request and extracts the token from the response is shown in the complete listing for the AccessControl.rb (shown at the end of this blog). Getting a token from ACS in Ruby, then amounts to making the following calls (from Program.rb):
scopeUri = WAZ::AppFabric::AccessControl.get_scope(serviceNamespace)
accessToken = WAZ::AppFabric::AccessControl.get_access_token(serviceNamespace, scopeUri, serviceIdentityName, serviceIdentityPassword)
With this, we have the token necessary to begin communicating with the Queue. Note that these tokens eventually expire, so if you will be caching this value, you may have to build logic to periodically renew the token by repeating the request.
Queue Runtime – Sending Messages
Now the application is ready to send messages to the queue. This amounts to constructing a request that looks like the following:
Sample Send to Queue Request
POST https://rubytest.servicebus.appfabriclabs.com/testqueue/messages HTTP/1.1
Accept: */*; q=0.5, application/xml
Content-Type: application/atom+xml;type=entry;charset=utf-8
Accept-Encoding: gzip, deflate
Authorization: WRAP access_token=”net.windows.servicebus.action=Listen%2cManage%2cSend&http%3a%2f%2fschemas.microsoft.com%2faccesscontrolservice%2f2010%2f07%2fclaims%2fidentityprovider=https%3a%2f%2frubytest-sb.accesscontrol.appfabriclabs.com%2f&Audience=http%3a%2f%2frubytest.servicebus.appfabriclabs.com&ExpiresOn=1306783739&Issuer=https%3a%2f%2frubytest-sb.accesscontrol.appfabriclabs.com%2f&HMACSHA256=ebfBpf%2fCKEoIxEqXzFtImTv2Z8Zk9NhqHvtjB%2fKv8b0%3d”
Content-Length: 110
Host: rubytest.servicebus.appfabriclabs.com
<entry xmlns=’http://www.w3.org/2005/Atom’><content type=’application/xml’>Hello, from Ruby!</content></entry>
Within this request the key steps are to:
- Use the POST verb
- Set the Content-Type header to:
application/atom+xml;type=entry;charset=utf-8 - Target the queue by name by posting to:
https://{serviceNamespace}.servicebus.appfabriclabs.com/{queueName}/messages
- Include the previously acquired access token in the Authorization header. This has a very particular form for the value which is (note the space after WRAP, it’s not an underscore):
WRAP access_token=”{access token value}” - The body of the request needs to include the message content in an envelope that looks like the following:
<entry xmlns=’http://www.w3.org/2005/Atom’>
<content type=’application/xml’>
{message content}
</content>
</entry>
A successful response to this will take the following form:
Sample Send to Queue Response
HTTP/1.1 201 Created
Content-Type: application/xml; charset=utf-8
Server: Microsoft-HTTPAPI/2.0
Date: Mon, 30 May 2011 19:08:59 GMT
Content-Length: 0
Ruby Code
The implementation for this is straightforward, consisting of the send, generate_send_request_uri, generate_queue_payload and generate_request as shown in the full listing of QueueClient.rb (provided at the end of this blog). Therefore sending a message to the AppFabric Queue from Ruby simply becomes this (as shown in Program.rb):
sendMessageResponse = WAZ::AppFabric::QueueClient.send(serviceNamespace, queueName, accessToken,
‘Hello, from Ruby!’)
Queue Runtime – Receiving Messages
Now that we have a message in the queue, our worker process will need to be able to retrieve it. As we said previously, there are two approaches.
Receive & Delete Retrieval
Here we show how to retrieve and delete the message in a single operation. This is accomplished by making a request of the following form:
Sample Receive & Delete Request
DELETE https://rubytest.servicebus.appfabriclabs.com/testqueue/messages/head?timeout=60 HTTP/1.1
Accept: */*; q=0.5, application/xml
Accept-Encoding: gzip, deflate
Authorization: WRAP access_token=”net.windows.servicebus.action=Listen%2cManage%2cSend&http%3a%2f%2fschemas.microsoft.com%2faccesscontrolservice%2f2010%2f07%2fclaims%2fidentityprovider=https%3a%2f%2frubytest-sb.accesscontrol.appfabriclabs.com%2f&Audience=http%3a%2f%2frubytest.servicebus.appfabriclabs.com&ExpiresOn=1306783739&Issuer=https%3a%2f%2frubytest-sb.accesscontrol.appfabriclabs.com%2f&HMACSHA256=ebfBpf%2fCKEoIxEqXzFtImTv2Z8Zk9NhqHvtjB%2fKv8b0%3d”
Content-Length: 0
Host: rubytest.servicebus.appfabriclabs.com
The key points to structuring this request are:
- Use the DELETE verb
- Target the head of the messages in the desired queue by submitting to the following URL. The timeout represents an HTTP long polling feature where the server will hold the request waiting for a message to appear until the specified time elapses. The timeout value is specified as an integer without units (like “30″ for a thirty second timeout).
https://{serviceNamespace}.servicebus.appfabriclabs.com/{queueName}/messages/head?timeout={time}
- Include the previously acquired access token in the Authorization header.
A successful response to this will include the next message from the head of the queue and take the following form:
Sample Receive & Delete Response
HTTP/1.1 200 OK
Content-Type: application/atom+xml;type=entry;charset=utf-8
Server: Microsoft-HTTPAPI/2.0
X-MS-DELIVERY-COUNT: 0
X-MS-LOCKED-UNTIL: Mon, 30 May 2011 19:09:30 GMT
X-MS-MESSAGE-ID: fa42914d3f7b4a8abc8437d29e9a3c03
X-MS-SEQUENCE-NUMBER: 1
X-MS-SIZE: 110
Date: Mon, 30 May 2011 19:08:59 GMT
Content-Length: 110
<entry xmlns=’http://www.w3.org/2005/Atom’><content type=’application/xml’>Hello, from Ruby!</content></entry>
Ruby Code
Our sample library shows this approach in Ruby, as implemented by the receive method in QueueClient.rb (shown in the complete listing at the end of this blog). With that in place, using Ruby to retrieve and delete a message looks like the following:
receiveMessageResponse = WAZ::AppFabric::QueueClient.receive(serviceNamespace, queueName, accessToken)
Peek-Lock Retrieval
Now, let’s look at an alternative approach to retrieving a message, whereby the worker process instead must explicitly delete the message when it has completed its processing. Moreover, it only has a specific window of time (say 30 seconds) in which to delete the message or the Queue automatically makes the message available to another caller (as you might desire in case the worker process that originally acquired the message crashed before completion). If the worker process determines it cannot process the message, it could elect to unlock the message and thereby explicitly release the message back into the queue (perhaps for another attempt). This form of retrieving a message is referred to as a Peek-Lock and completion is signaled by a call to Delete the Peek Locked Message and releasing the message by calling Unlock.
Let’s start with the approach for Peek-Lock retrieval. This is a request that takes the form:
Sample Peek-Locked Request
POST https://rubytest.servicebus.appfabriclabs.com/testqueue/messages/head?timeout=60 HTTP/1.1
Accept: */*; q=0.5, application/xml
Accept-Encoding: gzip, deflate
Authorization: WRAP access_token=”net.windows.servicebus.action=Listen%2cManage%2cSend&http%3a%2f%2fschemas.microsoft.com%2faccesscontrolservice%2f2010%2f07%2fclaims%2fidentityprovider=https%3a%2f%2frubytest-sb.accesscontrol.appfabriclabs.com%2f&Audience=http%3a%2f%2frubytest.servicebus.appfabriclabs.com&ExpiresOn=1306783739&Issuer=https%3a%2f%2frubytest-sb.accesscontrol.appfabriclabs.com%2f&HMACSHA256=ebfBpf%2fCKEoIxEqXzFtImTv2Z8Zk9NhqHvtjB%2fKv8b0%3d”
Content-Length: 0
Host: rubytest.servicebus.appfabriclabs.com
Within this request, the key steps are:
- Use the POST verb
- Target the head of the messages in the desired queue by submitting to the following URL (it’s the same URL used by the Receive and Delete). Again specify a timeout for HTTP long polling:
https://{serviceNamespace}.servicebus.appfabriclabs.com/{queueName}/messages/head?timeout={time}
- Include the previously acquired access token in the Authorization header.
A successful request, when a message is present, will return a response similar to the following:
Sample Peek-Locked Response
HTTP/1.1 200 OK
Content-Type: application/atom+xml;type=entry;charset=utf-8
Server: Microsoft-HTTPAPI/2.0
X-MS-MESSAGE-LOCATION: https://rubytest.servicebus.appfabriclabs.com/testqueue/Messages/5743357095e34fe59cf8f9d9b16366ea
X-MS-LOCK-ID: 0c23bb07-1ffb-4c9d-89a0-ed7d3df2c71f
X-MS-LOCK-LOCATION: https://rubytest.servicebus.appfabriclabs.com/testqueue/Messages/5743357095e34fe59cf8f9d9b16366ea/0c23bb07-1ffb-4c9d-89a0-ed7d3df2c71f
X-MS-DELIVERY-COUNT: 0
X-MS-LOCKED-UNTIL: Mon, 30 May 2011 19:09:30 GMT
X-MS-MESSAGE-ID: 5743357095e34fe59cf8f9d9b16366ea
X-MS-SEQUENCE-NUMBER: 2
X-MS-SIZE: 110
Date: Mon, 30 May 2011 19:08:59 GMT
Content-Length: 110
<entry xmlns=’http://www.w3.org/2005/Atom’><content type=’application/xml’>Hello, from Ruby!</content></entry>
Before you move on to processing the message body, you should capture the values of the X-MS-MESSAGE-ID and X-MS-LOCK-ID headers. Then go ahead and process the message body. When you have completed processing successfully (and want to delete the peek-locked message from the queue), you need to send a request similar to the following:
Sample Delete Request
Accept: */*; q=0.5, application/xml
Accept-Encoding: gzip, deflate
Authorization: WRAP access_token=”net.windows.servicebus.action=Listen%2cManage%2cSend&http%3a%2f%2fschemas.microsoft.com%2faccesscontrolservice%2f2010%2f07%2fclaims%2fidentityprovider=https%3a%2f%2frubytest-sb.accesscontrol.appfabriclabs.com%2f&Audience=http%3a%2f%2frubytest.servicebus.appfabriclabs.com&ExpiresOn=1306783739&Issuer=https%3a%2f%2frubytest-sb.accesscontrol.appfabriclabs.com%2f&HMACSHA256=ebfBpf%2fCKEoIxEqXzFtImTv2Z8Zk9NhqHvtjB%2fKv8b0%3d”
Content-Length: 0
Host: rubytest.servicebus.appfabriclabs.com
The key parts to constructing this request are:
- Use the DELETE verb
- Target the specific message and lock by providing the message id and lock id values captured previously in the request URL:
https://{serviceNamespace}.servicebus.appfabriclabs.com/{queuePath}/messages/{messageId}?lockId={lockId}
- Include the previously acquired access token in the Authorization header.
A successful response to this request should be of the form:
Sample Delete Peek-Locked Message Response
HTTP/1.1 200 OK
Content-Type: application/xml; charset=utf-8
Server: Microsoft-HTTPAPI/2.0
Date: Mon, 30 May 2011 19:09:00 GMT
Content-Length: 0
Ruby Code
The QueueClient.rb with its peekLock and deletePeekedMessage methods implement this logic in Ruby. Using the QueueClient then takes the following pattern (from Program.rb):
peeklockMessageResponse = WAZ::AppFabric::QueueClient.peeklock(serviceNamespace, queueName, accessToken)
messageId = peeklockMessageResponse.headers[:x_ms_message_id]
lockId = peeklockMessageResponse.headers[:x_ms_lock_id]
deletelockedMessageResponse = WAZ::AppFabric::QueueClient.deletePeekedMessage(serviceNamespace, queueName, accessToken, messageId, lockId)
If instead of deleting the message, you wish to unlock it, you must send a request of the form:
Sample Unlock Request
Accept: */*; q=0.5, application/xml
Accept-Encoding: gzip, deflate
Authorization: WRAP access_token=”net.windows.servicebus.action=Listen%2cManage%2cSend&http%3a%2f%2fschemas.microsoft.com%2faccesscontrolservice%2f2010%2f07%2fclaims%2fidentityprovider=https%3a%2f%2frubytest-sb.accesscontrol.appfabriclabs.com%2f&Audience=http%3a%2f%2frubytest.servicebus.appfabriclabs.com&ExpiresOn=1306783739&Issuer=https%3a%2f%2frubytest-sb.accesscontrol.appfabriclabs.com%2f&HMACSHA256=ebfBpf%2fCKEoIxEqXzFtImTv2Z8Zk9NhqHvtjB%2fKv8b0%3d”
Content-Length: 0
Host: rubytest.servicebus.appfabriclabs.com
The key parts to this request are:
- Use the DELETE verb
- Target a slightly different URL which names both the message id and lock id previously acquired. Notice it includes the lock id in the path instead of as a query parameter as was done for deleting a peek locked message:
https://{serviceNamespace}.servicebus.appfabriclabs.com/{queuePath}/messages/{messageId}/{lockId}
- Include the previously acquired access token in the Authorization header.
The successful response to this request is the same (HTTP 200 OK) as that shown for the Delete Peek-Locked Message.
Ruby Code
Again, the QueueClient.rb shows the complete Ruby implementation, you would call it as follows (as shown in Program.rb):
peeklockMessageResponse = WAZ::AppFabric::QueueClient.peeklock(serviceNamespace, queueName, accessToken)
messageId = peeklockMessageResponse.headers[:x_ms_message_id]
lockId = peeklockMessageResponse.headers[:x_ms_lock_id]
unlockMessageResponse = WAZ::AppFabric::QueueClient.unlockPeekedMessage(serviceNamespace, queueName, accessToken, messageId, lockId)
Queue Management – Creating, Inspecting and Deleting Queues
Beyond enabling run-time operations, the REST API to the Service Bus Queues also enables you to create, delete and inspect queue metadata. Given what we’ve already shown how to use the runtime operations, using these features will appear as old-hat. Requests need to first acquire an access token from ACS and then call the appropriate method. Let’s take a look at these.
Creating Queues
If a purely non-.NET scenario, someone would need to create the queue for our web app or worker process to use.
Creating a queue is performed by building a request as follows:
Sample Creating a Queue Request
PUT https://rubytest.servicebus.appfabriclabs.com/testqueue HTTP/1.1
Accept: */*; q=0.5, application/xml
Content-Type: application/atom+xml;type=entry;charset=utf-8
Accept-Encoding: gzip, deflate
Authorization: WRAP access_token=”net.windows.servicebus.action=Listen%2cManage%2cSend&http%3a%2f%2fschemas.microsoft.com%2faccesscontrolservice%2f2010%2f07%2fclaims%2fidentityprovider=https%3a%2f%2frubytest-sb.accesscontrol.appfabriclabs.com%2f&Audience=http%3a%2f%2frubytest.servicebus.appfabriclabs.com&ExpiresOn=1306783739&Issuer=https%3a%2f%2frubytest-sb.accesscontrol.appfabriclabs.com%2f&HMACSHA256=ebfBpf%2fCKEoIxEqXzFtImTv2Z8Zk9NhqHvtjB%2fKv8b0%3d”
Content-Length: 693
Host: rubytest.servicebus.appfabriclabs.com
<entry xmlns=’http://www.w3.org/2005/Atom’><content type=’application/xml’><QueueDescription xmlns:i=”http://www.w3.org/2001/XMLSchema-instance” xmlns=”http://schemas.microsoft.com/netservices/2010/10/servicebus/connect”> <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>
The key parts to creating a new Queue request are:
- Use the PUT verb
- Target a URL that includes the namespace and name of the queue you wish to create.
https://{serviceNamespace}.servicebus.appfabriclabs.com/{queuePath}
- Include the previously acquired access token in the Authorization header.
- Set the Content-Type to
application/atom+xml;type=entry;charset=utf-8
-
Send a queue description in the body of the message. A queue description has the form (see the MSDN documentation for details on each field):
<entry xmlns=’http://www.w3.org/2005/Atom’>
<content type=’application/xml’>
<QueueDescription xmlns:i=\”http://www.w3.org/2001/XMLSchema-instance\” xmlns=\”http://schemas.microsoft.com/netservices/2010/10/servicebus/connect\”>
<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>
Ruby Code
The logic for queue management is within the QueueManagement.rb file, and create_queue is the method which can be called to create the new Queue. For example, creating a new queue looks as follows in Ruby:
createQueueResponse = WAZ::AppFabric::QueueManagement.create_queue(serviceNamespace, queueName, accessToken)
Queue Descriptions & Enumerating Queues
Once a queue is created, the queue descriptions can be retrieved later. This can be useful to verify configuration or to see the values applied to queues created using default settings.
A request for a particular queue within a namespace is built to the form:
Sample Getting a Queue Description Request
GET https://rubytest.servicebus.appfabriclabs.com/testqueue HTTP/1.1
Accept: */*; q=0.5, application/xml
Accept-Encoding: gzip, deflate
Authorization: WRAP access_token=”net.windows.servicebus.action=Listen%2cManage%2cSend&http%3a%2f%2fschemas.microsoft.com%2faccesscontrolservice%2f2010%2f07%2fclaims%2fidentityprovider=https%3a%2f%2frubytest-sb.accesscontrol.appfabriclabs.com%2f&Audience=http%3a%2f%2frubytest.servicebus.appfabriclabs.com&ExpiresOn=1306783739&Issuer=https%3a%2f%2frubytest-sb.accesscontrol.appfabriclabs.com%2f&HMACSHA256=ebfBpf%2fCKEoIxEqXzFtImTv2Z8Zk9NhqHvtjB%2fKv8b0%3d”
Content-Length: 0
Host: rubytest.servicebus.appfabriclabs.com
The key parts to this request are:
- Use the GET verb
- Target the queue by name:
https://{serviceNamespace}.servicebus.appfabriclabs.com/{queueName}
- Include the previously acquired access token in the Authorization header.
The successful response to this takes the form (notice the queue description in the response body):
Sample Getting a Queue Description Response
HTTP/1.1 200 OK
Content-Type: application/atom+xml;type=entry;charset=utf-8
Server: Microsoft-HTTPAPI/2.0
Date: Mon, 30 May 2011 19:08:59 GMT
Content-Length: 980
<entry xmlns=”http://www.w3.org/2005/Atom”><id>https://rubytest.servicebus.appfabriclabs.com/testqueue</id><title type=”text”>testqueue</title><published>2011-05-30T19:08:58Z</published><updated>2011-05-30T19:08:58Z</updated><author><name>rubytest</name></author><link rel=”self” href=”https://rubytest.servicebus.appfabriclabs.com/testqueue”/><content type=”application/xml”><QueueDescription xmlns=”http://schemas.microsoft.com/netservices/2010/10/servicebus/connect” xmlns:i=”http://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>
Similarly, a list of descriptions for all queues at a certain point in the namespace’s hierarchy can be achieved with:
Sample Enumerating All Queue Descriptions Request
GET https://rubytest.servicebus.appfabriclabs.com/$Resources/Queues HTTP/1.1
Accept: */*; q=0.5, application/xml
Accept-Encoding: gzip, deflate
Authorization: WRAP access_token=”net.windows.servicebus.action=Listen%2cManage%2cSend&http%3a%2f%2fschemas.microsoft.com%2faccesscontrolservice%2f2010%2f07%2fclaims%2fidentityprovider=https%3a%2f%2frubytest-sb.accesscontrol.appfabriclabs.com%2f&Audience=http%3a%2f%2frubytest.servicebus.appfabriclabs.com&ExpiresOn=1306783739&Issuer=https%3a%2f%2frubytest-sb.accesscontrol.appfabriclabs.com%2f&HMACSHA256=ebfBpf%2fCKEoIxEqXzFtImTv2Z8Zk9NhqHvtjB%2fKv8b0%3d”
Content-Length: 0
Host: rubytest.servicebus.appfabriclabs.com
The key parts to this request are:
- Use the GET verb
- Target the special $Resources/Queues path
https://{serviceNamespace}.servicebus.appfabriclabs.com/$Resources/Queues
-
Include the previously acquired access token in the Authorization header.
The successful response to this contains all the queue descriptions for that level in the namespace hierarchy:
Sample Enumerating All Queue Descriptions Response
HTTP/1.1 200 OK
Content-Type: application/atom+xml;type=feed;charset=utf-8
Server: Microsoft-HTTPAPI/2.0
Date: Mon, 30 May 2011 19:08:59 GMT
Content-Length: 1258
<feed xmlns=”http://www.w3.org/2005/Atom”><title type=”text”>Queues</title><id>https://rubytest.servicebus.appfabriclabs.com/$Resources/Queues</id><updated>2011-05-30T19:08:59Z</updated><link rel=”self” href=”https://rubytest.servicebus.appfabriclabs.com/$Resources/Queues”/><entry xml:base=”https://rubytest.servicebus.appfabriclabs.com/$Resources/Queues”><id>https://rubytest.servicebus.appfabriclabs.com/testqueue</id><title type=”text”>testqueue</title><published>2011-05-30T19:08:58Z</published><updated>2011-05-30T19:08:58Z</updated><author><name>rubytest</name></author><link rel=”self” href=”../testqueue”/><content type=”application/xml”><QueueDescription xmlns=”http://schemas.microsoft.com/netservices/2010/10/servicebus/connect” xmlns:i=”http://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></feed>
Ruby Code
Within QueueManagement.rb, this logic is exposed by the get_queue and list_queues methods. Their use is as follows:
getQueueResponse = WAZ::AppFabric::QueueManagement.get_queue(serviceNamespace, queueName, accessToken)
listQueuesResponse = WAZ::AppFabric::QueueManagement.list_queues(serviceNamespace, accessToken)
Deleting Queues
There are limits to the number of queues that you can create, and one way to manage that is to delete unused queues.
You delete a queue by creating a request with the following structure:
Sample Delete Queue Request
DELETE https://rubytest.servicebus.appfabriclabs.com/testqueue HTTP/1.1
Accept: */*; q=0.5, application/xml
Accept-Encoding: gzip, deflate
Authorization: WRAP access_token=”net.windows.servicebus.action=Listen%2cManage%2cSend&http%3a%2f%2fschemas.microsoft.com%2faccesscontrolservice%2f2010%2f07%2fclaims%2fidentityprovider=https%3a%2f%2frubytest-sb.accesscontrol.appfabriclabs.com%2f&Audience=http%3a%2f%2frubytest.servicebus.appfabriclabs.com&ExpiresOn=1306783739&Issuer=https%3a%2f%2frubytest-sb.accesscontrol.appfabriclabs.com%2f&HMACSHA256=ebfBpf%2fCKEoIxEqXzFtImTv2Z8Zk9NhqHvtjB%2fKv8b0%3d”
Content-Length: 0
Host: rubytest.servicebus.appfabriclabs.com
The key parts to constructing this request are:
- Use the DELETE verb
- Target the queue by namespace and queue name:
https://{serviceNamespace}.servicebus.appfabriclabs.com/{queueName}
- Include the previously acquired access token in the Authorization header.
The successful response to this request is the same (HTTP 200 OK) as that shown for the Delete Peek-Locked Message.
Ruby Code
Within QueueManagement.rb, this logic is exposed by the delete_queue method and is used as follows:
deleteQueueResponse = WAZ::AppFabric::QueueManagement.delete_queue(serviceNamespace, queueName, accessToken)
Limitations to using REST Clients with Service Bus Queues
Compared to using the AppFabric Service Bus with the .NET client provided by the Azure AppFabric SDK, a REST client has some limitations (in the current CTP form) that apply to more advanced features. For the purposes of sending to and receiving from Queues, Topics or Subscriptions the REST API are simple, powerful and all you need. For details on the specific limitations, see the documentation.
Examining Communication with Fiddler
The source code of Program.rb contains the following line commented out:
###### OPTIONAL: Enable the Fiddler Proxy (if running Fiddler) #########
#RestClient.proxy = “http://127.0.0.1:9999/”
#########################################################################
If you want to use Fiddler debugging proxy to monitor HTTP traffic between your local Ruby application and the AppFabric Queues or ACS, start by installing Fiddler from http://www.fiddler2.com/fiddler2/ and configure the port to listen on in the Fiddler Options (as shown in the screenshot below).
After setting the port, uncomment the RestClient.proxy line in Program.rb and set the port value. For example, if the port is 9999, then the code would look like:
###### OPTIONAL: Enable the Fiddler Proxy (if running Fiddler) #########
RestClient.proxy = “http://127.0.0.1:9999/”
#########################################################################
Note: Port 9999 is more convenient for .NET developers running Azure emulator so that it and Fiddler don’t conflict.
Ruby Source Code
The complete listing for the sample client application in Program.rb and the three files that make up the Queue client library are provided below.
Program.rb
require ‘rubygems’
require ‘rest-client’
require ‘WAZ/AppFabric/AccessControl’
require ‘WAZ/AppFabric/QueueManagement’
require ‘WAZ/AppFabric/QueueClient’
###### ENTER YOUR QUEUE SETTINGS HERE ###################################
serviceNamespace =
“rubytest”
queueName =
‘testqueue’
serviceIdentityName =
“owner”
serviceIdentityPassword =
“xwCOTgOHT/w8daI9mhCA8Vm0SlKYPKZojYfYCafsRaU=”
#########################################################################
###### OPTIONAL: Enable the Fiddler Proxy (if runnning Fiddler) #########
#RestClient.proxy = “http://127.0.0.1:9999/”
#########################################################################
scopeUri = WAZ::AppFabric::AccessControl.get_scope(serviceNamespace)
puts ‘Using scope URI of ‘
+ scopeUri
puts ‘Authenticating via ACS’
accessToken = WAZ::AppFabric::AccessControl.get_access_token(serviceNamespace, scopeUri, serviceIdentityName, serviceIdentityPassword)
puts accessToken
puts ‘Queue Management – Create Queue’
createQueueResponse = WAZ::AppFabric::QueueManagement.create_queue(serviceNamespace, queueName, accessToken)
puts createQueueResponse
puts ‘Queue Management – Get Queue’
getQueueResponse = WAZ::AppFabric::QueueManagement.get_queue(serviceNamespace, queueName, accessToken)
puts getQueueResponse
puts ‘Queue Management – List Queues’
listQueuesResponse = WAZ::AppFabric::QueueManagement.list_queues(serviceNamespace, accessToken)
puts listQueuesResponse
puts ‘Queue Runtime – Sending Messages’
sendMessageResponse = WAZ::AppFabric::QueueClient.send(serviceNamespace, queueName, accessToken,
‘Hello, from Ruby!’)
puts sendMessageResponse
puts ‘Queue Runtime – Receiving Messages’
receiveMessageResponse = WAZ::AppFabric::QueueClient.receive(serviceNamespace, queueName, accessToken)
puts receiveMessageResponse
puts ‘Queue Runtime – Sending Messages [Again]‘
sendMessageResponse = WAZ::AppFabric::QueueClient.send(serviceNamespace, queueName, accessToken,
‘Hello, from Ruby!’)
puts sendMessageResponse
puts ‘Queue Runtime – Peek-Locking Messages’
peeklockMessageResponse = WAZ::AppFabric::QueueClient.peeklock(serviceNamespace, queueName, accessToken)
p peeklockMessageResponse.headers
messageId = peeklockMessageResponse.headers[:x_ms_message_id]
lockId = peeklockMessageResponse.headers[:x_ms_lock_id]
puts ‘Queue Runtime – Unlock-Peeked Messages’
unlockMessageResponse = WAZ::AppFabric::QueueClient.unlockPeekedMessage(serviceNamespace, queueName, accessToken, messageId, lockId)
p unlockMessageResponse
puts ‘Queue Runtime – Peek-Locking Messages [Again]‘
peeklockMessageResponse = WAZ::AppFabric::QueueClient.peeklock(serviceNamespace, queueName, accessToken)
p peeklockMessageResponse.headers
messageId = peeklockMessageResponse.headers[:x_ms_message_id]
lockId = peeklockMessageResponse.headers[:x_ms_lock_id]
puts ‘Queue Runtime – Delete-Peeked Messages’
deletelockedMessageResponse = WAZ::AppFabric::QueueClient.deletePeekedMessage(serviceNamespace, queueName, accessToken, messageId, lockId)
p deletelockedMessageResponse
puts ‘Queue Management – Delete Queue’
deleteQueueResponse = WAZ::AppFabric::QueueManagement.delete_queue(serviceNamespace, queueName, accessToken)
puts deleteQueueResponse
AccessControl.rb
module WAZ
module AppFabric
class AccessControl
def
self.get_access_token(serviceNamespace, scopeUri, serviceIdentityName, serviceIdentityPassword)
url = generate_request_uri(serviceNamespace)
request = generate_request(:post, url, scopeUri, serviceIdentityName, serviceIdentityPassword)
result = request.execute()
/wrap_access_token=(.+)&/
=~ result
return CGI.unescape(Regexp.last_match[1])
end
def
self.get_scope(serviceNamespace)
return
“http://#{serviceNamespace}.servicebus.appfabriclabs.com”
end
#############################################################
# private methods
private
def
self.generate_request_uri(serviceNamespace)
#url must include WRAP path or will be redirected to broken page
return
“https://#{serviceNamespace}-sb.accesscontrol.appfabriclabs.com/WRAPv0.9/”
end
def
self.generate_request(verb, url, scopeUri, serviceIdentityName, serviceIdentityPassword)
payload =
“wrap_name=#{CGI.escape(serviceIdentityName)}&wrap_password=#{CGI.escape(serviceIdentityPassword)}&wrap_scope=#{CGI.escape(scopeUri)}“
http_headers =
{}
http_headers.merge!(“Content-Type”
=>
“application/x-www-form-urlencoded”)
http_headers.merge!(“Content-Length”
=>
(payload or
“”).size)
request =
{:headers => http_headers, :method => verb.to_s.downcase.to_sym, :url => url, :payload => payload}
return RestClient::Request.new(request)
end
end
end
end
QueueClient.rb
module WAZ
module AppFabric
class QueueClient
def
self.send(serviceNamespace, queueName, accessToken, content)
url = generate_send_request_uri(serviceNamespace, queueName)
contentType =
“application/atom+xml;type=entry;charset=utf-8″
payload = generate_queue_payload(content);
puts payload
request = generate_request(:post, url, accessToken, contentType, payload)
result = request.execute()
return result
end
def
self.receive(serviceNamespace, queueName, accessToken)
url = generate_receive_request_uri(serviceNamespace, queueName,
“60″)
request = generate_request(:delete, url, accessToken,
nil,
nil)
result = request.execute()
return result
end
def
self.peeklock(serviceNamespace, queueName, accessToken)
url = generate_receive_request_uri(serviceNamespace, queueName,
“60″)
request = generate_request(:post, url, accessToken,
nil,
nil)
result = request.execute()
return result
end
def
self.deletePeekedMessage(serviceNamespace, queueName, accessToken, messageId, lockId)
url = generate_deletePeekedMessage_request_uri(serviceNamespace, queueName, messageId, lockId)
request = generate_request(:delete, url, accessToken,
nil,
nil)
result = request.execute()
return result
end
def
self.unlockPeekedMessage(serviceNamespace, queueName, accessToken, messageId, lockId)
url = generate_unlockMessage_request_uri(serviceNamespace, queueName, messageId, lockId)
request = generate_request(:delete, url, accessToken,
nil,
nil)
result = request.execute()
return result
end
#############################################################
# private methods
private
def
self.generate_send_request_uri(serviceNamespace, queuePath)
return
“https://#{serviceNamespace}.servicebus.appfabriclabs.com/#{queuePath}/messages”
end
def
self.generate_receive_request_uri(serviceNamespace, queuePath, timeout)
return
“https://#{serviceNamespace}.servicebus.appfabriclabs.com/#{queuePath}/messages/head?timeout=#{timeout}“
end
def
self.generate_deletePeekedMessage_request_uri(serviceNamespace, queuePath, messageId, lockId)
return
“https://#{serviceNamespace}.servicebus.appfabriclabs.com/#{queuePath}/messages/#{messageId}?lockId=#{lockId}“
end
def
self.generate_unlockMessage_request_uri(serviceNamespace, queuePath, messageId, lockId)
return
“https://#{serviceNamespace}.servicebus.appfabriclabs.com/#{queuePath}/messages/#{messageId}/#{lockId}“
end
def
self.generate_queue_payload(content)
return
“<entry xmlns=’http://www.w3.org/2005/Atom’>”
+
“<content type=’application/xml’>”
+
content +
“</content>”
+
“</entry>”
end
def
self.generate_request(verb, url, token, contentType, payload)
authHeaderValue =
“WRAP access_token=\”#{token}\”"
http_headers =
{}
http_headers.merge!(“Authorization”
=> authHeaderValue)
if
(contentType)
http_headers.merge!(“Content-Type”
=> contentType)
end
http_headers.merge!(“Content-Length”
=>
(payload or
“”).size)
request =
{:headers => http_headers, :method => verb.to_s.downcase.to_sym, :url => url, :payload => payload}
return RestClient::Request.new(request)
end
end
end
end
QueueManagement.rb
module WAZ
module AppFabric
class QueueManagement
def
self.create_queue(serviceNamespace, queueName, accessToken)
url = generate_request_uri(serviceNamespace, queueName)
payload = generate_queue_description();
contentType =
“application/atom+xml;type=entry;charset=utf-8″
request = generate_request(:put, url, accessToken, contentType, payload)
result = request.execute()
return result
end
def
self.delete_queue(serviceNamespace, queueName, accessToken)
url = generate_request_uri(serviceNamespace, queueName)
request = generate_request(:delete, url, accessToken,
nil,
nil)
result = request.execute()
return result
end
def
self.get_queue(serviceNamespace, queueName, accessToken)
url = generate_request_uri(serviceNamespace, queueName)
request = generate_request(:get, url, accessToken,
nil,
nil)
result = request.execute()
return result
end
def
self.list_queues(serviceNamespace, accessToken)
url = generate_list_request_uri(serviceNamespace)
request = generate_request(:get, url, accessToken,
nil,
nil)
result = request.execute()
return result
end
#############################################################
# private methods
private
def
self.generate_request_uri(serviceNamespace, queuePath)
return
“https://#{serviceNamespace}.servicebus.appfabriclabs.com/#{queuePath}“
end
def
self.generate_list_request_uri(serviceNamespace)
return
“https://#{serviceNamespace}.servicebus.appfabriclabs.com/$Resources/Queues”
end
def
self.generate_queue_description()
return
“<entry xmlns=’http://www.w3.org/2005/Atom’>”
+
“<content type=’application/xml’>”
+
“<QueueDescription xmlns:i=\”http://www.w3.org/2001/XMLSchema-instance\” xmlns=\”http://schemas.microsoft.com/netservices/2010/10/servicebus/connect\”>”
+
” <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>”
end
def
self.generate_request(verb, url, token, contentType, payload)
authHeaderValue =
“WRAP access_token=\”#{token}\”"
http_headers =
{}
http_headers.merge!(“Authorization”
=> authHeaderValue)
if
(contentType)
http_headers.merge!(“Content-Type”
=> contentType)
end
http_headers.merge!(“Content-Length”
=>
(payload or
“”).size)
request =
{:headers => http_headers, :method => verb.to_s.downcase.to_sym, :url => url, :payload => payload}
return RestClient::Request.new(request)
end
end
end
end
Sample Code
Available for download from here:
- Stand-alone Ruby files
- IronRuby
Conclusion
The blog article shows how to access Service Bus Queues from Ruby using the sample. Additionally the article also provides information on obtaining authentication tokens from Windows Azure AppFabric ACS, as operations against the AppFabric Service Bus require authentication.
Acknowledgements
Significant contributions of Manuel Ocampo, Larry Franks, Tim Wieman, Valery Mizonov and Zoiner Tejada are acknowledged.
नमस्ते (Namaste)!
One Comment
Leave a Reply
You must be logged in to post a comment.














(2 votes, average: 4.00 out of 5)
Pingback: Windows Azure and Cloud Computing Posts for 7/11/2011+ - Windows Azure Blog