Microsoft.Azure.Cosmos/src/Headers/Headers.cs (308 lines of code) (raw):
//------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
//------------------------------------------------------------
namespace Microsoft.Azure.Cosmos
{
using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using Microsoft.Azure.Documents;
using Microsoft.Azure.Documents.Collections;
/// <summary>
/// Header implementation used for Request and Responses
/// </summary>
/// <seealso cref="ResponseMessage"/>
/// <seealso cref="RequestMessage"/>
public class Headers : IEnumerable
{
internal static readonly string SDKSUPPORTEDCAPABILITIES = SDKSupportedCapabilitiesHelpers.GetSDKSupportedCapabilities().ToString(
CultureInfo.InvariantCulture);
internal virtual SubStatusCodes SubStatusCode
{
get => Headers.GetSubStatusCodes(this.SubStatusCodeLiteral);
set => this.SubStatusCodeLiteral = ((uint)value).ToString(CultureInfo.InvariantCulture);
}
/// <summary>
/// Gets the Continuation Token in the current <see cref="ResponseMessage"/>.
/// </summary>
public virtual string ContinuationToken
{
get => this.CosmosMessageHeaders.Continuation;
internal set => this.CosmosMessageHeaders.Continuation = value;
}
/// <summary>
/// Gets or Set the CoorelatedActivityId in the current <see cref="ResponseMessage"/>.
/// </summary>
internal virtual string CorrelatedActivityId
{
get => this.CosmosMessageHeaders.Get(HttpConstants.HttpHeaders.CorrelatedActivityId);
set => this.CosmosMessageHeaders.Set(HttpConstants.HttpHeaders.CorrelatedActivityId, value);
}
/// <summary>
/// Gets the request charge for this request from the Azure Cosmos DB service.
/// </summary>
/// <value>
/// The request charge measured in request units.
/// </value>
public virtual double RequestCharge
{
get
{
string value = this.CosmosMessageHeaders.RequestCharge;
if (value == null)
{
return 0;
}
return double.Parse(value, CultureInfo.InvariantCulture);
}
internal set => this.CosmosMessageHeaders.RequestCharge = value.ToString(CultureInfo.InvariantCulture);
}
/// <summary>
/// Gets the activity ID for the request from the Azure Cosmos DB service.
/// </summary>
/// <value>
/// The activity ID for the request.
/// </value>
public virtual string ActivityId
{
get => this.CosmosMessageHeaders.ActivityId;
internal set => this.CosmosMessageHeaders.ActivityId = value;
}
/// <summary>
/// Gets the entity tag associated with the resource from the Azure Cosmos DB service.
/// </summary>
/// <value>
/// The entity tag associated with the resource.
/// </value>
/// <remarks>
/// ETags are used for concurrency checking when updating resources.
/// </remarks>
public virtual string ETag
{
get => this.CosmosMessageHeaders.ETag;
internal set => this.CosmosMessageHeaders.ETag = value;
}
/// <summary>
/// Gets the Content Type for the current content in the <see cref="ResponseMessage"/>.
/// </summary>
public virtual string ContentType
{
get => this.CosmosMessageHeaders.ContentType;
internal set => this.CosmosMessageHeaders.ContentType = value;
}
/// <summary>
/// Gets the Session Token for the current <see cref="ResponseMessage"/>.
/// </summary>
/// <remarks>
/// Session Token is used along with Session Consistency.
/// </remarks>
public virtual string Session
{
get => this.CosmosMessageHeaders.SessionToken;
internal set => this.CosmosMessageHeaders.SessionToken = value;
}
/// <summary>
/// Gets the Content Length for the current content in the <see cref="ResponseMessage"/>.
/// </summary>
public virtual string ContentLength
{
get => this.CosmosMessageHeaders.ContentLength;
set => this.CosmosMessageHeaders.ContentLength = value;
}
/// <summary>
/// Gets the Location for the current content in the <see cref="ResponseMessage"/>.
/// </summary>
public virtual string Location
{
get => this.CosmosMessageHeaders.Location;
internal set => this.CosmosMessageHeaders.Location = value;
}
internal virtual string SubStatusCodeLiteral
{
get => this.CosmosMessageHeaders.SubStatus;
set => this.CosmosMessageHeaders.SubStatus = value;
}
internal TimeSpan? RetryAfter
{
get => Headers.GetRetryAfter(this.RetryAfterLiteral);
set
{
if (value.HasValue)
{
this.RetryAfterLiteral = value.Value.TotalMilliseconds.ToString(CultureInfo.InvariantCulture);
return;
}
this.RetryAfterLiteral = null;
}
}
internal virtual string Authorization
{
get => this.CosmosMessageHeaders.Authorization;
set => this.CosmosMessageHeaders.Authorization = value;
}
internal virtual string RetryAfterLiteral
{
get => this.CosmosMessageHeaders.RetryAfterInMilliseconds;
set => this.CosmosMessageHeaders.RetryAfterInMilliseconds = value;
}
internal virtual string PartitionKey
{
get => this.CosmosMessageHeaders.PartitionKey;
set => this.CosmosMessageHeaders.PartitionKey = value;
}
internal virtual string OptimisticDirectExecute
{
get => this.CosmosMessageHeaders.OptimisticDirectExecute;
set => this.CosmosMessageHeaders.OptimisticDirectExecute = value;
}
internal virtual string RequiresDistribution
{
get => this.CosmosMessageHeaders.RequiresDistribution;
set => this.CosmosMessageHeaders.RequiresDistribution = value;
}
internal virtual string PartitionKeyRangeId
{
get => this.CosmosMessageHeaders.PartitionKeyRangeId;
set => this.CosmosMessageHeaders.PartitionKeyRangeId = value;
}
internal virtual string IsUpsert
{
get => this.CosmosMessageHeaders.IsUpsert;
set => this.CosmosMessageHeaders.IsUpsert = value;
}
internal virtual string OfferThroughput
{
get => this.CosmosMessageHeaders.OfferThroughput;
set => this.CosmosMessageHeaders.OfferThroughput = value;
}
internal virtual string IfNoneMatch
{
get => this.CosmosMessageHeaders.IfNoneMatch;
set => this.CosmosMessageHeaders.IfNoneMatch = value;
}
internal virtual string PageSize
{
get => this.CosmosMessageHeaders.PageSize;
set => this.CosmosMessageHeaders.PageSize = value;
}
internal virtual string QueryMetricsText
{
get => this.CosmosMessageHeaders.QueryMetrics;
set => this.CosmosMessageHeaders.QueryMetrics = value;
}
internal virtual string IndexUtilizationText
{
get => this.CosmosMessageHeaders.IndexUtilization;
set => this.CosmosMessageHeaders.IndexUtilization = value;
}
internal virtual string QueryAdvice
{
get => this.CosmosMessageHeaders.QueryAdvice;
set => this.CosmosMessageHeaders.QueryAdvice = value;
}
internal virtual string BackendRequestDurationMilliseconds
{
get => this.CosmosMessageHeaders.BackendRequestDurationMilliseconds;
set => this.CosmosMessageHeaders.BackendRequestDurationMilliseconds = value;
}
internal virtual string ConsistencyLevel
{
get => this.CosmosMessageHeaders.ConsistencyLevel;
set => this.CosmosMessageHeaders.ConsistencyLevel = value;
}
internal virtual string SDKSupportedCapabilities
{
get => this.CosmosMessageHeaders.SDKSupportedCapabilities;
set => this.CosmosMessageHeaders.SDKSupportedCapabilities = value;
}
internal virtual string ContentSerializationFormat
{
get => this.CosmosMessageHeaders.ContentSerializationFormat;
set => this.CosmosMessageHeaders.ContentSerializationFormat = value;
}
internal virtual string ReadFeedKeyType
{
get => this.CosmosMessageHeaders.ReadFeedKeyType;
set => this.CosmosMessageHeaders.ReadFeedKeyType = value;
}
internal virtual string StartEpk
{
get => this.CosmosMessageHeaders.StartEpk;
set => this.CosmosMessageHeaders.StartEpk = value;
}
internal virtual string EndEpk
{
get => this.CosmosMessageHeaders.EndEpk;
set => this.CosmosMessageHeaders.EndEpk = value;
}
internal virtual string ItemCount => this.CosmosMessageHeaders.Get(HttpConstants.HttpHeaders.ItemCount);
/// <summary>
/// Creates a new instance of <see cref="Headers"/>.
/// </summary>
public Headers()
{
this.CosmosMessageHeaders = new StoreRequestHeaders();
}
internal Headers(INameValueCollection nameValueCollection)
{
this.CosmosMessageHeaders = nameValueCollection switch
{
StoreResponseNameValueCollection storeResponseNameValueCollection => new StoreResponseHeaders(storeResponseNameValueCollection),
HttpResponseHeadersWrapper httpResponseHeaders => httpResponseHeaders,
_ => new NameValueResponseHeaders(nameValueCollection),
};
}
internal Headers(CosmosMessageHeadersInternal cosmosMessageHeaders)
{
this.CosmosMessageHeaders = cosmosMessageHeaders;
}
/// <summary>
/// Gets the value of a particular header.
/// </summary>
/// <param name="headerName">Header name to look for.</param>
/// <returns>The header value.</returns>
public virtual string this[string headerName]
{
get => this.CosmosMessageHeaders[headerName];
set => this.CosmosMessageHeaders[headerName] = value;
}
/// <summary>
/// Enumerates all the HTTP headers names in the <see cref="Headers"/>.
/// </summary>
/// <returns>An enumerator for all headers.</returns>
public virtual IEnumerator<string> GetEnumerator()
{
foreach (string key in this.CosmosMessageHeaders.AllKeys())
{
yield return key;
}
}
/// <summary>
/// Adds a header to the Header collection.
/// </summary>
/// <param name="headerName">Header name.</param>
/// <param name="value">Header value.</param>
public virtual void Add(string headerName, string value)
{
this.CosmosMessageHeaders.Add(headerName, value);
}
/// <summary>
/// Adds a header to the Header collection.
/// </summary>
/// <param name="headerName">Header name.</param>
/// <param name="values">List of values to be added as a comma-separated list.</param>
public virtual void Add(string headerName, IEnumerable<string> values)
{
this.CosmosMessageHeaders.Add(headerName, values);
}
/// <summary>
/// Adds or updates a header in the Header collection.
/// </summary>
/// <param name="headerName">Header name.</param>
/// <param name="value">Header value.</param>
public virtual void Set(string headerName, string value)
{
this.CosmosMessageHeaders.Set(headerName, value);
}
/// <summary>
/// Gets the value of a particular header.
/// </summary>
/// <param name="headerName">Header name.</param>
/// <returns>The header value.</returns>
public virtual string Get(string headerName)
{
return this.CosmosMessageHeaders.Get(headerName);
}
/// <summary>
/// Tries to get the value for a particular header.
/// </summary>
/// <param name="headerName">Header name.</param>
/// <param name="value">Header value.</param>
/// <returns>True or false if the header name existed in the header collection.</returns>
public virtual bool TryGetValue(string headerName, out string value)
{
return this.CosmosMessageHeaders.TryGetValue(headerName, out value);
}
/// <summary>
/// Returns the header value or the default(string)
/// </summary>
/// <param name="headerName">Header Name</param>
/// <returns>Returns the header value or the default(string).</returns>
public virtual string GetValueOrDefault(string headerName)
{
if (this.TryGetValue(headerName, out string value))
{
return value;
}
return default;
}
/// <summary>
/// Removes a header from the header collection.
/// </summary>
/// <param name="headerName">Header name.</param>
public virtual void Remove(string headerName)
{
this.CosmosMessageHeaders.Remove(headerName);
}
/// <summary>
/// Obtains a list of all header names.
/// </summary>
/// <returns>An array with all the header names.</returns>
public virtual string[] AllKeys()
{
return this.CosmosMessageHeaders.AllKeys();
}
/// <summary>
/// Gets a header value with a particular type.
/// </summary>
/// <typeparam name="T">Type of the header value.</typeparam>
/// <param name="headerName">Header name.</param>
/// <returns>The header value parsed for a particular type.</returns>
public virtual T GetHeaderValue<T>(string headerName)
{
return this.CosmosMessageHeaders.GetHeaderValue<T>(headerName);
}
/// <summary>
/// Clones the current <see cref="Headers"/>.
/// </summary>
/// <returns>a cloned copy of the current <see cref="Headers"/></returns>
internal Headers Clone()
{
Headers clone = new Headers();
foreach (string key in this.CosmosMessageHeaders.AllKeys())
{
clone.Add(key, this.CosmosMessageHeaders.Get(key));
}
return clone;
}
/// <summary>
/// Enumerates all the HTTP headers names in the <see cref="Headers"/>.
/// </summary>
/// <returns>An enumerator for all headers.</returns>
IEnumerator IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
internal string[] GetValues(string key)
{
if (key == null)
{
throw new ArgumentNullException(nameof(key));
}
string value = this[key];
if (value == null)
{
return null;
}
return new string[1] { this[key] };
}
internal CosmosMessageHeadersInternal CosmosMessageHeaders { get; }
internal static int GetIntValueOrDefault(string value)
{
int.TryParse(value, out int number);
return number;
}
internal static SubStatusCodes GetSubStatusCodes(string value)
{
if (uint.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out uint nSubStatus))
{
return (SubStatusCodes)nSubStatus;
}
return SubStatusCodes.Unknown;
}
internal static TimeSpan? GetRetryAfter(string value)
{
if (long.TryParse(value, NumberStyles.Number, CultureInfo.InvariantCulture, out long retryIntervalInMilliseconds))
{
return TimeSpan.FromMilliseconds(retryIntervalInMilliseconds);
}
return null;
}
}
}