• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

loresoft / FluentRest / 8851497268

26 Apr 2024 04:40PM UTC coverage: 57.33% (+5.1%) from 52.206%
8851497268

push

github

pwelter34
Update Issue.cs

270 of 604 branches covered (44.7%)

Branch coverage included in aggregate %.

825 of 1306 relevant lines covered (63.17%)

69.17 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

62.88
/src/FluentRest/HttpMessageExtensions.cs
1
using System;
2
using System.Collections.Generic;
3
using System.Globalization;
4
using System.Net.Http;
5
using System.Threading;
6
using System.Threading.Tasks;
7
using System.Xml.Linq;
8

9
namespace FluentRest;
10

11
/// <summary>
12
/// Extension method for <see cref="HttpRequestMessage"/>
13
/// </summary>
14
public static class HttpMessageExtensions
15
{
16
    /// <summary>
17
    /// Gets the <see cref="UrlBuilder"/> from the specified <paramref name="requestMessage" /> properties dictionary.
18
    /// </summary>
19
    /// <param name="requestMessage">The request message containing the property.</param>
20
    /// <returns>
21
    /// The <see cref="UrlBuilder"/> to modify the request message URI.
22
    /// </returns>
23
    /// <exception cref="ArgumentNullException"><paramref name="requestMessage"/> is <see langword="null"/></exception>
24
    public static UrlBuilder GetUrlBuilder(this HttpRequestMessage requestMessage)
25
    {
26
        if (requestMessage == null)
909!
27
            throw new ArgumentNullException(nameof(requestMessage));
×
28

29
        var propertyValue = requestMessage.Properties.GetOrAdd(FluentProperties.RequestUrlBuilder, k =>
909✔
30
            requestMessage.RequestUri == null
162✔
31
                ? new UrlBuilder()
162✔
32
                : new UrlBuilder(requestMessage.RequestUri)
162✔
33
        );
909✔
34

35
        return propertyValue as UrlBuilder;
909✔
36
    }
37

38
    /// <summary>
39
    /// Sets the <see cref="UrlBuilder" /> on the specified <paramref name="requestMessage" /> properties dictionary.
40
    /// </summary>
41
    /// <param name="requestMessage">The request message containing the property.</param>
42
    /// <param name="urlBuilder">The URL bulder to set on the properties dictionary.</param>
43
    /// <exception cref="ArgumentNullException"><paramref name="requestMessage" /> is <see langword="null" /></exception>
44
    public static void SetUrlBuilder(this HttpRequestMessage requestMessage, UrlBuilder urlBuilder)
45
    {
46
        if (requestMessage == null)
27!
47
            throw new ArgumentNullException(nameof(requestMessage));
×
48

49
        requestMessage.Properties[FluentProperties.RequestUrlBuilder] = urlBuilder;
27✔
50
    }
27✔
51

52

53
    /// <summary>
54
    /// Gets the content data from the specified <paramref name="requestMessage" /> properties dictionary.
55
    /// </summary>
56
    /// <param name="requestMessage">The request message containing the property.</param>
57
    /// <returns>
58
    /// The content data to send for the request message.
59
    /// </returns>
60
    /// <exception cref="ArgumentNullException"><paramref name="requestMessage"/> is <see langword="null"/></exception>
61
    public static object GetContentData(this HttpRequestMessage requestMessage)
62
    {
63
        if (requestMessage == null)
78!
64
            throw new ArgumentNullException(nameof(requestMessage));
×
65

66
        requestMessage.Properties.TryGetValue(FluentProperties.RequestContentData, out var propertyValue);
78✔
67
        return propertyValue;
78✔
68
    }
69

70
    /// <summary>
71
    /// Sets the content data on the specified <paramref name="requestMessage" /> properties dictionary.
72
    /// </summary>
73
    /// <param name="requestMessage">The request message containing the property.</param>
74
    /// <param name="contentData">The content data to send for the request message..</param>
75
    /// <exception cref="ArgumentNullException"><paramref name="requestMessage" /> is <see langword="null" /></exception>
76
    public static void SetContentData(this HttpRequestMessage requestMessage, object contentData)
77
    {
78
        if (requestMessage == null)
×
79
            throw new ArgumentNullException(nameof(requestMessage));
×
80

81
        requestMessage.Properties[FluentProperties.RequestContentData] = contentData;
×
82
    }
×
83

84

85
    /// <summary>
86
    /// Gets the form data property from the specified <paramref name="requestMessage" /> properties dictionary.
87
    /// </summary>
88
    /// <param name="requestMessage">The request message containing the property.</param>
89
    /// <returns>
90
    /// The dictionary of for data to send in the request message.
91
    /// </returns>
92
    /// <exception cref="ArgumentNullException"><paramref name="requestMessage"/> is <see langword="null"/></exception>
93
    public static Dictionary<string, ICollection<string>> GetFormData(this HttpRequestMessage requestMessage)
94
    {
95
        if (requestMessage == null)
180!
96
            throw new ArgumentNullException(nameof(requestMessage));
×
97

98
        var propertyValue = requestMessage.Properties.GetOrAdd(FluentProperties.RequestFormData, k => new Dictionary<string, ICollection<string>>());
252✔
99
        return propertyValue as Dictionary<string, ICollection<string>>;
180✔
100
    }
101

102

103
    /// <summary>
104
    /// Gets the completion option property from the specified <paramref name="requestMessage" /> properties dictionary.
105
    /// </summary>
106
    /// <param name="requestMessage">The request message containing the property.</param>
107
    /// <returns>
108
    /// The <see cref="HttpCompletionOption"/> to use when sending the request message.
109
    /// </returns>
110
    /// <exception cref="ArgumentNullException"><paramref name="requestMessage"/> is <see langword="null"/></exception>
111
    public static HttpCompletionOption GetCompletionOption(this HttpRequestMessage requestMessage)
112
    {
113
        if (requestMessage == null)
156!
114
            throw new ArgumentNullException(nameof(requestMessage));
×
115

116
        requestMessage.Properties.TryGetValue(FluentProperties.HttpCompletionOption, out var propertyValue);
156✔
117
        return (HttpCompletionOption)(propertyValue ?? HttpCompletionOption.ResponseContentRead);
156✔
118
    }
119

120
    /// <summary>
121
    /// Sets the completion option property on the specified <paramref name="requestMessage" /> properties dictionary.
122
    /// </summary>
123
    /// <param name="requestMessage">The request message containing the property.</param>
124
    /// <param name="completionOption">The <see cref="HttpCompletionOption"/> to use when sending the request message.</param>
125
    /// <exception cref="ArgumentNullException"><paramref name="requestMessage"/> is <see langword="null"/></exception>
126
    public static void SetCompletionOption(this HttpRequestMessage requestMessage, HttpCompletionOption completionOption)
127
    {
128
        if (requestMessage == null)
×
129
            throw new ArgumentNullException(nameof(requestMessage));
×
130

131
        requestMessage.Properties[FluentProperties.HttpCompletionOption] = completionOption;
×
132
    }
×
133

134

135
    /// <summary>
136
    /// Gets the cancellation token property from the specified <paramref name="requestMessage" /> properties dictionary.
137
    /// </summary>
138
    /// <param name="requestMessage">The request message containing the property.</param>
139
    /// <returns>
140
    /// The <see cref="CancellationToken"/> to use when sending the request message.
141
    /// </returns>
142
    /// <exception cref="ArgumentNullException"><paramref name="requestMessage"/> is <see langword="null"/></exception>
143
    public static CancellationToken GetCancellationToken(this HttpRequestMessage requestMessage)
144
    {
145
        if (requestMessage == null)
156!
146
            throw new ArgumentNullException(nameof(requestMessage));
×
147

148
        requestMessage.Properties.TryGetValue(FluentProperties.CancellationToken, out var propertyValue);
156✔
149
        return (CancellationToken)(propertyValue ?? CancellationToken.None);
156✔
150
    }
151

152
    /// <summary>
153
    /// Sets the cancellation token property on the specified <paramref name="requestMessage" /> properties dictionary.
154
    /// </summary>
155
    /// <param name="requestMessage">The request message containing the property.</param>
156
    /// <param name="cancellationToken">The <see cref="CancellationToken"/> to use when sending the request message.</param>
157
    /// <exception cref="ArgumentNullException"><paramref name="requestMessage"/> is <see langword="null"/></exception>
158
    public static void SetCancellationToken(this HttpRequestMessage requestMessage, CancellationToken cancellationToken)
159
    {
160
        if (requestMessage == null)
6!
161
            throw new ArgumentNullException(nameof(requestMessage));
×
162

163
        requestMessage.Properties[FluentProperties.CancellationToken] = cancellationToken;
6✔
164
    }
6✔
165

166

167
    /// <summary>
168
    /// Gets the content serializer property from the specified <paramref name="requestMessage" /> properties dictionary.
169
    /// </summary>
170
    /// <param name="requestMessage">The request message containing the property.</param>
171
    /// <returns>
172
    /// The <see cref="IContentSerializer"/> to use when serializing content to send in the request message.
173
    /// </returns>
174
    /// <exception cref="ArgumentNullException"><paramref name="requestMessage"/> is <see langword="null"/></exception>
175
    public static IContentSerializer GetContentSerializer(this HttpRequestMessage requestMessage)
176
    {
177
        if (requestMessage == null)
381!
178
            throw new ArgumentNullException(nameof(requestMessage));
×
179

180
        var propertyValue = requestMessage.Properties.GetOrAdd(FluentProperties.ContentSerializer, k => ContentSerializer.Current);
441✔
181
        return propertyValue as IContentSerializer;
381✔
182
    }
183

184
    /// <summary>
185
    /// Sets the content serializer property on the specified <paramref name="requestMessage" /> properties dictionary.
186
    /// </summary>
187
    /// <param name="requestMessage">The request message containing the property.</param>
188
    /// <param name="contentSerializer">The <see cref="IContentSerializer"/> to use when serializing content to send in the request message.</param>
189
    /// <exception cref="ArgumentNullException"><paramref name="requestMessage"/> is <see langword="null"/></exception>
190
    public static void SetContentSerializer(this HttpRequestMessage requestMessage, IContentSerializer contentSerializer)
191
    {
192
        if (requestMessage == null)
99!
193
            throw new ArgumentNullException(nameof(requestMessage));
×
194

195
        requestMessage.Properties[FluentProperties.ContentSerializer] = contentSerializer ?? ContentSerializer.Current;
99!
196
    }
99✔
197

198

199
    /// <summary>
200
    /// Synchronizes the specified request message with the fluent properties.
201
    /// </summary>
202
    /// <param name="requestMessage">The request message.</param>
203
    public static void Synchronize(this HttpRequestMessage requestMessage)
204
    {
205
        var urlBuilder = requestMessage.GetUrlBuilder();
378✔
206
        requestMessage.RequestUri = urlBuilder.ToUri();
378✔
207
    }
378✔
208

209

210
    /// <summary>
211
    /// Deserialize the HTTP response message asynchronously.
212
    /// </summary>
213
    /// <typeparam name="TData">The type of the data.</typeparam>
214
    /// <param name="responseMessage">The response message to deserialize.</param>
215
    /// <param name="ensureSuccess">Throw an exception if the HTTP response was unsuccessful.</param>
216
    /// <returns>
217
    /// The data object deserialized from the HTTP response message.
218
    /// </returns>
219
    /// <exception cref="HttpRequestException">Response status code does not indicate success.</exception>
220
    /// <exception cref="ArgumentNullException"><paramref name="responseMessage"/> is <see langword="null"/></exception>
221
    public static async Task<TData> DeserializeAsync<TData>(this HttpResponseMessage responseMessage, bool ensureSuccess = true)
222
    {
223
        if (responseMessage == null)
153!
224
            throw new ArgumentNullException(nameof(responseMessage));
×
225

226

227
        if (ensureSuccess)
153✔
228
            await responseMessage.EnsureSuccessStatusCode(true);
153✔
229

230
        var serializer = responseMessage.RequestMessage.GetContentSerializer();
147✔
231
        var data = await serializer
147✔
232
            .DeserializeAsync<TData>(responseMessage.Content)
147✔
233
            .ConfigureAwait(false);
147✔
234

235
        return data;
147✔
236
    }
147✔
237

238
    /// <summary>
239
    /// Throws an exception if the IsSuccessStatusCode property for the HTTP response is false.
240
    /// </summary>
241
    /// <param name="responseMessage">The response message.</param>
242
    /// <param name="includeContent">if set to <c>true</c> the response content is included in the exception.</param>
243
    /// <returns></returns>
244
    /// <exception cref="HttpRequestException">The HTTP response is unsuccessful.</exception>
245
    public static async Task EnsureSuccessStatusCode(this HttpResponseMessage responseMessage, bool includeContent)
246
    {
247
        if (responseMessage.IsSuccessStatusCode)
153✔
248
            return;
147✔
249

250
        // will throw if respose is a problem json
251
        await CheckResponseForProblem(responseMessage).ConfigureAwait(false);
6✔
252

253
        var message = $"Response status code does not indicate success: {responseMessage.StatusCode} ({responseMessage.ReasonPhrase});";
6✔
254

255
        if (!includeContent)
6!
256
            throw new HttpRequestException(message);
×
257

258
        var contentString = await responseMessage.Content.ReadAsStringAsync();
6✔
259
        if (string.IsNullOrEmpty(contentString))
6!
260
            throw new HttpRequestException(message);
6✔
261

262

263
        // add response content body to message for easier debugging
264
        message += Environment.NewLine + contentString;
×
265

266
        var exception = new HttpRequestException(message);
×
267
        exception.Data.Add("Response", contentString);
×
268

269
        throw exception;
×
270
    }
147✔
271

272
    private static async Task CheckResponseForProblem(HttpResponseMessage responseMessage)
273
    {
274
        string mediaType = responseMessage.Content?.Headers?.ContentType?.MediaType;
6!
275
        if (!string.Equals(mediaType, ProblemDetails.ContentType, StringComparison.OrdinalIgnoreCase))
6!
276
            return;
6✔
277

278
        var serializer = responseMessage.RequestMessage.GetContentSerializer();
×
279

280
        var problem = await serializer
×
281
            .DeserializeAsync<ProblemDetails>(responseMessage.Content)
×
282
            .ConfigureAwait(false);
×
283

284
        throw new ProblemException(problem);
×
285
    }
6✔
286
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc