Skip to content

Commit 43d7214

Browse files
committed
[dotnet] Allow network interception to handle duplicate response headers
Headers in HTTP responses may be repeated. The previous implementation of CDP network response handling did not take this into account. Now, if a response has duplicate headers, the values will be combined into a single header with the correct name, and a comma-separated list for the value. This is complaint with RFC2616. There is an exception for the Set-Cookie header, however, which is allowed to occur multiple times, but is not combinable as to the rules of the aforementioned RFC. To account for this, a new property on HttpResponseData has been added to list the cookie headers (the `CookieHeaders` property) as found in the response.
1 parent c0a5c3e commit 43d7214

File tree

6 files changed

+120
-14
lines changed

6 files changed

+120
-14
lines changed

dotnet/src/webdriver/DevTools/v85/V85Network.cs

+23-3
Original file line numberDiff line numberDiff line change
@@ -147,14 +147,19 @@ public override async Task ContinueRequestWithResponse(HttpRequestData requestDa
147147
ResponseCode = responseData.StatusCode,
148148
};
149149

150-
if (responseData.Headers.Count > 0)
150+
if (responseData.Headers.Count > 0 || responseData.CookieHeaders.Count > 0)
151151
{
152152
List<HeaderEntry> headers = new List<HeaderEntry>();
153-
foreach(KeyValuePair<string, string> headerPair in responseData.Headers)
153+
foreach (KeyValuePair<string, string> headerPair in responseData.Headers)
154154
{
155155
headers.Add(new HeaderEntry() { Name = headerPair.Key, Value = headerPair.Value });
156156
}
157157

158+
foreach (string cookieHeader in responseData.CookieHeaders)
159+
{
160+
headers.Add(new HeaderEntry() { Name = "Set-Cookie", Value = cookieHeader });
161+
}
162+
158163
commandSettings.ResponseHeaders = headers.ToArray();
159164
}
160165

@@ -286,7 +291,22 @@ private void OnFetchRequestPaused(object sender, Fetch.RequestPausedEventArgs e)
286291

287292
foreach (var header in e.ResponseHeaders)
288293
{
289-
wrappedResponse.ResponseData.Headers.Add(header.Name, header.Value);
294+
if (header.Name.ToLowerInvariant() == "set-cookie")
295+
{
296+
wrappedResponse.ResponseData.CookieHeaders.Add(header.Value);
297+
}
298+
else
299+
{
300+
if (wrappedResponse.ResponseData.Headers.ContainsKey(header.Name))
301+
{
302+
string currentHeaderValue = wrappedResponse.ResponseData.Headers[header.Name];
303+
wrappedResponse.ResponseData.Headers[header.Name] = currentHeaderValue + ", " + header.Value;
304+
}
305+
else
306+
{
307+
wrappedResponse.ResponseData.Headers.Add(header.Name, header.Value);
308+
}
309+
}
290310
}
291311

292312
this.OnResponsePaused(wrappedResponse);

dotnet/src/webdriver/DevTools/v88/V88Network.cs

+23-3
Original file line numberDiff line numberDiff line change
@@ -148,14 +148,19 @@ public override async Task ContinueRequestWithResponse(HttpRequestData requestDa
148148
ResponseCode = responseData.StatusCode,
149149
};
150150

151-
if (responseData.Headers.Count > 0)
151+
if (responseData.Headers.Count > 0 || responseData.CookieHeaders.Count > 0)
152152
{
153153
List<HeaderEntry> headers = new List<HeaderEntry>();
154-
foreach(KeyValuePair<string, string> headerPair in responseData.Headers)
154+
foreach (KeyValuePair<string, string> headerPair in responseData.Headers)
155155
{
156156
headers.Add(new HeaderEntry() { Name = headerPair.Key, Value = headerPair.Value });
157157
}
158158

159+
foreach (string cookieHeader in responseData.CookieHeaders)
160+
{
161+
headers.Add(new HeaderEntry() { Name = "Set-Cookie", Value = cookieHeader });
162+
}
163+
159164
commandSettings.ResponseHeaders = headers.ToArray();
160165
}
161166

