Skip to content
This repository has been archived by the owner on Jan 23, 2023. It is now read-only.
/ corefx Public archive

Commit

Permalink
Fix cookie handling in managed implementation
Browse files Browse the repository at this point in the history
Simply reuse the Windows implementation's cookie handling, moving it to a shared file, calling it from the managed, and removing the managed's implementation.
  • Loading branch information
stephentoub committed May 25, 2017
1 parent f135f24 commit 2416022
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 131 deletions.
49 changes: 49 additions & 0 deletions src/System.Net.HttpListener/src/System/Net/HttpListenerResponse.cs
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,55 @@ public void AppendCookie(Cookie cookie)
Cookies.Add(cookie);
}

private void ComputeCookies()
{
if (NetEventSource.IsEnabled) NetEventSource.Info(this, $"Entering Set-Cookie: {Headers[HttpResponseHeader.SetCookie]}, Set-Cookie2: {Headers[HttpKnownHeaderNames.SetCookie2]}");

if (_cookies != null)
{
// now go through the collection, and concatenate all the cookies in per-variant strings
string setCookie2 = null, setCookie = null;
for (int index = 0; index < _cookies.Count; index++)
{
Cookie cookie = _cookies[index];
string cookieString = cookie.ToServerString();
if (cookieString == null || cookieString.Length == 0)
{
continue;
}
if (NetEventSource.IsEnabled) NetEventSource.Info(this, $"Now looking at index:{index} cookie: {cookie}");
if (cookie.IsRfc2965Variant())
{
setCookie2 = setCookie2 == null ? cookieString : setCookie2 + ", " + cookieString;
}
else
{
setCookie = setCookie == null ? cookieString : setCookie + ", " + cookieString;
}
}

if (!string.IsNullOrEmpty(setCookie))
{
Headers.Set(HttpKnownHeaderNames.SetCookie, setCookie);
if (string.IsNullOrEmpty(setCookie2))
{
Headers.Remove(HttpKnownHeaderNames.SetCookie2);
}
}

if (!string.IsNullOrEmpty(setCookie2))
{
Headers.Set(HttpKnownHeaderNames.SetCookie2, setCookie2);
if (string.IsNullOrEmpty(setCookie))
{
Headers.Remove(HttpKnownHeaderNames.SetCookie);
}
}
}

if (NetEventSource.IsEnabled) NetEventSource.Info(this, $"Exiting Set-Cookie: {Headers[HttpResponseHeader.SetCookie]} Set-Cookie2: {Headers[HttpKnownHeaderNames.SetCookie2]}");
}

public void Redirect(string url)
{
if (NetEventSource.IsEnabled) NetEventSource.Info(this, $"url={url}");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -167,24 +167,6 @@ public void CopyFrom(HttpListenerResponse templateResponse)
_version = templateResponse._version;
}

private bool FindCookie(Cookie cookie)
{
string name = cookie.Name;
string domain = cookie.Domain;
string path = cookie.Path;
foreach (Cookie c in _cookies)
{
if (name != c.Name)
continue;
if (domain != c.Domain)
continue;
if (path == c.Path)
return true;
}

return false;
}

internal void SendHeaders(bool closing, MemoryStream ms, bool isWebSocketHandshake = false)
{
if (!isWebSocketHandshake)
Expand Down Expand Up @@ -289,13 +271,7 @@ internal void SendHeaders(bool closing, MemoryStream ms, bool isWebSocketHandsha
}
}

if (_cookies != null)
{
foreach (Cookie cookie in _cookies)
{
_webHeaders.Set(HttpKnownHeaderNames.SetCookie, CookieToClientString(cookie));
}
}
ComputeCookies();
}

Encoding encoding = Encoding.Default;
Expand Down Expand Up @@ -361,52 +337,6 @@ private static string FormatHeaders(WebHeaderCollection headers)
return sb.Append("\r\n").ToString();
}

