Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve handling of Unprocessable Entity (422) HTTP errors #121

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
## 5.11.0
* Improve handling of Unprocessable Entity (422) HTTP errors

## 5.10.0
* Add plan create/update/find API endpoint
* Add `TransactionReview` webhook notification support
Expand Down
2 changes: 2 additions & 0 deletions src/Braintree/Exceptions/UnexpectedException.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,7 @@ namespace Braintree.Exceptions
{
public class UnexpectedException : BraintreeException
{
public UnexpectedException() : base() { }
public UnexpectedException(string message) : base(message) { }
}
}
7 changes: 7 additions & 0 deletions src/Braintree/Exceptions/UnprocessableEntityException.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace Braintree.Exceptions
{
public class UnprocessableEntityException : BraintreeException
{
public UnprocessableEntityException(string message) : base(message) { }
}
}
104 changes: 59 additions & 45 deletions src/Braintree/HttpService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -84,36 +84,44 @@ public virtual void SetRequestHeaders(HttpWebRequest request)
#endif

#if netcore
public HttpRequestMessage GetHttpRequest(string URL, string method) {
public HttpRequestMessage GetHttpRequest(string URL, string method)
{
var request = Configuration.HttpRequestMessageFactory(new HttpMethod(method), URL);
request.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue(GetAuthorizationSchema(), GetAuthorizationHeader());
SetRequestHeaders(request);
return request;
}

public string GetHttpResponse(HttpRequestMessage request) {
var response = httpClient.SendAsync(request).GetAwaiter().GetResult();
if (response.StatusCode != (HttpStatusCode)422)
public string GetHttpResponse(HttpRequestMessage request)
{
using (var response = httpClient.SendAsync(request).GetAwaiter().GetResult())
{
ThrowExceptionIfErrorStatusCode(response.StatusCode, null);
using (var responseStream = response.Content.ReadAsStreamAsync().GetAwaiter().GetResult())
{
string responseContent = ParseResponseStream(responseStream);
ThrowExceptionIfErrorStatusCode(response.StatusCode, responseContent);
return responseContent;
}
}

return ParseResponseStream(response.Content.ReadAsStreamAsync().GetAwaiter().GetResult());
}

public async Task<string> GetHttpResponseAsync(HttpRequestMessage request) {
var response = await httpClient.SendAsync(request).ConfigureAwait(false);
if (response.StatusCode != (HttpStatusCode)422)
public async Task<string> GetHttpResponseAsync(HttpRequestMessage request)
{
using (var response = await httpClient.SendAsync(request).ConfigureAwait(false))
{
ThrowExceptionIfErrorStatusCode(response.StatusCode, null);
using (var responseStream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false))
{
string responseContent = await ParseResponseStreamAsync(responseStream);
ThrowExceptionIfErrorStatusCode(response.StatusCode, responseContent);
return responseContent;
}
}

return await ParseResponseStreamAsync(await response.Content.ReadAsStreamAsync().ConfigureAwait(false));
}
#else
public HttpWebRequest GetHttpRequest(string URL, string method) {
public HttpWebRequest GetHttpRequest(string URL, string method)
{
const int SecurityProtocolTypeTls12 = 3072;
ServicePointManager.SecurityProtocol = ServicePointManager.SecurityProtocol | ((SecurityProtocolType) SecurityProtocolTypeTls12);
ServicePointManager.SecurityProtocol = ServicePointManager.SecurityProtocol | ((SecurityProtocolType)SecurityProtocolTypeTls12);

var request = Configuration.HttpWebRequestFactory(URL);
SetRequestProxy(request);
Expand All @@ -126,53 +134,59 @@ public virtual void SetRequestHeaders(HttpWebRequest request)
return request;
}

public string GetHttpResponse(HttpWebRequest request) {
try {
using (var response = (HttpWebResponse) request.GetResponse())
public string GetHttpResponse(HttpWebRequest request)
{
try
{
using (var response = (HttpWebResponse)request.GetResponse())
{
return ParseResponseStream(GetResponseStream(response));
using (var responseStream = GetResponseStream(response))
{
return ParseResponseStream(responseStream);
}
}
}
catch (WebException e)
{
using (var response = (HttpWebResponse) e.Response)
using (var response = (HttpWebResponse)e.Response)
{
if (response == null) throw e;

if (response.StatusCode == (HttpStatusCode)422) // UnprocessableEntity
if (response == null) throw;
using (var responseStream = GetResponseStream((HttpWebResponse)e.Response))
{
return ParseResponseStream(GetResponseStream((HttpWebResponse)e.Response));
string responseContent = ParseResponseStream(responseStream);
ThrowExceptionIfErrorStatusCode(response.StatusCode, responseContent);
return responseContent;
}

ThrowExceptionIfErrorStatusCode(response.StatusCode, null);
}

throw e;
throw;
}
}

public async Task<string> GetHttpResponseAsync(HttpWebRequest request) {
try {
using (var response = (HttpWebResponse) await request.GetResponseAsync().ConfigureAwait(false))
public async Task<string> GetHttpResponseAsync(HttpWebRequest request)
{
try
{
using (var response = (HttpWebResponse)await request.GetResponseAsync().ConfigureAwait(false))
{
return await ParseResponseStreamAsync(GetResponseStream(response)).ConfigureAwait(false);
using (var responseStream = GetResponseStream(response))
{
return await ParseResponseStreamAsync(responseStream).ConfigureAwait(false);
}
}
}
catch (WebException e)
{
using (var response = (HttpWebResponse) e.Response)
using (var response = (HttpWebResponse)e.Response)
{
if (response == null) throw e;

if (response.StatusCode == (HttpStatusCode)422) // UnprocessableEntity
if (response == null) throw;
using (var responseStream = GetResponseStream((HttpWebResponse)e.Response))
{
return await ParseResponseStreamAsync(GetResponseStream((HttpWebResponse) e.Response)).ConfigureAwait(false);
string responseContent = await ParseResponseStreamAsync(responseStream).ConfigureAwait(false);
ThrowExceptionIfErrorStatusCode(response.StatusCode, responseContent);
return responseContent;
}

ThrowExceptionIfErrorStatusCode(response.StatusCode, null);
}

throw e;
throw;
}
}
#endif
Expand Down Expand Up @@ -283,7 +297,7 @@ public static void ThrowExceptionIfErrorStatusCode(HttpStatusCode httpStatusCode
{
if (httpStatusCode != HttpStatusCode.OK && httpStatusCode != HttpStatusCode.Created)
{
switch ((int) httpStatusCode)
switch ((int)httpStatusCode)
{
case 401:
throw new AuthenticationException();
Expand All @@ -293,6 +307,8 @@ public static void ThrowExceptionIfErrorStatusCode(HttpStatusCode httpStatusCode
throw new NotFoundException();
case 408:
throw new RequestTimeoutException();
case 422:
throw new UnprocessableEntityException(message);
case 426:
throw new UpgradeRequiredException();
case 429:
Expand All @@ -304,9 +320,7 @@ public static void ThrowExceptionIfErrorStatusCode(HttpStatusCode httpStatusCode
case 504:
throw new GatewayTimeoutException();
default:
var exception = new UnexpectedException();
exception.Source = "Unexpected HTTP_RESPONSE " + httpStatusCode;
throw exception;
throw new UnexpectedException("Unexpected HTTP_RESPONSE " + httpStatusCode + ". Response: " + message);
}
}
}
Expand Down