Skip to content

Commit cf49a71

Browse files
authored
Add HttpResponseMessageExtensions to simply verify information on a HttpResponseMessage.
Includes: - HasHttpVersion - HasHttpStatusCode - HasReasonPhrase - HasResponseHeader - HasContentHeader - HasContent
1 parent 641851a commit cf49a71

10 files changed

+796
-26
lines changed
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
using System.Net.Http.Headers;
2+
3+
namespace TestableHttpClient
4+
{
5+
internal static class HttpHeadersExtensions
6+
{
7+
internal static bool HasHeader(this HttpHeaders headers, string headerName)
8+
{
9+
return headers.TryGetValues(headerName, out _);
10+
}
11+
12+
internal static bool HasHeader(this HttpHeaders headers, string headerName, string headerValue)
13+
{
14+
if (headers.TryGetValues(headerName, out var values))
15+
{
16+
var value = string.Join(" ", values);
17+
return StringMatcher.Matches(value, headerValue);
18+
}
19+
20+
return false;
21+
}
22+
}
23+
}

src/TestableHttpClient/HttpRequestMessageExtensions.cs

Lines changed: 2 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
using System;
22
using System.Net.Http;
33
using System.Net.Http.Headers;
4-
using System.Text.RegularExpressions;
54

65
namespace TestableHttpClient
76
{
@@ -204,22 +203,6 @@ public static bool HasContentHeader(this HttpRequestMessage httpRequestMessage,
204203
return httpRequestMessage.Content.Headers.HasHeader(headerName, headerValue);
205204
}
206205

207-
private static bool HasHeader(this HttpHeaders headers, string headerName)
208-
{
209-
return headers.TryGetValues(headerName, out _);
210-
}
211-
212-
private static bool HasHeader(this HttpHeaders headers, string headerName, string headerValue)
213-
{
214-
if (headers.TryGetValues(headerName, out var values))
215-
{
216-
var value = string.Join(" ", values);
217-
return Matches(value, headerValue);
218-
}
219-
220-
return false;
221-
}
222-
223206
/// <summary>
224207
/// Determines whether the request uri matches a pattern.
225208
/// </summary>
@@ -238,7 +221,7 @@ public static bool HasMatchingUri(this HttpRequestMessage httpRequestMessage, st
238221
null => throw new ArgumentNullException(nameof(pattern)),
239222
"" => false,
240223
"*" => true,
241-
_ => Matches(httpRequestMessage.RequestUri.AbsoluteUri, pattern),
224+
_ => StringMatcher.Matches(httpRequestMessage.RequestUri.AbsoluteUri, pattern),
242225
};
243226
}
244227

