internal static string CanonicalizeHttpRequest( Uri address, ResourceUriComponents uriComponents, string method, string contentType, string date, NameValueCollection headers) { // The first element should be the Method of the request. // I.e. GET, POST, PUT, or HEAD. CanonicalizedString canonicalizedString = new CanonicalizedString(method); // The second element should be the MD5 value. // This is optional and may be empty. string httpContentMD5Value = string.Empty; // First extract all the content MD5 values from the header. ArrayList httpContentMD5Values = HttpRequestAccessor.GetHeaderValues(headers, HeaderNames.ContentMD5); // If we only have one, then set it to the value we want to append to the canonicalized string. if (httpContentMD5Values.Count == 1) { httpContentMD5Value = (string)httpContentMD5Values[0]; } canonicalizedString.AppendCanonicalizedElement(httpContentMD5Value); // The third element should be the content type. canonicalizedString.AppendCanonicalizedElement(contentType); // The fourth element should be the request date. // See if there's an storage date header. // If there's one, then don't use the date header. ArrayList httpStorageDateValues = HttpRequestAccessor.GetHeaderValues(headers, HeaderNames.StorageDateTime); if (httpStorageDateValues.Count > 0) { date = null; } canonicalizedString.AppendCanonicalizedElement(date); // Look for header names that start with StorageHttpConstants.HeaderNames.PrefixForStorageHeader // Then sort them in case-insensitive manner. ArrayList httpStorageHeaderNameArray = new ArrayList(); foreach (string key in headers.Keys) { if (key.ToLowerInvariant().StartsWith(HeaderNames.PrefixForStorageHeader, StringComparison.Ordinal)) { httpStorageHeaderNameArray.Add(key.ToLowerInvariant()); } } httpStorageHeaderNameArray.Sort(); // Now go through each header's values in the sorted order and append them to the canonicalized string. foreach (string key in httpStorageHeaderNameArray) { StringBuilder canonicalizedElement = new StringBuilder(key); string delimiter = ":"; ArrayList values = HttpRequestAccessor.GetHeaderValues(headers, key); // Go through values, unfold them, and then append them to the canonicalized element string. foreach (string value in values) { // Unfolding is simply removal of CRLF. string unfoldedValue = value.Replace(ConstChars.CarriageReturnLinefeed, string.Empty); // Append it to the canonicalized element string. canonicalizedElement.Append(delimiter); canonicalizedElement.Append(unfoldedValue); delimiter = ","; } // Now, add this canonicalized element to the canonicalized header string. canonicalizedString.AppendCanonicalizedElement(canonicalizedElement.ToString()); } // Now we append the canonicalized resource element. string canonicalizedResource = GetCanonicalizedResource(address, uriComponents); canonicalizedString.AppendCanonicalizedElement(canonicalizedResource); return(canonicalizedString.Value); }