From 44cae6904d7c8e7223ebe9d2fa7ad185145262ab Mon Sep 17 00:00:00 2001 From: Robert McRackan Date: Mon, 14 Sep 2026 17:15:15 -0400 Subject: [PATCH] Experiment: RequestNextByteRangeAsync expects `PartialContent`. One user ( #2047 ) is getting `OK`. Attempting to support it --- Source/.mcp.json | 8 ++++ Source/AaxDecrypter/NetworkFileStream.cs | 58 ++++++++++++++++-------- 2 files changed, 48 insertions(+), 18 deletions(-) create mode 100644 Source/.mcp.json diff --git a/Source/.mcp.json b/Source/.mcp.json new file mode 100644 index 00000000..99551812 --- /dev/null +++ b/Source/.mcp.json @@ -0,0 +1,8 @@ +{ + "servers": { + "github": { + "type": "http", + "url": "https://api.githubcopilot.com/mcp/" + } + } +} diff --git a/Source/AaxDecrypter/NetworkFileStream.cs b/Source/AaxDecrypter/NetworkFileStream.cs index 9bb4b23b..47a5bc31 100644 --- a/Source/AaxDecrypter/NetworkFileStream.cs +++ b/Source/AaxDecrypter/NetworkFileStream.cs @@ -241,33 +241,55 @@ public class NetworkFileStream : Stream, IUpdatable } } - private async Task RequestNextByteRangeAsync(HttpClient client) - { - using var request = new HttpRequestMessage(HttpMethod.Get, Uri); + private async Task RequestNextByteRangeAsync(HttpClient client) + { + using var request = new HttpRequestMessage(HttpMethod.Get, Uri); - //Just in case it snuck in the saved json (Issue #1232) - RequestHeaders.Remove("Range"); + //Just in case it snuck in the saved json (Issue #1232) + RequestHeaders.Remove("Range"); - foreach (var header in RequestHeaders) - request.Headers.Add(header.Key, header.Value); + foreach (var header in RequestHeaders) + request.Headers.Add(header.Key, header.Value); - request.Headers.Add("Range", $"bytes={WritePosition}-"); + request.Headers.Add("Range", $"bytes={WritePosition}-"); - var response = await client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, _cancellationSource.Token); + var response = await client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, _cancellationSource.Token); - if (response.StatusCode != HttpStatusCode.PartialContent) - throw new WebException($"Server at {Uri.Host} responded with unexpected status code: {response.StatusCode}."); + try + { + if (response.StatusCode == HttpStatusCode.OK) + { + if (WritePosition != 0) + throw new WebException( + $"Server at {Uri.Host} ignored the requested byte range. " + + "Cannot resume this download from a full-file response."); - var totalSize = response.Content.Headers.ContentRange?.Length ?? - throw new WebException("The response did not contain a total content length."); + var fileSize = response.Content.Headers.ContentLength ?? + throw new WebException( + "The response did not contain a Content-Length."); - var rangeSize = response.Content.Headers.ContentLength ?? - throw new WebException($"The response did not contain a {nameof(response.Content.Headers.ContentLength)};"); + return new BlockResponse(response, fileSize, fileSize); + } - return new BlockResponse(response, rangeSize, totalSize); - } + if (response.StatusCode != HttpStatusCode.PartialContent) + throw new WebException($"Server at {Uri.Host} responded with unexpected status code: {response.StatusCode}."); - private readonly record struct BlockResponse(HttpResponseMessage Response, long BlockSize, long FileSize) : IDisposable + var totalSize = response.Content.Headers.ContentRange?.Length ?? + throw new WebException("The response did not contain a total content length."); + + var rangeSize = response.Content.Headers.ContentLength ?? + throw new WebException($"The response did not contain a {nameof(response.Content.Headers.ContentLength)};"); + + return new BlockResponse(response, rangeSize, totalSize); + } + catch + { + response.Dispose(); + throw; + } + } + + private readonly record struct BlockResponse(HttpResponseMessage Response, long BlockSize, long FileSize) : IDisposable { public void Dispose() => Response?.Dispose(); }