private static string CookieToClientString(Cookie cookie)
{
if (cookie.Name.Length == 0)
return String.Empty;

StringBuilder result = new StringBuilder(64);

if (cookie.Version > 0)
result.Append("Version=").Append(cookie.Version).Append(";");

result.Append(cookie.Name).Append("=").Append(cookie.Value);

if (cookie.Path != null && cookie.Path.Length != 0)
result.Append(";Path=").Append(QuotedString(cookie, cookie.Path));

if (cookie.Domain != null && cookie.Domain.Length != 0)
result.Append(";Domain=").Append(QuotedString(cookie, cookie.Domain));

if (cookie.Port != null && cookie.Port.Length != 0)
result.Append(";Port=").Append(cookie.Port);

return result.ToString();
}

private static string QuotedString(Cookie cookie, string value)
{
if (cookie.Version == 0 || IsToken(value))
return value;
else
return "\"" + value.Replace("\"", "\\\"") + "\"";
}

private static string s_tspecials = "()<>@,;:\\\"/[]?={} \t"; // from RFC 2965, 2068

private static bool IsToken(string value)
{
int len = value.Length;
for (int i = 0; i < len; i++)
{
char c = value[i];
if (c < 0x20 || c >= 0x7f || s_tspecials.IndexOf(c) != -1)
return false;
}
return true;
}

private bool Disposed { get; set; }
internal bool SentHeaders { get; set; }
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -357,56 +357,6 @@ internal unsafe uint SendHeaders(Interop.HttpApi.HTTP_DATA_CHUNK* pDataChunk,
return statusCode;
}

internal void ComputeCookies()
{
if (NetEventSource.IsEnabled)
NetEventSource.Info(this,
$"Entering Set-Cookie: {Headers[HttpResponseHeader.SetCookie]}, Set-Cookie2: {Headers[HttpKnownHeaderNames.SetCookie2]}");
if (_cookies != null)
{
// now go through the collection, and concatenate all the cookies in per-variant strings
string setCookie2 = null;
string setCookie = null;
for (int index = 0; index < _cookies.Count; index++)
{
Cookie cookie = _cookies[index];
string cookieString = cookie.ToServerString();
if (cookieString == null || cookieString.Length == 0)
{
continue;
}
if (NetEventSource.IsEnabled) NetEventSource.Info(this, $"Now looking at index:{index} cookie: {cookie}");
if (cookie.IsRfc2965Variant())
{
setCookie2 = setCookie2 == null ? cookieString : setCookie2 + ", " + cookieString;
}
else
{
setCookie = setCookie == null ? cookieString : setCookie + ", " + cookieString;
}
}
if (!string.IsNullOrEmpty(setCookie))
{
Headers.Set(HttpKnownHeaderNames.SetCookie, setCookie);
if (string.IsNullOrEmpty(setCookie2))
{
Headers.Remove(HttpKnownHeaderNames.SetCookie2);
}
}
if (!string.IsNullOrEmpty(setCookie2))
{
Headers.Set(HttpKnownHeaderNames.SetCookie2, setCookie2);
if (string.IsNullOrEmpty(setCookie))
{
Headers.Remove(HttpKnownHeaderNames.SetCookie);
}
}
}
if (NetEventSource.IsEnabled)
NetEventSource.Info(this,
$"Exiting Set-Cookie: {Headers[HttpResponseHeader.SetCookie]} Set-Cookie2: {Headers[HttpKnownHeaderNames.SetCookie2]}");
}

internal Interop.HttpApi.HTTP_FLAGS ComputeHeaders()
{
Interop.HttpApi.HTTP_FLAGS flags = Interop.HttpApi.HTTP_FLAGS.NONE;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ public static IEnumerable<object[]> Cookies_TestData()
};
}

