Skip to content

Commit 3a95ea1

Browse files
authored
Add StatusCode to HttpRequestException (#32455)
Adds HttpRequestException.StatusCode property, to be set by EnsureSuccessStatusCode and convenience methods when an exception is generated by a status code.
1 parent 7d4e1bb commit 3a95ea1

File tree

7 files changed

+86
-11
lines changed

7 files changed

+86
-11
lines changed

src/libraries/System.Net.Http/ref/System.Net.Http.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,9 +128,9 @@ public abstract partial class HttpContent : System.IDisposable
128128
protected HttpContent() { }
129129
public System.Net.Http.Headers.HttpContentHeaders Headers { get { throw null; } }
130130
public System.Threading.Tasks.Task CopyToAsync(System.IO.Stream stream) { throw null; }
131-
public System.Threading.Tasks.Task CopyToAsync(System.IO.Stream stream, System.Threading.CancellationToken cancellationToken) { throw null; }
132131
public System.Threading.Tasks.Task CopyToAsync(System.IO.Stream stream, System.Net.TransportContext context) { throw null; }
133132
public System.Threading.Tasks.Task CopyToAsync(System.IO.Stream stream, System.Net.TransportContext context, System.Threading.CancellationToken cancellationToken) { throw null; }
133+
public System.Threading.Tasks.Task CopyToAsync(System.IO.Stream stream, System.Threading.CancellationToken cancellationToken) { throw null; }
134134
protected virtual System.Threading.Tasks.Task<System.IO.Stream> CreateContentReadStreamAsync() { throw null; }
135135
protected virtual System.Threading.Tasks.Task<System.IO.Stream> CreateContentReadStreamAsync(System.Threading.CancellationToken cancellationToken) { throw null; }
136136
public void Dispose() { }
@@ -186,6 +186,8 @@ public partial class HttpRequestException : System.Exception
186186
public HttpRequestException() { }
187187
public HttpRequestException(string message) { }
188188
public HttpRequestException(string message, System.Exception inner) { }
189+
public HttpRequestException(string message, System.Exception inner, System.Net.HttpStatusCode? statusCode) { }
190+
public System.Net.HttpStatusCode? StatusCode { get { throw null; } }
189191
}
190192
public partial class HttpRequestMessage : System.IDisposable
191193
{

src/libraries/System.Net.Http/src/System/Net/Http/HttpRequestException.cs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,26 @@ public HttpRequestException(string message, Exception inner)
2828
}
2929
}
3030

31+
/// <summary>
32+
/// Initializes a new instance of the <see cref="HttpRequestException" /> class with a specific message that describes the current exception, an inner exception, and an HTTP status code.
33+
/// </summary>
34+
/// <param name="message">A message that describes the current exception.</param>
35+
/// <param name="inner">The inner exception.</param>
36+
/// <param name="statusCode">The HTTP status code.</param>
37+
public HttpRequestException(string message, Exception inner, HttpStatusCode? statusCode)
38+
: this(message, inner)
39+
{
40+
StatusCode = statusCode;
41+
}
42+
43+
/// <summary>
44+
/// Gets the HTTP status code to be returned with the exception.
45+
/// </summary>
46+
/// <value>
47+
/// An HTTP status code if the exception represents a non-successful result, otherwise <c>null</c>.
48+
/// </value>
49+
public HttpStatusCode? StatusCode { get; }
50+
3151
// This constructor is used internally to indicate that a request was not successfully sent due to an IOException,
3252
// and the exception occurred early enough so that the request may be retried on another connection.
3353
internal HttpRequestException(string message, Exception inner, RequestRetryType allowRetry)

