Skip to content

Commit 2a52239

Browse files
committed
Improved error handling to show response body content
1 parent 20fa1eb commit 2a52239

File tree

3 files changed

+40
-112
lines changed

3 files changed

+40
-112
lines changed

Diff for: CSharp.StackExchange/Api/Impl/StackExchangeErrorHandler.cs

+35-67
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,10 @@
1919
#endregion
2020

2121
using System;
22+
using System.IO;
23+
using System.IO.Compression;
2224
using System.Net;
25+
using System.Text;
2326
using Spring.Http;
2427
using Spring.Rest.Client;
2528
using Spring.Rest.Client.Support;
@@ -33,6 +36,9 @@ namespace CSharp.StackExchange.Api.Impl
3336
/// <author>Scott Smith</author>
3437
class StackExchangeErrorHandler : DefaultResponseErrorHandler
3538
{
39+
// Default encoding for JSON
40+
private static readonly Encoding DefaultCharset = new UTF8Encoding(false);
41+
3642
/// <summary>
3743
/// Handles the error in the given response.
3844
/// <para/>
@@ -53,7 +59,7 @@ public override void HandleError(Uri requestUri, HttpMethod requestMethod, HttpR
5359
switch (type)
5460
{
5561
case 4:
56-
HandleClientErrors(response.StatusCode);
62+
HandleClientErrors(response);
5763
break;
5864
case 5:
5965
HandleServerErrors(response.StatusCode);
@@ -71,80 +77,42 @@ public override void HandleError(Uri requestUri, HttpMethod requestMethod, HttpR
7177
}
7278
}
7379

74-
private void HandleClientErrors(HttpStatusCode statusCode)
75-
{
76-
if (statusCode == (HttpStatusCode)400)
77-
{
78-
throw new StackExchangeApiException(
79-
"An invalid parameter was passed, this includes even 'high level' parameters like key or site.",
80-
StackExchangeApiError.BadParameter);
81-
}
82-
83-
if (statusCode == (HttpStatusCode)401)
84-
{
85-
throw new StackExchangeApiException(
86-
"A method that requires an access token (obtained via authentication) was called without one.",
87-
StackExchangeApiError.AccessTokenRequired);
88-
}
89-
90-
if (statusCode == (HttpStatusCode)402)
91-
{
92-
throw new StackExchangeApiException(
93-
"An invalid access token was passed to a method.",
94-
StackExchangeApiError.InvalidAccessToken);
95-
}
80+
private void HandleClientErrors(HttpResponseMessage<byte[]> response)
81+
{
82+
if (response == null) throw new ArgumentNullException("response");
9683

97-
if (statusCode == (HttpStatusCode)403)
98-
{
99-
throw new StackExchangeApiException(
100-
"A method which requires certain permissions was called with an access token that lacks those permissions.",
101-
StackExchangeApiError.AccessDenied);
102-
}
84+
var errorText = ExtractErrorDetailsFromResponse(response);
10385

104-
if (statusCode == (HttpStatusCode)404)
105-
{
106-
throw new StackExchangeApiException(
107-
"An attempt was made to call a method that does not exist. Note, calling methods that expect numeric ids (like /users/{ids}) with non-numeric ids can also result in this error.",
108-
StackExchangeApiError.NoMethod);
109-
}
110-
111-
if (statusCode == (HttpStatusCode)405)
112-
{
113-
throw new StackExchangeApiException(
114-
"A method was called in a manner that requires an application key (generally, with an access token), but no key was passed.",
115-
StackExchangeApiError.KeyRequired);
116-
}
117-
118-
if (statusCode == (HttpStatusCode)406)
119-
{
120-
throw new StackExchangeApiException(
121-
"An access token is no longer believed to be secure, normally because it was used on a non-HTTPS call. The access token will be invalidated if this error is returned.",
122-
StackExchangeApiError.AccessTokenCompromised);
123-
}
124-
}
86+
throw new StackExchangeApiException(
87+
"The server indicated a client error has occured and returned the following HTTP status code: " + response.StatusCode +
88+
Environment.NewLine + Environment.NewLine +
89+
errorText,
90+
StackExchangeApiError.ClientError);
91+
}
12592

12693
private void HandleServerErrors(HttpStatusCode statusCode)
12794
{
128-
if (statusCode == (HttpStatusCode)500)
129-
{
130-
throw new StackExchangeApiException(
131-
"An unexpected error occurred in the API. It has been logged, and Stack Exchange developers have been notified. You should report these errors on Stack Apps if you want to be notified when they're fixed.",
132-
StackExchangeApiError.InternalError);
133-
}
95+
throw new StackExchangeApiException(
96+
"The server indicated a server error has occured and returned the following HTTP status code: " + statusCode,
97+
StackExchangeApiError.ServerError);
98+
}
13499

135-
if (statusCode == (HttpStatusCode)502)
100+
private string ExtractErrorDetailsFromResponse(HttpResponseMessage<byte[]> response)
101+
{
102+
if (response.Body == null)
136103
{
137-
throw new StackExchangeApiException(
138-
"An application has violated part of the rate limiting contract, so the request was terminated.",
139-
StackExchangeApiError.ThrottleViolation);
104+
return null;
140105
}
106+
var contentType = response.Headers.ContentType;
107+
var charset = (contentType != null && contentType.CharSet != null) ? contentType.CharSet : DefaultCharset;
141108

142-
if (statusCode == (HttpStatusCode)503)
143-
{
144-
throw new StackExchangeApiException(
145-
"Some or all of the API is unavailable. Applications should backoff on requests to the method invoked.",
146-
StackExchangeApiError.TemporarilyUnavailable);
147-
}
148-
}
109+
var stream = new MemoryStream(response.Body);
110+
var gZipStream = new GZipStream(stream, CompressionMode.Decompress);
111+
112+
var responseUncompressed = new byte[response.Body.Length * 10];
113+
var size = gZipStream.Read(responseUncompressed, 0, responseUncompressed.Length);
114+
115+
return charset.GetString(responseUncompressed, 0, size);
116+
}
149117
}
150118
}

