Skip to content

Commit eda6631

Browse files
committed
[AndroidClientHandler] Wrap Java exceptions in .NET ones
Context: 60363ef This commit a follow-up to 60363ef in that it causes less Java exceptions to "leak" to applications which use code shared between platforms that might not be able to check for Java exception types directly (because they don't link against `Mono.Android.dll`). However, instead of making the behavior optional, as implemented in 60363ef, this commit unconditionally wraps `Java.IO.Exception` and some of its derivatives in the standard .NET `WebException`. This makes the handler to behave in a manner that's closer to how other `HttpClient` custom handlers behave. The `$(AndroidBoundExceptionType)` MSBuild property must be set to `System` in order to use the wrapped exceptions.
1 parent d471b4a commit eda6631

File tree

1 file changed

+29
-13
lines changed

1 file changed

+29
-13
lines changed

src/Mono.Android/Xamarin.Android.Net/AndroidClientHandler.cs

Lines changed: 29 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -282,14 +282,24 @@ string EncodeUrl (Uri url)
282282
if (ReadTimeout != TimeSpan.Zero)
283283
java_connection!.ReadTimeout = checked ((int)ReadTimeout.TotalMilliseconds);
284284

285-
HttpURLConnection httpConnection = await SetupRequestInternal (request, java_connection!).ConfigureAwait (continueOnCapturedContext: false);;
286-
var response = await ProcessRequest (request, java_url, httpConnection, cancellationToken, redirectState).ConfigureAwait (continueOnCapturedContext: false);;
287-
if (response != null)
288-
return response;
289-
290-
if (redirectState.NewUrl == null)
291-
throw new InvalidOperationException ("Request redirected but no new URI specified");
292-
request.Method = redirectState.Method;
285+
try {
286+
HttpURLConnection httpConnection = await SetupRequestInternal (request, java_connection!).ConfigureAwait (continueOnCapturedContext: false);
287+
HttpResponseMessage? response = await ProcessRequest (request, java_url, httpConnection, cancellationToken, redirectState).ConfigureAwait (continueOnCapturedContext: false);
288+
if (response != null)
289+
return response;
290+
291+
if (redirectState.NewUrl == null)
292+
throw new InvalidOperationException ("Request redirected but no new URI specified");
293+
request.Method = redirectState.Method;
294+
} catch (Java.Net.SocketTimeoutException ex) when (JNIEnv.ShouldWrapJavaException (ex)) {
295+
throw new WebException (ex.Message, ex, WebExceptionStatus.Timeout, null);
296+
} catch (Java.Net.UnknownServiceException ex) when (JNIEnv.ShouldWrapJavaException (ex)) {
297+
throw new WebException (ex.Message, ex, WebExceptionStatus.ProtocolError, null);
298+
} catch (Java.Lang.SecurityException ex) when (JNIEnv.ShouldWrapJavaException (ex)) {
299+
throw new WebException (ex.Message, ex, WebExceptionStatus.SecureChannelFailure, null);
300+
} catch (Java.IO.IOException ex) when (JNIEnv.ShouldWrapJavaException (ex)) {
301+
throw new WebException (ex.Message, ex, WebExceptionStatus.UnknownError, null);
302+
}
293303
}
294304
}
295305

@@ -339,8 +349,11 @@ Task ConnectAsync (HttpURLConnection httpConnection, CancellationToken ct)
339349
if (t.Exception != null) Logger.Log(LogLevel.Info, LOG_APP, $"Disconnection exception: {t.Exception}");
340350
}, TaskScheduler.Default)))
341351
httpConnection?.Connect ();
342-
} catch {
343-
ct.ThrowIfCancellationRequested ();
352+
} catch (Exception ex) {
353+
if (ct.IsCancellationRequested) {
354+
Logger.Log (LogLevel.Info, LOG_APP, $"Exception caught while cancelling connection: {ex}");
355+
ct.ThrowIfCancellationRequested ();
356+
}
344357
throw;
345358
}
346359
}, ct);
@@ -449,8 +462,7 @@ protected virtual async Task WriteRequestContentToOutput (HttpRequestMessage req
449462
if (Logger.LogNet)
450463
Logger.Log (LogLevel.Info, LOG_APP, $"Reading...");
451464
ret.Content = GetContent (httpConnection, httpConnection.InputStream!);
452-
}
453-
else {
465+
} else {
454466
if (Logger.LogNet)
455467
Logger.Log (LogLevel.Info, LOG_APP, $"Status code is {statusCode}, reading...");
456468
// For 400 >= response code <= 599 the Java client throws the FileNotFound exception when attempting to read from the input stream.
@@ -818,7 +830,11 @@ void AppendEncoding (string encoding, ref List <string>? list)
818830
if (httpConnection == null)
819831
throw new InvalidOperationException ($"Unsupported URL scheme {conn.URL?.Protocol}");
820832

821-
httpConnection.RequestMethod = request.Method.ToString ();
833+
try {
834+
httpConnection.RequestMethod = request.Method.ToString ();
835+
} catch (Java.Net.ProtocolException ex) when (JNIEnv.ShouldWrapJavaException (ex)) {
836+
throw new WebException (ex.Message, ex, WebExceptionStatus.ProtocolError, null);
837+
}
822838

823839
// SSL context must be set up as soon as possible, before adding any content or
824840
// headers. Otherwise Java won't use the socket factory

0 commit comments

Comments
 (0)