src/libraries/System.Net.Http/src/System/Net/Http/HttpResponseMessage.cs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -169,11 +169,14 @@ public HttpResponseMessage EnsureSuccessStatusCode()
169169
{
170170
if (!IsSuccessStatusCode)
171171
{
172-
throw new HttpRequestException(SR.Format(
173-
System.Globalization.CultureInfo.InvariantCulture,
174-
SR.net_http_message_not_success_statuscode,
175-
(int)_statusCode,
176-
ReasonPhrase));
172+
throw new HttpRequestException(
173+
SR.Format(
174+
System.Globalization.CultureInfo.InvariantCulture,
175+
SR.net_http_message_not_success_statuscode,
176+
(int)_statusCode,
177+
ReasonPhrase),
178+
inner: null,
179+
_statusCode);
177180
}
178181

179182
return this;

src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientTest.cs

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -192,9 +192,16 @@ public async Task GetContentAsync_ErrorStatusCode_ExpectedExceptionThrown(bool w
192192
Content = withResponseContent ? new ByteArrayContent(new byte[1]) : null
193193
}))))
194194
{
195-
await Assert.ThrowsAsync<HttpRequestException>(() => client.GetStringAsync(CreateFakeUri()));
196-
await Assert.ThrowsAsync<HttpRequestException>(() => client.GetByteArrayAsync(CreateFakeUri()));
197-
await Assert.ThrowsAsync<HttpRequestException>(() => client.GetStreamAsync(CreateFakeUri()));
195+
HttpRequestException ex;
196+
197+
ex = await Assert.ThrowsAsync<HttpRequestException>(() => client.GetStringAsync(CreateFakeUri()));
198+
Assert.Equal(HttpStatusCode.BadRequest, ex.StatusCode);
199+
200+
ex = await Assert.ThrowsAsync<HttpRequestException>(() => client.GetByteArrayAsync(CreateFakeUri()));
201+
Assert.Equal(HttpStatusCode.BadRequest, ex.StatusCode);
202+
203+
ex = await Assert.ThrowsAsync<HttpRequestException>(() => client.GetStreamAsync(CreateFakeUri()));
204+
Assert.Equal(HttpStatusCode.BadRequest, ex.StatusCode);
198205
}
199206
}
200207

src/libraries/System.Net.Http/tests/FunctionalTests/HttpResponseMessageTest.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -105,12 +105,14 @@ public void EnsureSuccessStatusCode_VariousStatusCodes_ThrowIfNot2xx()
105105
{
106106
using (var m = new HttpResponseMessage(HttpStatusCode.MultipleChoices))
107107
{
108-
Assert.Throws<HttpRequestException>(() => m.EnsureSuccessStatusCode());
108+
var ex = Assert.Throws<HttpRequestException>(() => m.EnsureSuccessStatusCode());
109+
Assert.Equal(HttpStatusCode.MultipleChoices, ex.StatusCode);
109110
}
110111

111112
using (var m = new HttpResponseMessage(HttpStatusCode.BadGateway))
112113
{
113-
Assert.Throws<HttpRequestException>(() => m.EnsureSuccessStatusCode());
114+
var ex = Assert.Throws<HttpRequestException>(() => m.EnsureSuccessStatusCode());
115+
Assert.Equal(HttpStatusCode.BadGateway, ex.StatusCode);
114116
}
115117

116118
using (var response = new HttpResponseMessage(HttpStatusCode.OK))
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
// See the LICENSE file in the project root for more information.
4+
5+
using Xunit;
6+
7+
namespace System.Net.Http.Tests
8+
{
9+
public class HttpRequestExceptionTests
10+
{
11+
[Fact]
12+
public void DefaultConstructors_HasNoStatusCode()
13+
{
14+
var exception = new HttpRequestException();
15+
Assert.Null(exception.StatusCode);
16+
17+
exception = new HttpRequestException("message");
18+
Assert.Null(exception.StatusCode);
19+
20+
exception = new HttpRequestException("message", new InvalidOperationException());
21+
Assert.Null(exception.StatusCode);
22+
}
23+
24+
[Fact]
25+
public void StoresStatusCode()
26+
{
27+
var exception = new HttpRequestException("message", null, HttpStatusCode.InternalServerError);
28+
Assert.Equal(HttpStatusCode.InternalServerError, exception.StatusCode);
29+
}
30+
31+
[Fact]
32+
public void StoresNonStandardStatusCode()
33+
{
34+
var statusCode = (HttpStatusCode)999;
35+
36+
var exception = new HttpRequestException("message", null, statusCode);
37+
Assert.Equal(statusCode, exception.StatusCode);
38+
}
39+
}
40+
}

src/libraries/System.Net.Http/tests/UnitTests/System.Net.Http.Unit.Tests.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -415,6 +415,7 @@
415415
<Compile Include="MockContent.cs" />
416416
<Compile Include="StreamToStreamCopyTest.cs" />
417417
<Compile Include="HttpEnvironmentProxyTest.cs" />
418+
<Compile Include="HttpRequestExceptionTests.cs" />
418419
<Compile Include="HttpWindowsProxyTest.cs" />
419420
<Compile Include="SystemProxyInfoTest.cs" />
420421
<Compile Include="..\..\src\System\Net\Http\SocketsHttpHandler\HttpNoProxy.cs">

0 commit comments

Comments
 (0)