/// <inheritdoc/>
        public Task <QueuedMessageList> ListMessagesAsync(QueueName queueName, QueuedMessageListId marker, int?limit, bool echo, bool includeClaimed, CancellationToken cancellationToken)
        {
            if (queueName == null)
            {
                throw new ArgumentNullException("queueName");
            }
            if (limit <= 0)
            {
                throw new ArgumentOutOfRangeException("limit");
            }

            UriTemplate template = new UriTemplate("/queues/{queue_name}/messages?marker={marker}&limit={limit}&echo={echo}&include_claimed={include_claimed}");

            var parameters =
                new Dictionary <string, string>()
            {
                { "queue_name", queueName.Value },
                { "echo", echo.ToString() },
                { "include_claimed", includeClaimed.ToString() }
            };

            if (marker != null)
            {
                parameters["marker"] = marker.Value;
            }
            if (limit != null)
            {
                parameters["limit"] = limit.ToString();
            }

            Func <Task <Tuple <IdentityToken, Uri> >, HttpWebRequest> prepareRequest =
                PrepareRequestAsyncFunc(HttpMethod.GET, template, parameters);

            Func <Task <HttpWebRequest>, Task <ListCloudQueueMessagesResponse> > requestResource =
                GetResponseAsyncFunc <ListCloudQueueMessagesResponse>(cancellationToken);

            Func <Task <ListCloudQueueMessagesResponse>, QueuedMessageList> resultSelector =
                task =>
            {
                ReadOnlyCollection <QueuedMessage> messages = null;
                if (task.Result != null)
                {
                    messages = task.Result.Messages;
                }

                QueuedMessageListId nextMarker = null;
                if (task.Result != null && task.Result.Links != null)
                {
                    Link nextLink = task.Result.Links.FirstOrDefault(i => string.Equals(i.Rel, "next", StringComparison.OrdinalIgnoreCase));
                    if (nextLink != null)
                    {
                        Uri baseUri = new Uri("https://example.com");
                        Uri absoluteUri;
                        if (nextLink.Href.StartsWith("/v1"))
                        {
                            absoluteUri = new Uri(baseUri, nextLink.Href.Substring("/v1".Length));
                        }
                        else
                        {
                            absoluteUri = new Uri(baseUri, nextLink.Href);
                        }

                        UriTemplateMatch match = template.Match(baseUri, absoluteUri);
                        if (!string.IsNullOrEmpty(match.BoundVariables["marker"]))
                        {
                            nextMarker = new QueuedMessageListId(match.BoundVariables["marker"]);
                        }
                    }
                }

                if (messages == null || messages.Count == 0)
                {
                    // use the same marker again
                    messages   = messages ?? new ReadOnlyCollection <QueuedMessage>(new QueuedMessage[0]);
                    nextMarker = marker;
                }

                Func <CancellationToken, Task <ReadOnlyCollectionPage <QueuedMessage> > > getNextPageAsync = null;
                if (nextMarker != null || messages.Count == 0)
                {
                    getNextPageAsync =
                        nextCancellationToken => ListMessagesAsync(queueName, nextMarker, limit, echo, includeClaimed, nextCancellationToken)
                        .Select(t => (ReadOnlyCollectionPage <QueuedMessage>)t.Result);
                }

                return(new QueuedMessageList(messages, getNextPageAsync, nextMarker));
            };

            return(AuthenticateServiceAsync(cancellationToken)
                   .Select(prepareRequest)
                   .Then(requestResource)
                   .Select(resultSelector));
        }
        /// <summary>
        /// Gets a list of messages currently in a queue.
        /// </summary>
        /// <param name="queueingService">The queueing service instance.</param>
        /// <param name="queueName">The queue name.</param>
        /// <param name="marker">The identifier of the message list page to return. This is obtained from <see cref="QueuedMessageList.NextPageId"/>. If this value is <see langword="null"/>, the list starts at the beginning.</param>
        /// <param name="limit">The maximum number of messages to return. If this value is <see langword="null"/>, a provider-specific default value is used.</param>
        /// <param name="echo"><see langword="true"/> to include messages created by the current client; otherwise, <see langword="false"/>.</param>
        /// <param name="includeClaimed"><see langword="true"/> to include claimed messages; otherwise <see langword="false"/> to return only unclaimed messages.</param>
        /// <returns>A collection of <see cref="QueuedMessage"/> objects describing the messages in the queue.</returns>
        /// <exception cref="ArgumentNullException">If <paramref name="queueingService"/> is <see langword="null"/>.</exception>
        /// <exception cref="ArgumentNullException">If <paramref name="queueName"/> is <see langword="null"/>.</exception>
        /// <exception cref="ArgumentOutOfRangeException">If <paramref name="limit"/> is less than or equal to 0.</exception>
        /// <exception cref="WebException">If the REST request does not return successfully.</exception>
        /// <seealso href="https://wiki.openstack.org/w/index.php?title=Marconi/specs/api/v1#List_Messages">List Messages (OpenStack Marconi API v1 Blueprint)</seealso>
        public static QueuedMessageList ListMessages(this IQueueingService queueingService, QueueName queueName, QueuedMessageListId marker, int?limit, bool echo, bool includeClaimed)
        {
            if (queueingService == null)
            {
                throw new ArgumentNullException("queueingService");
            }

            try
            {
                return(queueingService.ListMessagesAsync(queueName, marker, limit, echo, includeClaimed, CancellationToken.None).Result);
            }
            catch (AggregateException ex)
            {
                ReadOnlyCollection <Exception> innerExceptions = ex.Flatten().InnerExceptions;
                if (innerExceptions.Count == 1)
                {
                    throw innerExceptions[0];
                }

                throw;
            }
        }