static string BuildCanonicalizedResource(IRequest request)
{
// CanonicalResourcePrefix will hold the bucket name if we switched to virtual host addressing
// during request preprocessing (where it would have been removed from ResourcePath)
var sb = new StringBuilder(request.CanonicalResourcePrefix);
sb.Append(!string.IsNullOrEmpty(request.ResourcePath)
? AWSSDKUtils.UrlEncode(request.ResourcePath, true)
: "/");
// form up the set of all subresources and specific query parameters that must be
// included in the canonical resource, then append them ordered by key to the
// canonicalization
var resourcesToSign = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
if (request.SubResources.Count > 0)
{
foreach (var subResource in request.SubResources)
{
if (!SubResourcesSigningExclusion.Contains(subResource.Key))
{
resourcesToSign.Add(subResource.Key, subResource.Value);
}
}
}
if (request.Parameters.Count > 0)
{
foreach (var parameter in request.Parameters)
{
if (parameter.Value != null && SignableParameters.Contains(parameter.Key))
{
resourcesToSign.Add(parameter.Key, parameter.Value);
}
}
}
var delim = "?";
List<KeyValuePair<string, string>> resources = new List<KeyValuePair<string, string>>();
foreach (var kvp in resourcesToSign)
{
resources.Add(kvp);
}
resources.Sort((firstPair, nextPair) =>
{
return string.CompareOrdinal(firstPair.Key, nextPair.Key);
});
foreach (var resourceToSign in resources)
{
sb.AppendFormat("{0}{1}", delim, resourceToSign.Key);
if (resourceToSign.Value != null)
sb.AppendFormat("={0}", resourceToSign.Value);
delim = "&";
}
return sb.ToString();
}
}