mirror of
https://github.com/bloxstraplabs/bloxstrap.git
synced 2025-04-21 10:01:27 -07:00
HttpClient - Use singleton and enable gzip
Rework of #45 as it kept crashing on release
This commit is contained in:
parent
a39ce6bf81
commit
170c6e5884
@ -10,6 +10,7 @@ using Bloxstrap.Dialogs.BootstrapperDialogs;
|
||||
using Bloxstrap.Helpers;
|
||||
using Bloxstrap.Helpers.Integrations;
|
||||
using Bloxstrap.Helpers.RSMM;
|
||||
using System.Net;
|
||||
|
||||
namespace Bloxstrap
|
||||
{
|
||||
@ -66,8 +67,6 @@ namespace Bloxstrap
|
||||
"By default, two mod presets are provided for restoring the old death\n" +
|
||||
"sound and the old mouse cursor.\n";
|
||||
|
||||
private static readonly HttpClient Client = new();
|
||||
|
||||
private string? LaunchCommandLine;
|
||||
|
||||
private string VersionGuid = null!;
|
||||
@ -87,7 +86,6 @@ namespace Bloxstrap
|
||||
{
|
||||
LaunchCommandLine = launchCommandLine;
|
||||
FreshInstall = String.IsNullOrEmpty(Program.Settings.VersionGuid);
|
||||
Client.Timeout = TimeSpan.FromMinutes(10);
|
||||
}
|
||||
|
||||
// this is called from BootstrapperStyleForm.SetupDialog()
|
||||
@ -133,7 +131,7 @@ namespace Bloxstrap
|
||||
{
|
||||
Dialog.Message = "Connecting to Roblox...";
|
||||
|
||||
VersionGuid = await Client.GetStringAsync($"{DeployManager.BaseUrl}/version");
|
||||
VersionGuid = await Program.HttpClient.GetStringAsync($"{DeployManager.BaseUrl}/version");
|
||||
VersionFolder = Path.Combine(Directories.Versions, VersionGuid);
|
||||
VersionPackageManifest = await PackageManifest.Get(VersionGuid);
|
||||
}
|
||||
@ -611,7 +609,7 @@ namespace Bloxstrap
|
||||
{
|
||||
Debug.WriteLine($"Downloading {package.Name}...");
|
||||
|
||||
var response = await Client.GetAsync(packageUrl);
|
||||
var response = await Program.HttpClient.GetAsync(packageUrl);
|
||||
|
||||
if (CancelFired)
|
||||
return;
|
||||
|
@ -34,7 +34,7 @@
|
||||
<GroupBox Grid.Column="0" Header="Discord Rich Presence" Margin="10,10,5,5">
|
||||
<StackPanel VerticalAlignment="Center">
|
||||
<CheckBox x:Name="CheckBoxDRPEnabled" Content=" Show game activity" Margin="5" VerticalAlignment="Top" IsChecked="{Binding DRPEnabled, Mode=TwoWay}" />
|
||||
<CheckBox x:Name="CheckBoxDRPButtons" Content=" Allow others to join" Margin="5" VerticalAlignment="Top" IsEnabled="{Binding IsChecked, ElementName=CheckBoxDRPEnabled, Mode=OneWay}" IsChecked="{Binding DRPButtons, Mode=TwoWay}" />
|
||||
<CheckBox x:Name="CheckBoxDRPButtons" Content=" Allow people to join" Margin="5" VerticalAlignment="Top" IsEnabled="{Binding IsChecked, ElementName=CheckBoxDRPEnabled, Mode=OneWay}" IsChecked="{Binding DRPButtons, Mode=TwoWay}" />
|
||||
</StackPanel>
|
||||
</GroupBox>
|
||||
<GroupBox Grid.Column="1" Header="FPS Unlocking" Margin="5,10,10,5">
|
||||
|
@ -104,9 +104,7 @@ namespace Bloxstrap.Helpers
|
||||
string baseUrl = BuildBaseUrl(channel);
|
||||
string lastDeploy = "";
|
||||
|
||||
using (HttpClient client = new())
|
||||
{
|
||||
string deployHistory = await client.GetStringAsync($"{baseUrl}/DeployHistory.txt");
|
||||
string deployHistory = await Program.HttpClient.GetStringAsync($"{baseUrl}/DeployHistory.txt");
|
||||
|
||||
using (StringReader reader = new(deployHistory))
|
||||
{
|
||||
@ -118,7 +116,6 @@ namespace Bloxstrap.Helpers
|
||||
lastDeploy = line;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (String.IsNullOrEmpty(lastDeploy))
|
||||
throw new Exception($"Could not get latest deploy for channel {channel}");
|
||||
|
@ -91,16 +91,13 @@ namespace Bloxstrap.Helpers.Integrations
|
||||
|
||||
Debug.WriteLine("Installing/Updating rbxfpsunlocker...");
|
||||
|
||||
using (HttpClient client = new())
|
||||
{
|
||||
byte[] bytes = await client.GetByteArrayAsync(downloadUrl);
|
||||
byte[] bytes = await Program.HttpClient.GetByteArrayAsync(downloadUrl);
|
||||
|
||||
using (MemoryStream zipStream = new(bytes))
|
||||
{
|
||||
ZipArchive zip = new(zipStream);
|
||||
zip.ExtractToDirectory(folderLocation, true);
|
||||
}
|
||||
}
|
||||
|
||||
if (!File.Exists(settingsLocation))
|
||||
{
|
||||
|
@ -75,11 +75,8 @@ namespace Bloxstrap.Helpers.RSMM
|
||||
string pkgManifestUrl = $"{DeployManager.BaseUrl}/{versionGuid}-rbxPkgManifest.txt";
|
||||
string pkgManifestData;
|
||||
|
||||
using (HttpClient http = new())
|
||||
{
|
||||
var getData = http.GetStringAsync(pkgManifestUrl);
|
||||
var getData = Program.HttpClient.GetStringAsync(pkgManifestUrl);
|
||||
pkgManifestData = await getData.ConfigureAwait(false);
|
||||
}
|
||||
|
||||
return new PackageManifest(pkgManifestData);
|
||||
}
|
||||
|
@ -1,288 +0,0 @@
|
||||
using System.Collections;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
|
||||
// taken from MiscUtil: https://github.com/loory/MiscUtil
|
||||
// the proper usage of MiscUtil nowadays is to *not* use the library and rather copy the code you need so lol
|
||||
|
||||
namespace Bloxstrap.Helpers
|
||||
{
|
||||
/// <summary>
|
||||
/// Takes an encoding (defaulting to UTF-8) and a function which produces a seekable stream
|
||||
/// (or a filename for convenience) and yields lines from the end of the stream backwards.
|
||||
/// Only single byte encodings, and UTF-8 and Unicode, are supported. The stream
|
||||
/// returned by the function must be seekable.
|
||||
/// </summary>
|
||||
public sealed class ReverseLineReader : IEnumerable<string>
|
||||
{
|
||||
/// <summary>
|
||||
/// Buffer size to use by default. Classes with internal access can specify
|
||||
/// a different buffer size - this is useful for testing.
|
||||
/// </summary>
|
||||
private const int DefaultBufferSize = 4096;
|
||||
|
||||
/// <summary>
|
||||
/// Means of creating a Stream to read from.
|
||||
/// </summary>
|
||||
private readonly Func<Stream> streamSource;
|
||||
|
||||
/// <summary>
|
||||
/// Encoding to use when converting bytes to text
|
||||
/// </summary>
|
||||
private readonly Encoding encoding;
|
||||
|
||||
/// <summary>
|
||||
/// Size of buffer (in bytes) to read each time we read from the
|
||||
/// stream. This must be at least as big as the maximum number of
|
||||
/// bytes for a single character.
|
||||
/// </summary>
|
||||
private readonly int bufferSize;
|
||||
|
||||
/// <summary>
|
||||
/// Function which, when given a position within a file and a byte, states whether
|
||||
/// or not the byte represents the start of a character.
|
||||
/// </summary>
|
||||
private Func<long, byte, bool> characterStartDetector;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a LineReader from a stream source. The delegate is only
|
||||
/// called when the enumerator is fetched. UTF-8 is used to decode
|
||||
/// the stream into text.
|
||||
/// </summary>
|
||||
/// <param name="streamSource">Data source</param>
|
||||
public ReverseLineReader(Func<Stream> streamSource)
|
||||
: this(streamSource, Encoding.UTF8)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a LineReader from a filename. The file is only opened
|
||||
/// (or even checked for existence) when the enumerator is fetched.
|
||||
/// UTF8 is used to decode the file into text.
|
||||
/// </summary>
|
||||
/// <param name="filename">File to read from</param>
|
||||
public ReverseLineReader(string filename)
|
||||
: this(filename, Encoding.UTF8)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a LineReader from a filename. The file is only opened
|
||||
/// (or even checked for existence) when the enumerator is fetched.
|
||||
/// </summary>
|
||||
/// <param name="filename">File to read from</param>
|
||||
/// <param name="encoding">Encoding to use to decode the file into text</param>
|
||||
public ReverseLineReader(string filename, Encoding encoding)
|
||||
: this(() => File.OpenRead(filename), encoding)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a LineReader from a stream source. The delegate is only
|
||||
/// called when the enumerator is fetched.
|
||||
/// </summary>
|
||||
/// <param name="streamSource">Data source</param>
|
||||
/// <param name="encoding">Encoding to use to decode the stream into text</param>
|
||||
public ReverseLineReader(Func<Stream> streamSource, Encoding encoding)
|
||||
: this(streamSource, encoding, DefaultBufferSize)
|
||||
{
|
||||
}
|
||||
|
||||
internal ReverseLineReader(Func<Stream> streamSource, Encoding encoding, int bufferSize)
|
||||
{
|
||||
this.streamSource = streamSource;
|
||||
this.encoding = encoding;
|
||||
this.bufferSize = bufferSize;
|
||||
if (encoding.IsSingleByte)
|
||||
{
|
||||
// For a single byte encoding, every byte is the start (and end) of a character
|
||||
characterStartDetector = (pos, data) => true;
|
||||
}
|
||||
else if (encoding is UnicodeEncoding)
|
||||
{
|
||||
// For UTF-16, even-numbered positions are the start of a character.
|
||||
// TODO: This assumes no surrogate pairs. More work required
|
||||
// to handle that.
|
||||
characterStartDetector = (pos, data) => (pos & 1) == 0;
|
||||
}
|
||||
else if (encoding is UTF8Encoding)
|
||||
{
|
||||
// For UTF-8, bytes with the top bit clear or the second bit set are the start of a character
|
||||
// See http://www.cl.cam.ac.uk/~mgk25/unicode.html
|
||||
characterStartDetector = (pos, data) => (data & 0x80) == 0 || (data & 0x40) != 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ArgumentException("Only single byte, UTF-8 and Unicode encodings are permitted");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the enumerator reading strings backwards. If this method discovers that
|
||||
/// the returned stream is either unreadable or unseekable, a NotSupportedException is thrown.
|
||||
/// </summary>
|
||||
public IEnumerator<string> GetEnumerator()
|
||||
{
|
||||
Stream stream = streamSource();
|
||||
if (!stream.CanSeek)
|
||||
{
|
||||
stream.Dispose();
|
||||
throw new NotSupportedException("Unable to seek within stream");
|
||||
}
|
||||
if (!stream.CanRead)
|
||||
{
|
||||
stream.Dispose();
|
||||
throw new NotSupportedException("Unable to read within stream");
|
||||
}
|
||||
return GetEnumeratorImpl(stream);
|
||||
}
|
||||
|
||||
private IEnumerator<string> GetEnumeratorImpl(Stream stream)
|
||||
{
|
||||
try
|
||||
{
|
||||
long position = stream.Length;
|
||||
|
||||
if (encoding is UnicodeEncoding && (position & 1) != 0)
|
||||
{
|
||||
throw new InvalidDataException("UTF-16 encoding provided, but stream has odd length.");
|
||||
}
|
||||
|
||||
// Allow up to two bytes for data from the start of the previous
|
||||
// read which didn't quite make it as full characters
|
||||
byte[] buffer = new byte[bufferSize + 2];
|
||||
char[] charBuffer = new char[encoding.GetMaxCharCount(buffer.Length)];
|
||||
int leftOverData = 0;
|
||||
String? previousEnd = null;
|
||||
// TextReader doesn't return an empty string if there's line break at the end
|
||||
// of the data. Therefore we don't return an empty string if it's our *first*
|
||||
// return.
|
||||
bool firstYield = true;
|
||||
|
||||
// A line-feed at the start of the previous buffer means we need to swallow
|
||||
// the carriage-return at the end of this buffer - hence this needs declaring
|
||||
// way up here!
|
||||
bool swallowCarriageReturn = false;
|
||||
|
||||
while (position > 0)
|
||||
{
|
||||
int bytesToRead = Math.Min(position > int.MaxValue ? bufferSize : (int)position, bufferSize);
|
||||
|
||||
position -= bytesToRead;
|
||||
stream.Position = position;
|
||||
StreamUtil.ReadExactly(stream, buffer, bytesToRead);
|
||||
// If we haven't read a full buffer, but we had bytes left
|
||||
// over from before, copy them to the end of the buffer
|
||||
if (leftOverData > 0 && bytesToRead != bufferSize)
|
||||
{
|
||||
// Buffer.BlockCopy doesn't document its behaviour with respect
|
||||
// to overlapping data: we *might* just have read 7 bytes instead of
|
||||
// 8, and have two bytes to copy...
|
||||
Array.Copy(buffer, bufferSize, buffer, bytesToRead, leftOverData);
|
||||
}
|
||||
// We've now *effectively* read this much data.
|
||||
bytesToRead += leftOverData;
|
||||
|
||||
int firstCharPosition = 0;
|
||||
while (!characterStartDetector(position + firstCharPosition, buffer[firstCharPosition]))
|
||||
{
|
||||
firstCharPosition++;
|
||||
// Bad UTF-8 sequences could trigger this. For UTF-8 we should always
|
||||
// see a valid character start in every 3 bytes, and if this is the start of the file
|
||||
// so we've done a short read, we should have the character start
|
||||
// somewhere in the usable buffer.
|
||||
if (firstCharPosition == 3 || firstCharPosition == bytesToRead)
|
||||
{
|
||||
throw new InvalidDataException("Invalid UTF-8 data");
|
||||
}
|
||||
}
|
||||
leftOverData = firstCharPosition;
|
||||
|
||||
int charsRead = encoding.GetChars(buffer, firstCharPosition, bytesToRead - firstCharPosition, charBuffer, 0);
|
||||
int endExclusive = charsRead;
|
||||
|
||||
for (int i = charsRead - 1; i >= 0; i--)
|
||||
{
|
||||
char lookingAt = charBuffer[i];
|
||||
if (swallowCarriageReturn)
|
||||
{
|
||||
swallowCarriageReturn = false;
|
||||
if (lookingAt == '\r')
|
||||
{
|
||||
endExclusive--;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
// Anything non-line-breaking, just keep looking backwards
|
||||
if (lookingAt != '\n' && lookingAt != '\r')
|
||||
{
|
||||
continue;
|
||||
}
|
||||
// End of CRLF? Swallow the preceding CR
|
||||
if (lookingAt == '\n')
|
||||
{
|
||||
swallowCarriageReturn = true;
|
||||
}
|
||||
int start = i + 1;
|
||||
string bufferContents = new string(charBuffer, start, endExclusive - start);
|
||||
endExclusive = i;
|
||||
string stringToYield = previousEnd == null ? bufferContents : bufferContents + previousEnd;
|
||||
if (!firstYield || stringToYield.Length != 0)
|
||||
{
|
||||
yield return stringToYield;
|
||||
}
|
||||
firstYield = false;
|
||||
previousEnd = null;
|
||||
}
|
||||
|
||||
previousEnd = endExclusive == 0 ? null : (new string(charBuffer, 0, endExclusive) + previousEnd);
|
||||
|
||||
// If we didn't decode the start of the array, put it at the end for next time
|
||||
if (leftOverData != 0)
|
||||
{
|
||||
Buffer.BlockCopy(buffer, 0, buffer, bufferSize, leftOverData);
|
||||
}
|
||||
}
|
||||
if (leftOverData != 0)
|
||||
{
|
||||
// At the start of the final buffer, we had the end of another character.
|
||||
throw new InvalidDataException("Invalid UTF-8 data at start of stream");
|
||||
}
|
||||
if (firstYield && string.IsNullOrEmpty(previousEnd))
|
||||
{
|
||||
yield break;
|
||||
}
|
||||
yield return previousEnd ?? "";
|
||||
}
|
||||
finally
|
||||
{
|
||||
stream.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return GetEnumerator();
|
||||
}
|
||||
}
|
||||
|
||||
public static class StreamUtil
|
||||
{
|
||||
public static void ReadExactly(Stream input, byte[] buffer, int bytesToRead)
|
||||
{
|
||||
int index = 0;
|
||||
while (index < bytesToRead)
|
||||
{
|
||||
int read = input.Read(buffer, index, bytesToRead - index);
|
||||
if (read == 0)
|
||||
{
|
||||
throw new EndOfStreamException
|
||||
(String.Format("End of stream reached with {0} byte{1} left to read.",
|
||||
bytesToRead - index,
|
||||
bytesToRead - index == 1 ? "s" : ""));
|
||||
}
|
||||
index += read;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -42,7 +42,7 @@ namespace Bloxstrap.Helpers
|
||||
|
||||
new Preferences().ShowDialog();
|
||||
|
||||
Environment.Exit(0);
|
||||
Program.Exit();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -15,14 +15,9 @@ namespace Bloxstrap.Helpers
|
||||
|
||||
public static async Task<T?> GetJson<T>(string url)
|
||||
{
|
||||
using (HttpClient client = new())
|
||||
{
|
||||
client.DefaultRequestHeaders.Add("User-Agent", Program.ProjectRepository);
|
||||
|
||||
string json = await client.GetStringAsync(url);
|
||||
string json = await Program.HttpClient.GetStringAsync(url);
|
||||
return JsonSerializer.Deserialize<T>(json);
|
||||
}
|
||||
}
|
||||
|
||||
public static string MD5File(string filename)
|
||||
{
|
||||
|
@ -8,6 +8,8 @@ using Bloxstrap.Enums;
|
||||
using Bloxstrap.Helpers;
|
||||
using Bloxstrap.Models;
|
||||
using Bloxstrap.Dialogs;
|
||||
using System.Net.Http;
|
||||
using System.Net;
|
||||
|
||||
namespace Bloxstrap
|
||||
{
|
||||
@ -34,6 +36,7 @@ namespace Bloxstrap
|
||||
|
||||
public static SettingsManager SettingsManager = new();
|
||||
public static SettingsFormat Settings = SettingsManager.Settings;
|
||||
public static readonly HttpClient HttpClient = new(new HttpClientHandler { AutomaticDecompression = DecompressionMethods.All });
|
||||
|
||||
// shorthand
|
||||
public static DialogResult ShowMessageBox(string message, MessageBoxIcon icon = MessageBoxIcon.None, MessageBoxButtons buttons = MessageBoxButtons.OK)
|
||||
@ -57,6 +60,9 @@ namespace Bloxstrap
|
||||
// see https://aka.ms/applicationconfiguration.
|
||||
ApplicationConfiguration.Initialize();
|
||||
|
||||
HttpClient.Timeout = TimeSpan.FromMinutes(5);
|
||||
HttpClient.DefaultRequestHeaders.Add("User-Agent", ProjectRepository);
|
||||
|
||||
LocalAppData = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
|
||||
StartMenu = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.StartMenu), "Programs", ProjectName);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user