@@ -271,15 +254,8 @@ public static bool HasContent(this HttpRequestMessage httpRequestMessage, string
271254
{
272255
"" => stringContent == pattern,
273256
"*" => true,
274-
_ => Matches(stringContent, pattern),
257+
_ => StringMatcher.Matches(stringContent, pattern),
275258
};
276259
}
277-
278-
private static bool Matches(string value, string pattern)
279-
{
280-
var regex = Regex.Escape(pattern).Replace("\\*", "(.*)");
281-
282-
return Regex.IsMatch(value, $"^{regex}$");
283-
}
284260
}
285261
}
Lines changed: 234 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,234 @@
1+
using System;
2+
using System.Net;
3+
using System.Net.Http;
4+
5+
namespace TestableHttpClient
6+
{
7+
/// <summary>
8+
/// A set of static methods for checking values on a <see cref="HttpResponseMessage"/>.
9+
/// </summary>
10+
public static class HttpResponseMessageExtensions
11+
{
12+
/// <summary>
13+
/// Determines whether a specific HttpVersion is set on a response.
14+
/// </summary>
15+
/// <param name="httpResponseMessage">A <see cref="HttpResponseMessage"/> to check the correct version on.</param>
16+
/// <param name="httpVersion">The expected version.</param>
17+
/// <returns>true when the HttpVersion matches; otherwise, false.</returns>
18+
public static bool HasHttpVersion(this HttpResponseMessage httpResponseMessage, Version httpVersion)
19+
{
20+
if (httpResponseMessage == null)
21+
{
22+
throw new ArgumentNullException(nameof(httpResponseMessage));
23+
}
24+
25+
if (httpVersion == null)
26+
{
27+
throw new ArgumentNullException(nameof(httpVersion));
28+
}
29+
30+
return httpResponseMessage.Version == httpVersion;
31+
}
32+
33+
/// <summary>
34+
/// Determines whether a specific HttpVersion is set on a response.
35+
/// </summary>
36+
/// <param name="httpResponseMessage">A <see cref="HttpResponseMessage"/> to check the correct version on.</param>
37+
/// <param name="httpVersion">The expected version.</param>
38+
/// <returns>true when the HttpVersion matches; otherwise, false.</returns>
39+
public static bool HasHttpVersion(this HttpResponseMessage httpResponseMessage, string httpVersion)
40+
{
41+
if (httpResponseMessage == null)
42+
{
43+
throw new ArgumentNullException(nameof(httpResponseMessage));
44+
}
45+
46+
if (string.IsNullOrEmpty(httpVersion))
47+
{
48+
throw new ArgumentNullException(nameof(httpVersion));
49+
}
50+
51+
return HasHttpVersion(httpResponseMessage, new Version(httpVersion));
52+
}
53+
54+
/// <summary>
55+
/// Determines whether a specific status code is set on a response.
56+
/// </summary>
57+
/// <param name="httpResponseMessage">A <see cref="HttpResponseMessage"/> to check the correct version on.</param>
58+
/// <param name="httpStatusCode">The expected status code.</param>
59+
/// <returns>true when the status code matches; otherwise, false.</returns>
60+
public static bool HasHttpStatusCode(this HttpResponseMessage httpResponseMessage, HttpStatusCode httpStatusCode)
61+
{
62+
if (httpResponseMessage == null)
63+
{
64+
throw new ArgumentNullException(nameof(httpResponseMessage));
65+
}
66+
67+
return httpResponseMessage.StatusCode == httpStatusCode;
68+
}
69+
70+
/// <summary>
71+
/// Determines whether a specific reason phrase is set on a response.
72+
/// </summary>
73+
/// <param name="httpResponseMessage">A <see cref="HttpResponseMessage"/> to check the correct version on.</param>
74+
/// <param name="reasonPhrase">The expected reason phrase.</param>
75+
/// <returns>true when the reason phrase matches; otherwise, false.</returns>
76+
public static bool HasReasonPhrase(this HttpResponseMessage httpResponseMessage, string reasonPhrase)
77+
{
78+
if (httpResponseMessage == null)
79+
{
80+
throw new ArgumentNullException(nameof(httpResponseMessage));
81+
}
82+
83+
if (reasonPhrase == null)
84+
{
85+
throw new ArgumentNullException(nameof(reasonPhrase));
86+
}
87+
88+
return httpResponseMessage.ReasonPhrase == reasonPhrase;
89+
}
90+
91+
/// <summary>
92+
/// Determines whether a specific header is set on a response.
93+
/// </summary>
94+
/// <remarks>This method only checks headers in <see cref="HttpRequestHeaders"/></remarks>
95+
/// <param name="httpResponseMessage">A <see cref="HttpResponseMessage"/> to check the response header on.</param>
96+
/// <param name="headerName">The name of the header to locate on the response.</param>
97+
/// <returns>true when the response contains a header with the specified name; otherwise, false.</returns>
98+
public static bool HasResponseHeader(this HttpResponseMessage httpResponseMessage, string headerName)
99+
{
100+
if (httpResponseMessage == null)
101+
{
102+
throw new ArgumentNullException(nameof(httpResponseMessage));
103+
}
104+
105+
if (string.IsNullOrEmpty(headerName))
106+
{
107+
throw new ArgumentNullException(nameof(headerName));
108+
}
109+
110+
return httpResponseMessage.Headers.HasHeader(headerName);
111+
}
112+
113+
/// <summary>
114+
/// Determines whether a specific header with a specific value is set on a response.
115+
/// </summary>
116+
/// <remarks>This method only checks headers in <see cref="HttpRequestHeaders"/></remarks>
117+
/// <param name="httpResponseMessage">A <see cref="HttpResponseMessage"/> to check the response header on.</param>
118+
/// <param name="headerName">The name of the header to locate on the response.</param>
119+
/// <param name="headerValue">The value the header should have. Wildcard is supported.</param>
120+
/// <returns>true when the response contains a header with the specified name and value; otherwise, false.</returns>
121+
public static bool HasResponseHeader(this HttpResponseMessage httpResponseMessage, string headerName, string headerValue)
122+
{
123+
if (httpResponseMessage == null)
124+
{
125+
throw new ArgumentNullException(nameof(httpResponseMessage));
126+
}
127+
128+
if (string.IsNullOrEmpty(headerName))
129+
{
130+
throw new ArgumentNullException(nameof(headerName));
131+
}
132+
133+
if (string.IsNullOrEmpty(headerValue))
134+
{
135+
throw new ArgumentNullException(nameof(headerValue));
136+
}
137+
138+
return httpResponseMessage.Headers.HasHeader(headerName, headerValue);
139+
}
140+
141+
/// <summary>
142+
/// Determines whether a specific header is set on a response.
143+
/// </summary>
144+
/// <remarks>This method only checks headers in <see cref="HttpContentHeaders"/></remarks>
145+
/// <param name="httpResponseMessage">A <see cref="HttpResponseMessage"/> to check the content header on.</param>
146+
/// <param name="headerName">The name of the header to locate on the response content.</param>
147+
/// <returns>true when the response contains a header with the specified name; otherwise, false.</returns>
148+
public static bool HasContentHeader(this HttpResponseMessage httpResponseMessage, string headerName)
149+
{
150+
if (httpResponseMessage == null)
151+
{
152+
throw new ArgumentNullException(nameof(httpResponseMessage));
153+
}
154+
155+
if (string.IsNullOrEmpty(headerName))
156+
{
157+
throw new ArgumentNullException(nameof(headerName));
158+
}
159+
160+
if (httpResponseMessage.Content == null)
161+
{
162+
return false;
163+
}
164+
165+
return httpResponseMessage.Content.Headers.HasHeader(headerName);
166+
}
167+
168+
/// <summary>
169+
/// Determines whether a specific header with a specific value is set on a response.
170+
/// </summary>
171+
/// <remarks>This method only checks headers in <see cref="HttpContentHeaders"/></remarks>
172+
/// <param name="httpResponseMessage">A <see cref="HttpResponseMessage"/> to check the content header on.</param>
173+
/// <param name="headerName">The name of the header to locate on the response content.</param>
174+
/// <param name="headerValue">The value the header should have. Wildcard is supported.</param>
175+
/// <returns>true when the response contains a header with the specified name and value; otherwise, false.</returns>
176+
public static bool HasContentHeader(this HttpResponseMessage httpResponseMessage, string headerName, string headerValue)
177+
{
178+
if (httpResponseMessage == null)
179+
{
180+
throw new ArgumentNullException(nameof(httpResponseMessage));
181+
}
182+
183+
if (string.IsNullOrEmpty(headerName))
184+
{
185+
throw new ArgumentNullException(nameof(headerName));
186+
}
187+
188+
if (string.IsNullOrEmpty(headerValue))
189+
{
190+
throw new ArgumentNullException(nameof(headerValue));
191+
}
192+
193+
if (httpResponseMessage.Content == null)
194+
{
195+
return false;
196+
}
197+
198+
return httpResponseMessage.Content.Headers.HasHeader(headerName, headerValue);
199+
}
200+
201+
/// <summary>
202+
/// Determines whether the response content matches a string pattern.
203+
/// </summary>
204+
/// <param name="httpResponseMessage">A <see cref="HttpResponseMessage"/> to check the correct content on.</param>
205+
/// <param name="pattern">A pattern to match the response content, supports * as wildcards.</param>
206+
/// <returns>true when the response content matches the pattern; otherwise, false.</returns>
207+
public static bool HasContent(this HttpResponseMessage httpResponseMessage, string pattern)
208+
{
209+
if (httpResponseMessage == null)
210+
{
211+
throw new ArgumentNullException(nameof(httpResponseMessage));
212+
}
213+
214+
if (pattern == null)
215+
{
216+
throw new ArgumentNullException(nameof(pattern));
217+
}
218+
219+
if (httpResponseMessage.Content == null)
220+
{
221+
return false;
222+
}
223+
224+
var stringContent = httpResponseMessage.Content.ReadAsStringAsync().Result;
225+
226+
return pattern switch
227+
{
228+
"" => stringContent == pattern,
229+
"*" => true,
230+
_ => StringMatcher.Matches(stringContent, pattern),
231+
};
232+
}
233+
}
234+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
using System.Text.RegularExpressions;
2+
3+
namespace TestableHttpClient
4+
{
5+
internal static class StringMatcher
6+
{
7+
internal static bool Matches(string value, string pattern)
8+
{
9+
var regex = Regex.Escape(pattern).Replace("\\*", "(.*)");
10+
11+
return Regex.IsMatch(value, $"^{regex}$");
12+
}
13+
}
14+
}

0 commit comments

Comments
 (0)