public static bool RegisterPrefix(string prefix, IWebRequestCreate creator)
{
bool Error = false;
int i;
WebRequestPrefixElement Current;
if (prefix == null)
{
throw new ArgumentNullException(nameof(prefix));
}
if (creator == null)
{
throw new ArgumentNullException(nameof(creator));
}
// Lock this object, then walk down PrefixList looking for a place to
// to insert this prefix.
lock (s_internalSyncObject)
{
// Clone the object and update the clone, thus
// allowing other threads to still read from the original.
List<WebRequestPrefixElement> prefixList = new List<WebRequestPrefixElement>(PrefixList);
// As AbsoluteUri is used later for Create, account for formating changes
// like Unicode escaping, default ports, etc.
Uri tempUri;
if (Uri.TryCreate(prefix, UriKind.Absolute, out tempUri))
{
String cookedUri = tempUri.AbsoluteUri;
// Special case for when a partial host matching is requested, drop the added trailing slash
// IE: http://host could match host or host.domain
if (!prefix.EndsWith("/", StringComparison.Ordinal)
&& tempUri.GetComponents(UriComponents.PathAndQuery | UriComponents.Fragment, UriFormat.UriEscaped)
.Equals("/"))
{
cookedUri = cookedUri.Substring(0, cookedUri.Length - 1);
}
prefix = cookedUri;
}
i = 0;
// The prefix list is sorted with longest entries at the front. We
// walk down the list until we find a prefix shorter than this
// one, then we insert in front of it. Along the way we check
// equal length prefixes to make sure this isn't a dupe.
while (i < prefixList.Count)
{
Current = prefixList[i];
// See if the new one is longer than the one we're looking at.
if (prefix.Length > Current.Prefix.Length)
{
// It is. Break out of the loop here.
break;
}
// If these are of equal length, compare them.
if (prefix.Length == Current.Prefix.Length)
{
// They're the same length.
if (string.Equals(Current.Prefix, prefix, StringComparison.OrdinalIgnoreCase))
{
// ...and the strings are identical. This is an error.
Error = true;
break;
}
}
i++;
}
// When we get here either i contains the index to insert at or
// we've had an error, in which case Error is true.
if (!Error)
{
// No error, so insert.
prefixList.Insert(i, new WebRequestPrefixElement(prefix, creator));
// Assign the clone to the static object. Other threads using it
// will have copied the original object already.
PrefixList = prefixList;
}
}
return !Error;
}