Bug 55477 - Stream Closed Exception thrown in AndroidClientHandler during redirected HTTP POST call.
Summary: Stream Closed Exception thrown in AndroidClientHandler during redirected HTTP...
Status: RESOLVED FIXED
Alias: None
Product: Android
Classification: Xamarin
Component: Android+BCL Integration (show other bugs)
Version: 7.2 (15.1)
Hardware: PC Windows
: Normal normal
Target Milestone: 15.4
Assignee: Marek Habersack
URL:
Depends on:
Blocks:
 
Reported: 2017-04-21 21:28 UTC by Jeremy Cook
Modified: 2017-10-05 17:05 UTC (History)
2 users (show)

Tags:
Is this bug a regression?: ---
Last known good build:

Notice (2018-05-24): bugzilla.xamarin.com is now in read-only mode.

Please join us on Visual Studio Developer Community and in the Xamarin and Mono organizations on GitHub to continue tracking issues. Bugzilla will remain available for reference in read-only mode. We will continue to work on open Bugzilla bugs, copy them to the new locations as needed for follow-up, and add the new items under Related Links.

Our sincere thanks to everyone who has contributed on this bug tracker over the years. Thanks also for your understanding as we make these adjustments and improvements for the future.


Please create a new report on Developer Community or GitHub with your current version information, steps to reproduce, and relevant error messages or log files if you are hitting an issue that looks similar to this resolved bug and you do not yet see a matching new report.

Related Links:
Status:
RESOLVED FIXED

Description Jeremy Cook 2017-04-21 21:28:33 UTC
I am seeing a "System.ObjectDisposedException: Cannot access a closed Stream." call in AndroidClientHandler when my HTTP POST method is redirected over HTTPS.   The exception is coming from the Stream.CopyToAsync() call in this code in AndroidClientHandler:
	if (httpConnection.DoOutput) {
		using (var stream = await request.Content.ReadAsStreamAsync ().ConfigureAwait (false)) {
			await stream.CopyToAsync(httpConnection.OutputStream, 4096, cancellationToken)
							.ConfigureAwait(false);
					}
				}

What appears to be happening is that when the redirect over HTTPS is made, request.Content.ReadAsStreamAsync() is called again on the same HttpContent stream.  According to what I've read (http://stackoverflow.com/questions/26942514/multiple-calls-to-httpcontent-readasasync),  you can only read the HttpContent stream once.   This code should probably be refactored to make the ReadAsStreamAsync() call only one time per unique HTTP request, and then rewinding and resuing it for all following redirected calls.

Thanks
Comment 1 Marek Habersack 2017-04-24 09:16:19 UTC
Can you please attach a small application that reproduces the issue? Also, can you attach the stack trace you get when the issue occurs? Thanks!
Comment 2 Jeremy Cook 2017-04-24 23:08:53 UTC
Hi Marek,
We use a modified version of AndroidClientHandler in our app, because we talk to hardware devices that have invalid/expired certs that we can't change, and AndroidClientHandler doesn't have a way to ignore those errors.  I could provide a stack trace using our modified version, but not sure how much that would help you. (the modifications are pretty simple, it's almost identical to the version in github).  Also, since our app talks to hardware devices, I don't have a way to provide you an app that reproduces this, short of creating a device simulator or providing you with a rather bulky printer/scanner/copier device.   On a side note, AndroidClientHandler also does not properly honor the UseProxy setting.  I can provide you a copy of our modified AndroidClientHandler for you to compare and maybe make a change to get that fixed.
Thanks
Comment 3 Marek Habersack 2017-04-25 11:16:48 UTC
Hi Jeremy,

Regarding the SSL certs, did you try to use these https://github.com/xamarin/xamarin-android/blob/master/src/Mono.Android/Xamarin.Android.Net/AndroidClientHandler.cs#L562-L607 ? They should let you do what you need in a derived class.

I'd love to see the modifications you made to the class, thanks :)

Regarding UseProxy. This one's tricky as the Java API that handles proxies doesn't support passing credentials and we use the Java connection class under the hood, but there certainly is room for improvement there. If you could please file a separate bug for the proxy issues you're seeing that'd be great! Thanks!
Comment 4 Jeremy Cook 2017-04-25 17:18:34 UTC
Hi Marek,

We tried deriving a new class for SSL certs, but that approach didn't work.  I'll send you an email with our modified code, and explanations for all that we've done.   

Thanks!
Comment 5 Marek Habersack 2017-05-26 10:52:10 UTC
PR opened: https://github.com/xamarin/xamarin-android/pull/608