@@ -287,7 +292,22 @@ private void OnFetchRequestPaused(object sender, Fetch.RequestPausedEventArgs e)
287292

288293
foreach (var header in e.ResponseHeaders)
289294
{
290-
wrappedResponse.ResponseData.Headers.Add(header.Name, header.Value);
295+
if (header.Name.ToLowerInvariant() == "set-cookie")
296+
{
297+
wrappedResponse.ResponseData.CookieHeaders.Add(header.Value);
298+
}
299+
else
300+
{
301+
if (wrappedResponse.ResponseData.Headers.ContainsKey(header.Name))
302+
{
303+
string currentHeaderValue = wrappedResponse.ResponseData.Headers[header.Name];
304+
wrappedResponse.ResponseData.Headers[header.Name] = currentHeaderValue + ", " + header.Value;
305+
}
306+
else
307+
{
308+
wrappedResponse.ResponseData.Headers.Add(header.Name, header.Value);
309+
}
310+
}
291311
}
292312

293313
this.OnResponsePaused(wrappedResponse);

dotnet/src/webdriver/DevTools/v89/V89Network.cs

+23-3
Original file line numberDiff line numberDiff line change
@@ -147,14 +147,19 @@ public override async Task ContinueRequestWithResponse(HttpRequestData requestDa
147147
ResponseCode = responseData.StatusCode,
148148
};
149149

150-
if (responseData.Headers.Count > 0)
150+
if (responseData.Headers.Count > 0 || responseData.CookieHeaders.Count > 0)
151151
{
152152
List<HeaderEntry> headers = new List<HeaderEntry>();
153-
foreach(KeyValuePair<string, string> headerPair in responseData.Headers)
153+
foreach (KeyValuePair<string, string> headerPair in responseData.Headers)
154154
{
155155
headers.Add(new HeaderEntry() { Name = headerPair.Key, Value = headerPair.Value });
156156
}
157157

158+
foreach (string cookieHeader in responseData.CookieHeaders)
159+
{
160+
headers.Add(new HeaderEntry() { Name = "Set-Cookie", Value = cookieHeader });
161+
}
162+
158163
commandSettings.ResponseHeaders = headers.ToArray();
159164
}
160165

@@ -286,7 +291,22 @@ private void OnFetchRequestPaused(object sender, Fetch.RequestPausedEventArgs e)
286291

287292
foreach (var header in e.ResponseHeaders)
288293
{
289-
wrappedResponse.ResponseData.Headers.Add(header.Name, header.Value);
294+
if (header.Name.ToLowerInvariant() == "set-cookie")
295+
{
296+
wrappedResponse.ResponseData.CookieHeaders.Add(header.Value);
297+
}
298+
else
299+
{
300+
if (wrappedResponse.ResponseData.Headers.ContainsKey(header.Name))
301+
{
302+
string currentHeaderValue = wrappedResponse.ResponseData.Headers[header.Name];
303+
wrappedResponse.ResponseData.Headers[header.Name] = currentHeaderValue + ", " + header.Value;
304+
}
305+
else
306+
{
307+
wrappedResponse.ResponseData.Headers.Add(header.Name, header.Value);
308+
}
309+
}
290310
}
291311

292312
this.OnResponsePaused(wrappedResponse);

dotnet/src/webdriver/DevTools/v90/V90Network.cs

+22-2
Original file line numberDiff line numberDiff line change
@@ -147,14 +147,19 @@ public override async Task ContinueRequestWithResponse(HttpRequestData requestDa
147147
ResponseCode = responseData.StatusCode,
148148
};
149149

150-
if (responseData.Headers.Count > 0)
150+
if (responseData.Headers.Count > 0 || responseData.CookieHeaders.Count > 0)
151151
{
152152
List<HeaderEntry> headers = new List<HeaderEntry>();
153153
foreach(KeyValuePair<string, string> headerPair in responseData.Headers)
154154
{
155155
headers.Add(new HeaderEntry() { Name = headerPair.Key, Value = headerPair.Value });
156156
}
157157

158+
foreach(string cookieHeader in responseData.CookieHeaders)
159+
{
160+
headers.Add(new HeaderEntry() { Name = "Set-Cookie", Value = cookieHeader });
161+
}
162+
158163
commandSettings.ResponseHeaders = headers.ToArray();
159164
}
160165

