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

Failed to read stream from HttpClient.Get with option HttpCompletionOption.ResponseHeadersRead #255

Closed
jiabiao opened this issue Jun 3, 2017 · 11 comments

Comments

@jiabiao
Copy link

jiabiao commented Jun 3, 2017

The following code works fine under full framework, but get exception under .net core 1.0 and 2.0.

var res = new HttpClient().GetAsync("https://github.com/adamhathcock/sharpcompress/raw/master/tests/TestArchives/Archives/Tar.tar",
	HttpCompletionOption.ResponseHeadersRead).Result;
var stream = res.Content.ReadAsStreamAsync().Result;
var reader = ReaderFactory.Open(stream);
reader.MoveToNextEntry();
reader.WriteEntryTo(new MemoryStream());  //System.IO.IOException: 'Unable to read data from the transport connection. The connection was closed before all data could be read. Expected 105472 bytes, read 512 bytes.'

Changing the HttpClient.Get option to HttpCompletionOption.ResponseContentRead also works. But for large files, it can not start decompressing until the entire file is downloaded.

@adamhathcock
Copy link
Owner

Worked for me

    class Program
    {
        static void Main(string[] args)
        {
            Test().Wait();
        }

        public static async Task Test()
        {
            using(var client = new HttpClient())
            using (var response = await client.GetAsync("https://github.com/adamhathcock/sharpcompress/raw/master/tests/TestArchives/Archives/Tar.tar",
                    HttpCompletionOption.ResponseHeadersRead))
            {
                var stream = await response.Content.ReadAsStreamAsync();
                using (var reader = ReaderFactory.Open(stream))
                {
                    reader.MoveToNextEntry();
                    reader.WriteEntryTo(new MemoryStream());  //System
                }
            }
        }
    }

Always use async/await and using statements please.

@adamhathcock
Copy link
Owner

This netcoreapp1.1 haven't tried 2.0

@jiabiao
Copy link
Author

jiabiao commented Jun 4, 2017

Weird, your code throw the same exception on my end.
sharpcompress

I did use async/await and using statements in my actual code. The code in the original post is simplified for demonstration purposes.

@adamhathcock
Copy link
Owner

Weird.

Just in case I put my code here: https://github.com/adamhathcock/sc-http-test

@jiabiao
Copy link
Author

jiabiao commented Jun 4, 2017

git clone & dotnet run still get the same exception.
I will debug with source to see what happened.

D:\Code\netcore>git clone https://github.com/adamhathcock/sc-http-test.git
Cloning into 'sc-http-test'...
remote: Counting objects: 6, done.
remote: Compressing objects: 100% (6/6), done.
Unpacking objects: 100% (6/6), done.
remote: Total 6 (delta 0), reused 6 (delta 0), pack-reused 0
Checking connectivity... done.

D:\Code\netcore>cd sc-http-test

D:\Code\netcore\sc-http-test>dotnet restore
  Restoring packages for D:\Code\netcore\sc-http-test\test.csproj...
  Generating MSBuild file D:\Code\netcore\sc-http-test\obj\test.csproj.nuget.g.props.
  Generating MSBuild file D:\Code\netcore\sc-http-test\obj\test.csproj.nuget.g.targets.
  Writing lock file to disk. Path: D:\Code\netcore\sc-http-test\obj\project.assets.json
  Restore completed in 1.46 sec for D:\Code\netcore\sc-http-test\test.csproj.

  NuGet Config files used:
      C:\Users\jiabiao\AppData\Roaming\NuGet\NuGet.Config
      C:\Program Files (x86)\NuGet\Config\Microsoft.VisualStudio.Offline.config

  Feeds used:
      https://api.nuget.org/v3/index.json
      C:\Program Files (x86)\Microsoft SDKs\NuGetPackages\

D:\Code\netcore\sc-http-test>dotnet run

Unhandled Exception: System.AggregateException: One or more errors occurred. (Unable to read data from the transport connection. The connection was closed before all data could be read. Expected 105472 bytes, read 512 bytes.) ---> System.IO.IOException: Unable to read data from the transport connection. The connection was closed before all data could be read. Expected 105472 bytes, read 512 bytes.
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
   at System.Net.Http.WinHttpResponseStream.Read(Byte[] buffer, Int32 offset, Int32 count)
   at System.Net.Http.DelegatingStream.Read(Byte[] buffer, Int32 offset, Int32 count)
   at SharpCompress.IO.RewindableStream.Read(Byte[] buffer, Int32 offset, Int32 count)
   at SharpCompress.IO.RewindableStream.Read(Byte[] buffer, Int32 offset, Int32 count)
   at SharpCompress.Common.Tar.TarReadOnlySubStream.Read(Byte[] buffer, Int32 offset, Int32 count)
   at SharpCompress.Common.EntryStream.Read(Byte[] buffer, Int32 offset, Int32 count)
   at SharpCompress.Common.EntryStream.SkipEntry()
   at SharpCompress.Common.EntryStream.Dispose(Boolean disposing)
   at System.IO.Stream.Close()
   at SharpCompress.Readers.AbstractReader`2.Write(Stream writeStream)
   at SharpCompress.Readers.AbstractReader`2.WriteEntryTo(Stream writableStream)
   at test.Program.<Test>d__1.MoveNext() in D:\Code\netcore\sc-http-test\Program.cs:line 26
   --- End of inner exception stack trace ---
   at System.Threading.Tasks.Task.ThrowIfExceptional(Boolean includeTaskCanceledExceptions)
   at System.Threading.Tasks.Task.Wait(Int32 millisecondsTimeout, CancellationToken cancellationToken)
   at System.Threading.Tasks.Task.Wait()
   at test.Program.Main(String[] args) in D:\Code\netcore\sc-http-test\Program.cs:line 13

D:\Code\netcore\sc-http-test>

@jiabiao
Copy link
Author

jiabiao commented Jun 4, 2017

I created an issue https://github.com/dotnet/corefx/issues/20676.
Reading 0 byte from network stream will cause this exception.
So if the count parameter is 0, the RewindableStream.Read method should return 0 directly.

        public override int Read(byte[] buffer, int offset, int count)
        {
            if (count == 0)
            {
                return 0;
            }

@adamhathcock
Copy link
Owner

I don't get how I didn't get the exception but you did. Just happened to read zero bytes and I didn't?

@jiabiao
Copy link
Author

jiabiao commented Jun 5, 2017

This issue occurs only on windows, Are you using macOS or Linux?
Otherwise, I don't know why you didn't get the exception. You can add a conditional breakpoints at the beginning of RewindableStream.Read method to investigate.

@adamhathcock
Copy link
Owner

You're right. I get this on Windows but not macOS

@adamhathcock
Copy link
Owner

@jiabiao
Copy link
Author

jiabiao commented Jun 9, 2017

thanks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants