Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.

Commit 7b5c31e

Browse files
committed
Fix handling of RedirectLocation header
1 parent 2215ccb commit 7b5c31e

File tree

5 files changed

+44
-17
lines changed

5 files changed

+44
-17
lines changed

src/System.Net.HttpListener/src/System/Net/Managed/HttpListener.Managed.cs

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -68,9 +68,10 @@ public bool UnsafeConnectionNtlmAuthentication
6868
public void Stop()
6969
{
7070
if (NetEventSource.IsEnabled) NetEventSource.Enter(this);
71-
try
71+
72+
lock (_internalLock)
7273
{
73-
lock (_internalLock)
74+
try
7475
{
7576
CheckDisposed();
7677
if (_state == State.Stopped)
@@ -79,19 +80,18 @@ public void Stop()
7980
}
8081

8182
Close(false);
82-
83+
}
84+
catch (Exception exception)
85+
{
86+
if (NetEventSource.IsEnabled) NetEventSource.Error(this, $"Stop {exception}");
87+
throw;
88+
}
89+
finally
90+
{
8391
_state = State.Stopped;
92+
if (NetEventSource.IsEnabled) NetEventSource.Exit(this);
8493
}
8594
}
86-
catch (Exception exception)
87-
{
88-
if (NetEventSource.IsEnabled) NetEventSource.Error(this, $"Stop {exception}");
89-
throw;
90-
}
91-
finally
92-
{
93-
if (NetEventSource.IsEnabled) NetEventSource.Exit(this);
94-
}
9595
}
9696

9797
public void Abort()

src/System.Net.HttpListener/src/System/Net/Managed/HttpListenerContext.Managed.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ public Task<HttpListenerWebSocketContext> AcceptWebSocketAsync(string subProtoco
9797
public Task<HttpListenerWebSocketContext> AcceptWebSocketAsync(string subProtocol, int receiveBufferSize, TimeSpan keepAliveInterval, ArraySegment<byte> internalBuffer)
9898
{
9999
WebSocketValidate.ValidateArraySegment(internalBuffer, nameof(internalBuffer));
100+
HttpWebSocket.ValidateOptions(subProtocol, receiveBufferSize, HttpWebSocket.MinSendBufferSize, keepAliveInterval);
100101
return HttpWebSocket.AcceptWebSocketAsyncCore(this, subProtocol, receiveBufferSize, keepAliveInterval, internalBuffer);
101102
}
102103
}

src/System.Net.HttpListener/src/System/Net/Managed/HttpListenerResponse.Managed.cs

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -316,6 +316,9 @@ internal void SendHeaders(bool closing, MemoryStream ms, bool isWebSocketHandsha
316316
SentHeaders = !isWebSocketHandshake;
317317
}
318318

319+
private static bool HeaderCanHaveEmptyValue(string name) =>
320+
!string.Equals(name, HttpKnownHeaderNames.Location, StringComparison.OrdinalIgnoreCase);
321+
319322
private static string FormatHeaders(WebHeaderCollection headers)
320323
{
321324
var sb = new StringBuilder();
@@ -324,9 +327,34 @@ private static string FormatHeaders(WebHeaderCollection headers)
324327
{
325328
string key = headers.GetKey(i);
326329
string[] values = headers.GetValues(i);
330+
331+
int startingLength = sb.Length;
332+
333+
sb.Append(key).Append(": ");
334+
bool anyValues = false;
327335
for (int j = 0; j < values.Length; j++)
328336
{
329-
sb.Append(key).Append(": ").Append(values[j]).Append("\r\n");
337+
string value = values[j];
338+
if (!string.IsNullOrWhiteSpace(value))
339+
{
340+
if (anyValues)
341+
{
342+
sb.Append(", ");
343+
}
344+
sb.Append(value);
345+
anyValues = true;
346+
}
347+
}
348+
349+
if (anyValues || HeaderCanHaveEmptyValue(key))
350+
{
351+
// Complete the header
352+
sb.Append("\r\n");
353+
}
354+
else
355+
{
356+
// Empty header; remove it.
357+
sb.Length = startingLength;
330358
}
331359
}
332360

src/System.Net.HttpListener/tests/HttpListenerResponseTests.Headers.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -209,8 +209,7 @@ public async Task RedirectLocation_SetAndSend_Success(string redirectLocation, i
209209
[InlineData(null, null)]
210210
[InlineData("", null)]
211211
[InlineData("\r \t \n", "")]
212-
// The managed implementation should set Location directly in Headers rather than track it with its own variable.
213-
[ConditionalTheory(nameof(Helpers) + "." + nameof(Helpers.IsWindowsImplementation))] // [ActiveIssue(19972, TestPlatforms.AnyUnix)]
212+
[ConditionalTheory(nameof(PlatformDetection) + "." + nameof(PlatformDetection.IsNotOneCoreUAP))]
214213
public async Task RedirectLocation_SetNullOrEmpty_ResetsRedirectLocation(string redirectLocation, string expectedRedirectLocation)
215214
{
216215
using (HttpListenerResponse response = await GetResponse())

src/System.Net.HttpListener/tests/HttpListenerResponseTests.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -263,8 +263,7 @@ public async Task CloseResponseEntity_EmptyResponseEntity_Success(bool willBlock
263263
}
264264
}
265265

266-
// The managed implementation should not register as disposed before setting ContentLength - this causes an ObjectDisposedException.
267-
[ConditionalTheory(nameof(Helpers) + "." + nameof(Helpers.IsWindowsImplementation))] // [ActiveIssue(19975, TestPlatforms.AnyUnix)]
266+
[ConditionalTheory(nameof(Helpers) + "." + nameof(Helpers.IsWindowsImplementation))] // [ActiveIssue(20201, TestPlatforms.AnyUnix)]
268267
[InlineData(true)]
269268
[InlineData(false)]
270269
public async Task CloseResponseEntity_AllContentLengthAlreadySent_DoesNotSendEntity(bool willBlock)

0 commit comments

Comments
 (0)