[ConditionalTheory(nameof(Helpers) + "." + nameof(Helpers.IsWindowsImplementation))] // [ActiveIssue(20165, TestPlatforms.AnyUnix)]
[ConditionalTheory(nameof(PlatformDetection) + "." + nameof(PlatformDetection.IsNotOneCoreUAP))]
[MemberData(nameof(Cookies_TestData))]
public async Task Cookies_SetAndSend_ClientReceivesExpectedHeaders(CookieCollection cookies, int expectedBytes, string expectedSetCookie, string expectedSetCookie2)
{
Expand All @@ -102,7 +102,7 @@ public async Task Cookies_SetAndSend_ClientReceivesExpectedHeaders(CookieCollect
string clientResponse = GetClientResponse(expectedBytes);
if (expectedSetCookie != null)
{
Assert.Contains($"{Environment.NewLine}{expectedSetCookie}{Environment.NewLine}", clientResponse);
Assert.Contains($"\r\n{expectedSetCookie}\r\n", clientResponse);
}
else
{
Expand All @@ -111,15 +111,15 @@ public async Task Cookies_SetAndSend_ClientReceivesExpectedHeaders(CookieCollect

if (expectedSetCookie2 != null)
{
Assert.Contains($"{Environment.NewLine}{expectedSetCookie2}{Environment.NewLine}", clientResponse);
Assert.Contains($"\r\n{expectedSetCookie2}\r\n", clientResponse);
}
else
{
Assert.DoesNotContain("Set-Cookie2:", clientResponse);
}
}

[ConditionalFact(nameof(Helpers) + "." + nameof(Helpers.IsWindowsImplementation))] // [ActiveIssue(20165, TestPlatforms.AnyUnix)]
[ConditionalFact(nameof(PlatformDetection) + "." + nameof(PlatformDetection.IsNotOneCoreUAP))]
public async Task Cookies_SetInHeader_ClientReceivesExpectedHeaders()
{
HttpListenerResponse response = await GetResponse();
Expand All @@ -129,11 +129,11 @@ public async Task Cookies_SetInHeader_ClientReceivesExpectedHeaders()
response.Close();

string clientResponse = GetClientResponse(173);
Assert.Contains($"{Environment.NewLine}Set-Cookie: name1=value1{Environment.NewLine}", clientResponse);
Assert.Contains($"{Environment.NewLine}Set-Cookie2: name2=value2{Environment.NewLine}", clientResponse);
Assert.Contains($"\r\nSet-Cookie: name1=value1\r\n", clientResponse);
Assert.Contains($"\r\nSet-Cookie2: name2=value2\r\n", clientResponse);
}

[ConditionalFact(nameof(Helpers) + "." + nameof(Helpers.IsWindowsImplementation))] // [ActiveIssue(20165, TestPlatforms.AnyUnix)]
[ConditionalFact(nameof(PlatformDetection) + "." + nameof(PlatformDetection.IsNotOneCoreUAP))]
public async Task Cookies_SetCookie2InHeadersButNotInCookies_RemovesFromHeaders()
{
HttpListenerResponse response = await GetResponse();
Expand All @@ -149,10 +149,10 @@ public async Task Cookies_SetCookie2InHeadersButNotInCookies_RemovesFromHeaders(

string clientResponse = GetClientResponse(170);
Assert.DoesNotContain("Set-Cookie:", clientResponse);
Assert.Contains($"{Environment.NewLine}Set-Cookie2: name3=value3; Port=\"200\"; Version=1{Environment.NewLine}", clientResponse);
Assert.Contains($"\r\nSet-Cookie2: name3=value3; Port=\"200\"; Version=1\r\n", clientResponse);
}

[ConditionalFact(nameof(Helpers) + "." + nameof(Helpers.IsWindowsImplementation))] // [ActiveIssue(20165, TestPlatforms.AnyUnix)]
[ConditionalFact(nameof(PlatformDetection) + "." + nameof(PlatformDetection.IsNotOneCoreUAP))]
public async Task Cookies_SetCookieInHeadersButNotInCookies_RemovesFromHeaders()
{
HttpListenerResponse response = await GetResponse();
Expand All @@ -167,7 +167,7 @@ public async Task Cookies_SetCookieInHeadersButNotInCookies_RemovesFromHeaders()
Assert.Null(response.Headers["Set-Cookie2"]);

string clientResponse = GetClientResponse(146);
Assert.Contains($"{Environment.NewLine}Set-Cookie: name3=value3{Environment.NewLine}", clientResponse);
Assert.Contains($"\r\nSet-Cookie: name3=value3\r\n", clientResponse);
Assert.DoesNotContain("Set-Cookie2", clientResponse);
}

Expand Down

0 comments on commit 2416022

Please sign in to comment.