Diff for: CSharp.StackExchange/Api/StackExchangeApiError.cs

+4-44
Original file line numberDiff line numberDiff line change
@@ -28,53 +28,13 @@ namespace CSharp.StackExchange.Api
2828
public enum StackExchangeApiError
2929
{
3030
/// <summary>
31-
/// 400 status code. An invalid parameter was passed, this includes even "high level" parameters like key or site.
31+
/// 400 status codes.
3232
/// </summary>
33-
BadParameter,
34-
35-
/// <summary>
36-
/// 401 status code. A method that requires an access token (obtained via authentication) was called without one.
37-
/// </summary>
38-
AccessTokenRequired,
39-
40-
/// <summary>
41-
/// 402 status code. An invalid access token was passed to a method.
42-
/// </summary>
43-
InvalidAccessToken,
44-
45-
/// <summary>
46-
/// 403 status code. A method which requires certain permissions was called with an access token that lacks those permissions.
47-
/// </summary>
48-
AccessDenied,
49-
50-
/// <summary>
51-
/// 404 status code. An attempt was made to call a method that does not exist. Note, calling methods that expect numeric ids (like /users/{ids}) with non-numeric ids can also result in this error.
52-
/// </summary>
53-
NoMethod,
54-
55-
/// <summary>
56-
/// 405 status code. A method was called in a manner that requires an application key (generally, with an access token), but no key was passed.
57-
/// </summary>
58-
KeyRequired,
59-
60-
/// <summary>
61-
/// 406 status code. An access token is no longer believed to be secure, normally because it was used on a non-HTTPS call. The access token will be invalidated if this error is returned.
62-
/// </summary>
63-
AccessTokenCompromised,
64-
65-
/// <summary>
66-
/// 500 status code. An unexpected error occurred in the API. It has been logged, and Stack Exchange developers have been notified. You should report these errors on Stack Apps if you want to be notified when they're fixed.
67-
/// </summary>
68-
InternalError,
69-
70-
/// <summary>
71-
/// 502 status code. An application has violated part of the rate limiting contract, so the request was terminated.
72-
/// </summary>
73-
ThrottleViolation,
33+
ClientError,
7434

7535
/// <summary>
76-
/// 503 status code. Some or all of the API is unavailable. Applications should backoff on requests to the method invoked.
36+
/// 500 status codes.
7737
/// </summary>
78-
TemporarilyUnavailable
38+
ServerError
7939
}
8040
}

Diff for: CSharp.StackExchange/Api/StackExchangeApiException.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ public StackExchangeApiException(string message, StackExchangeApiError error)
6161
public StackExchangeApiException(string message, Exception innerException)
6262
: base(message, innerException)
6363
{
64-
_error = StackExchangeApiError.InternalError;
64+
_error = StackExchangeApiError.ServerError;
6565
}
6666

6767
/// <summary>

0 commit comments

Comments
 (0)