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)

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


Attachments

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

Note You need to log in before you can comment on or make changes to this bug.