@@ -286,7 +291,22 @@ private void OnFetchRequestPaused(object sender, Fetch.RequestPausedEventArgs e)
286291

287292
foreach (var header in e.ResponseHeaders)
288293
{
289-
wrappedResponse.ResponseData.Headers.Add(header.Name, header.Value);
294+
if (header.Name.ToLowerInvariant() == "set-cookie")
295+
{
296+
wrappedResponse.ResponseData.CookieHeaders.Add(header.Value);
297+
}
298+
else
299+
{
300+
if (wrappedResponse.ResponseData.Headers.ContainsKey(header.Name))
301+
{
302+
string currentHeaderValue = wrappedResponse.ResponseData.Headers[header.Name];
303+
wrappedResponse.ResponseData.Headers[header.Name] = currentHeaderValue + ", " + header.Value;
304+
}
305+
else
306+
{
307+
wrappedResponse.ResponseData.Headers.Add(header.Name, header.Value);
308+
}
309+
}
290310
}
291311

292312
this.OnResponsePaused(wrappedResponse);

dotnet/src/webdriver/DevTools/v91/V91Network.cs

+23-3
Original file line numberDiff line numberDiff line change
@@ -147,14 +147,19 @@ public override async Task ContinueRequestWithResponse(HttpRequestData requestDa
147147
ResponseCode = responseData.StatusCode,
148148
};
149149

150-
if (responseData.Headers.Count > 0)
150+
if (responseData.Headers.Count > 0 || responseData.CookieHeaders.Count > 0)
151151
{
152152
List<HeaderEntry> headers = new List<HeaderEntry>();
153-
foreach(KeyValuePair<string, string> headerPair in responseData.Headers)
153+
foreach (KeyValuePair<string, string> headerPair in responseData.Headers)
154154
{
155155
headers.Add(new HeaderEntry() { Name = headerPair.Key, Value = headerPair.Value });
156156
}
157157

158+
foreach (string cookieHeader in responseData.CookieHeaders)
159+
{
160+
headers.Add(new HeaderEntry() { Name = "Set-Cookie", Value = cookieHeader });
161+
}
162+
158163
commandSettings.ResponseHeaders = headers.ToArray();
159164
}
160165

@@ -286,7 +291,22 @@ private void OnFetchRequestPaused(object sender, Fetch.RequestPausedEventArgs e)
286291

287292
foreach (var header in e.ResponseHeaders)
288293
{
289-
wrappedResponse.ResponseData.Headers.Add(header.Name, header.Value);
294+
if (header.Name.ToLowerInvariant() == "set-cookie")
295+
{
296+
wrappedResponse.ResponseData.CookieHeaders.Add(header.Value);
297+
}
298+
else
299+
{
300+
if (wrappedResponse.ResponseData.Headers.ContainsKey(header.Name))
301+
{
302+
string currentHeaderValue = wrappedResponse.ResponseData.Headers[header.Name];
303+
wrappedResponse.ResponseData.Headers[header.Name] = currentHeaderValue + ", " + header.Value;
304+
}
305+
else
306+
{
307+
wrappedResponse.ResponseData.Headers.Add(header.Name, header.Value);
308+
}
309+
}
290310
}
291311

292312
this.OnResponsePaused(wrappedResponse);

dotnet/src/webdriver/HttpResponseData.cs

+6
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ namespace OpenQA.Selenium
2929
public class HttpResponseData
3030
{
3131
private Dictionary<string, string> headers = new Dictionary<string, string>();
32+
private List<string> cookies = new List<string>();
3233

3334
/// <summary>
3435
/// Gets or sets the ID of the request that generated this response.
@@ -64,5 +65,10 @@ public class HttpResponseData
6465
/// Gets the headers of the HTTP response.
6566
/// </summary>
6667
public Dictionary<string, string> Headers => this.headers;
68+
69+
/// <summary>
70+
/// Gets the cookie headers of the HTTP response.
71+
/// </summary>
72+
public List<string> CookieHeaders => this.cookies;
6773
}
6874
}

0 commit comments

Comments
 (0)