You've already forked linux-packaging-mono
Imported Upstream version 4.6.0.125
Former-commit-id: a2155e9bd80020e49e72e86c44da02a8ac0e57a4
This commit is contained in:
parent
a569aebcfd
commit
e79aa3c0ed
@ -0,0 +1,210 @@
|
||||
// <copyright>
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// </copyright>
|
||||
|
||||
namespace System.ServiceModel.Channels
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Runtime;
|
||||
using System.Text;
|
||||
|
||||
internal class HttpHeaderInfo
|
||||
{
|
||||
private static readonly HttpHeaderInfo[] knownContentHeaders = new HttpHeaderInfo[]
|
||||
{
|
||||
new HttpHeaderInfo("Allow") { IsContentHeader = true },
|
||||
new HttpHeaderInfo("Content-Encoding") { IsContentHeader = true },
|
||||
new HttpHeaderInfo("Content-Language") { IsContentHeader = true },
|
||||
new HttpHeaderInfo("Content-Length") { IsContentHeader = true },
|
||||
new HttpHeaderInfo("Content-Location") { IsContentHeader = true },
|
||||
new HttpHeaderInfo("Content-MD5") { IsContentHeader = true },
|
||||
new HttpHeaderInfo("Content-Range") { IsContentHeader = true },
|
||||
new HttpHeaderInfo("Content-Type") { IsContentHeader = true },
|
||||
new HttpHeaderInfo("Expires") { IsContentHeader = true },
|
||||
new HttpHeaderInfo("Last-Modified") { IsContentHeader = true },
|
||||
new HttpHeaderInfo("Content-Disposition") { IsContentHeader = true }
|
||||
};
|
||||
|
||||
private static readonly Type httpRequestHeaderType = typeof(HttpRequestHeader);
|
||||
private static readonly Type httpResponseHeaderType = typeof(HttpResponseHeader);
|
||||
|
||||
private static ConcurrentDictionary<string, HttpHeaderInfo> knownHeadersInfos;
|
||||
|
||||
private bool isUnknownHeader;
|
||||
|
||||
static HttpHeaderInfo()
|
||||
{
|
||||
// Create the known headers list with the content headers
|
||||
knownHeadersInfos = new ConcurrentDictionary<string, HttpHeaderInfo>(
|
||||
knownContentHeaders.ToDictionary(headerInfo => headerInfo.Name),
|
||||
StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
// Add the request and response headers to the known headers list
|
||||
AddKnownHeaders(Enum.GetNames(httpRequestHeaderType).Select(enumString => GetHeaderString(enumString)), true);
|
||||
AddKnownHeaders(Enum.GetNames(httpResponseHeaderType).Select(enumString => GetHeaderString(enumString)), false);
|
||||
}
|
||||
|
||||
private HttpHeaderInfo(string name, bool isUnknownHeader = false)
|
||||
{
|
||||
Fx.Assert(!string.IsNullOrWhiteSpace(name), "The 'name' parameter should not be null or whitespace.");
|
||||
this.Name = name;
|
||||
|
||||
this.isUnknownHeader = isUnknownHeader;
|
||||
if (this.isUnknownHeader)
|
||||
{
|
||||
this.IsRequestHeader = true;
|
||||
this.IsResponseHeader = true;
|
||||
this.IsContentHeader = true;
|
||||
}
|
||||
}
|
||||
|
||||
public string Name { get; private set; }
|
||||
|
||||
public bool IsRequestHeader { get; private set; }
|
||||
|
||||
public bool IsResponseHeader { get; private set; }
|
||||
|
||||
public bool IsContentHeader { get; private set; }
|
||||
|
||||
public static HttpHeaderInfo Create(string headerName)
|
||||
{
|
||||
Fx.Assert(!string.IsNullOrWhiteSpace(headerName), "The 'headerName' should not be null or whitespace.");
|
||||
|
||||
HttpHeaderInfo headerInfo;
|
||||
if (!knownHeadersInfos.TryGetValue(headerName, out headerInfo))
|
||||
{
|
||||
headerInfo = new HttpHeaderInfo(headerName, true);
|
||||
}
|
||||
|
||||
return headerInfo;
|
||||
}
|
||||
|
||||
public bool TryAddHeader(HttpHeaders headers, string value)
|
||||
{
|
||||
Fx.Assert(headers != null, "The 'headers' parameter should never be null.");
|
||||
if (!headers.TryAddWithoutValidation(this.Name, value))
|
||||
{
|
||||
this.UpdateHeaderInfo(headers);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool TryRemoveHeader(HttpHeaders headers)
|
||||
{
|
||||
Fx.Assert(headers != null, "The 'headers' parameter should never be null.");
|
||||
|
||||
try
|
||||
{
|
||||
headers.Remove(this.Name);
|
||||
return true;
|
||||
}
|
||||
catch (InvalidOperationException ex)
|
||||
{
|
||||
FxTrace.Exception.TraceHandledException(ex, TraceEventType.Information);
|
||||
this.UpdateHeaderInfo(headers);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public IEnumerable<string> TryGetHeader(HttpHeaders headers)
|
||||
{
|
||||
Fx.Assert(headers != null, "The 'headers' parameter should never be null.");
|
||||
|
||||
IEnumerable<string> values = null;
|
||||
|
||||
if (!headers.TryGetValues(this.Name, out values))
|
||||
{
|
||||
values = null;
|
||||
this.UpdateHeaderInfo(headers);
|
||||
}
|
||||
|
||||
return values;
|
||||
}
|
||||
|
||||
private static void AddKnownHeaders(IEnumerable<string> headers, bool asRequestHeader)
|
||||
{
|
||||
foreach (string header in headers)
|
||||
{
|
||||
HttpHeaderInfo headerInfo = null;
|
||||
if (knownHeadersInfos.TryGetValue(header, out headerInfo))
|
||||
{
|
||||
if (headerInfo.IsContentHeader)
|
||||
{
|
||||
// this header is actually a content header so continue
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (headerInfo == null)
|
||||
{
|
||||
headerInfo = new HttpHeaderInfo(header);
|
||||
knownHeadersInfos.TryAdd(headerInfo.Name, headerInfo);
|
||||
}
|
||||
|
||||
if (asRequestHeader)
|
||||
{
|
||||
headerInfo.IsRequestHeader = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
headerInfo.IsResponseHeader = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static string GetHeaderString(string headerEnumString)
|
||||
{
|
||||
// Have to special case 'ETag' as it should not be hypenated
|
||||
if (string.Equals(headerEnumString, HttpResponseHeader.ETag.ToString(), StringComparison.Ordinal))
|
||||
{
|
||||
return headerEnumString;
|
||||
}
|
||||
|
||||
StringBuilder asStringBuilder = new StringBuilder(headerEnumString);
|
||||
|
||||
// Note that we are not considering the first and last characters of the string
|
||||
// as headers never start or end with '-'
|
||||
for (int i = asStringBuilder.Length - 2; i > 0; i--)
|
||||
{
|
||||
if (char.IsUpper(asStringBuilder[i]) && char.IsLower(asStringBuilder[i + 1]))
|
||||
{
|
||||
asStringBuilder.Insert(i, '-');
|
||||
}
|
||||
}
|
||||
|
||||
return asStringBuilder.ToString();
|
||||
}
|
||||
|
||||
private void UpdateHeaderInfo(HttpHeaders headers)
|
||||
{
|
||||
Fx.Assert(headers != null, "The 'headers' parameter should never be null.");
|
||||
|
||||
if (headers is HttpContentHeaders)
|
||||
{
|
||||
this.IsContentHeader = false;
|
||||
}
|
||||
else if (headers is HttpRequestHeaders)
|
||||
{
|
||||
this.IsRequestHeader = false;
|
||||
}
|
||||
else if (headers is HttpResponseHeaders)
|
||||
{
|
||||
this.IsResponseHeader = false;
|
||||
}
|
||||
|
||||
if (this.isUnknownHeader)
|
||||
{
|
||||
this.isUnknownHeader = !knownHeadersInfos.TryAdd(this.Name, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user