Skip to content

Commit bf75897

Browse files
committed
WIP: use HttpClient instead of WebClient
1 parent cb1e145 commit bf75897

4 files changed

Lines changed: 168 additions & 86 deletions

File tree

ModApi.UpdateManager/DllsUpdater.cs

Lines changed: 9 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
using System.IO.Compression;
66
using System.Linq;
77
using System.Net;
8+
using System.Net.Http;
9+
using System.Net.Http.Headers;
810
using System.Reflection;
911
using System.Security.AccessControl;
1012
using System.Security.Principal;
@@ -30,18 +32,9 @@ public class GithubRelease
3032

3133
private static string GithubRequestGET(string uri)
3234
{
33-
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
34-
request.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;
35-
request.Method = "GET";
36-
request.Accept = "application/vnd.github.v3+json";
37-
request.UserAgent = UpdateManager.HttpUserAgent;
38-
39-
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
40-
using (Stream stream = response.GetResponseStream())
41-
using (StreamReader reader = new StreamReader(stream))
42-
{
43-
return reader.ReadToEnd();
44-
}
35+
var downloadClient = new DownloadClient(uri);
36+
downloadClient.AddHeader("Accept", "application/vnd.github.v3+json");
37+
return downloadClient.DownloadString();
4538
}
4639

4740
private static GithubRelease GetLatestGithubRelease(string repoUser, string repoName)
@@ -90,11 +83,6 @@ public static bool HasDllsUpdate(out GithubRelease release)
9083

9184
static readonly string[] DLL_NAMES = { "SporeModAPI.combined.dll", "SporeModAPI.disk.dll", "SporeModAPI.march2017.dll", "SporeModAPI.lib" };
9285

93-
public class UpdateProgressEventArgs : EventArgs
94-
{
95-
public float Progress { get; set; }
96-
}
97-
9886
/// <summary>
9987
/// How much of the progress is spent on download (the rest on copying the files)
10088
/// </summary>
@@ -114,17 +102,16 @@ public static void UpdateDlls(GithubRelease release, Action<int> progressHandler
114102
{
115103
throw new InvalidOperationException("Invalid update: no 'SporeModAPIdlls.zip' asset");
116104
}
117-
using (var client = new WebClient())
105+
using (var downloadClient = new DownloadClient(asset.browser_download_url))
118106
{
119-
client.Headers.Add("User-Agent", UpdateManager.HttpUserAgent);
120-
client.DownloadProgressChanged += (s, e) =>
107+
downloadClient.DownloadProgressChanged += (s, progress) =>
121108
{
122109
if (progressHandler != null)
123-
progressHandler((int)(e.ProgressPercentage * DOWNLOAD_PROGRESS));
110+
progressHandler((int)(progress * DOWNLOAD_PROGRESS));
124111
};
125112

126113
string zipName = Path.GetTempFileName();
127-
client.DownloadFile(asset.browser_download_url, zipName);
114+
downloadClient.DownloadFile(zipName);
128115

129116
using (var zip = ZipFile.Open(zipName, ZipArchiveMode.Read))
130117
{
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.IO;
4+
using System.Linq;
5+
using System.Net.Http;
6+
using System.Text;
7+
using System.Threading.Tasks;
8+
using System.Windows.Forms;
9+
10+
namespace ModApi.UpdateManager
11+
{
12+
public class DownloadClient : IDisposable
13+
{
14+
private HttpClient httpClient = new HttpClient();
15+
private HttpRequestMessage httpRequestMessage = new HttpRequestMessage();
16+
private static string httpUserAgent = "Spore-ModAPI-Launcher-Kit/" + UpdateManager.CurrentVersion.ToString();
17+
18+
19+
public delegate void DownloadClientEventHandler(object source, long percentage);
20+
public event DownloadClientEventHandler DownloadProgressChanged;
21+
22+
public DownloadClient(string url)
23+
{
24+
httpClient.Timeout = TimeSpan.FromMinutes(5);
25+
httpRequestMessage.RequestUri = new Uri(url);
26+
httpRequestMessage.Headers.Add("User-Agent", httpUserAgent);
27+
}
28+
29+
public void SetTimeout(TimeSpan timeout)
30+
{
31+
httpClient.Timeout = timeout;
32+
}
33+
34+
public void AddHeader(string key, string value)
35+
{
36+
httpRequestMessage.Headers.Add(key, value);
37+
}
38+
39+
public string DownloadString()
40+
{
41+
var response = httpClient.SendAsync(httpRequestMessage).Result;
42+
43+
if (!response.IsSuccessStatusCode)
44+
{
45+
throw new HttpRequestException($"Received unsuccessful status code: {(int)response.StatusCode} {response.StatusCode}");
46+
}
47+
48+
return response.Content.ReadAsStringAsync().Result;
49+
}
50+
51+
public void DownloadFile(string file)
52+
{
53+
var response = httpClient.SendAsync(httpRequestMessage).Result;
54+
55+
if (!response.IsSuccessStatusCode)
56+
{
57+
throw new HttpRequestException($"Received unsuccessful status code: {(int)response.StatusCode} {response.StatusCode}");
58+
}
59+
60+
using (var downloadStream = response.Content.ReadAsStreamAsync().Result)
61+
using (var fileStream = new FileStream(file, FileMode.Create))
62+
{
63+
long streamLength = downloadStream.Length;
64+
long totalBytesRead = 0;
65+
byte[] buffer = new byte[1024];
66+
int bufferLength = 0;
67+
int percentageDownloaded = 0;
68+
int percentage = 0;
69+
70+
while ((bufferLength = downloadStream.Read(buffer, 0, buffer.Length)) > 0)
71+
{
72+
fileStream.Write(buffer, 0, bufferLength);
73+
74+
// only trigger event when percentage has changed
75+
percentage = (int)(totalBytesRead / streamLength * 100);
76+
if (percentageDownloaded != percentage)
77+
{
78+
percentageDownloaded = percentage;
79+
DownloadProgressChanged?.Invoke(this, percentage);
80+
}
81+
82+
totalBytesRead += bufferLength;
83+
}
84+
}
85+
}
86+
87+
public void Dispose()
88+
{
89+
Dispose(true);
90+
GC.SuppressFinalize(this);
91+
}
92+
93+
protected virtual void Dispose(bool disposing)
94+
{
95+
if (disposing)
96+
{
97+
httpClient.Dispose();
98+
httpRequestMessage.Dispose();
99+
100+
httpClient = null;
101+
httpRequestMessage = null;
102+
}
103+
}
104+
}
105+
}

ModApi.UpdateManager/ModApi.UpdateManager.csproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
<Reference Include="System.Drawing" />
5050
<Reference Include="System.IO.Compression" />
5151
<Reference Include="System.IO.Compression.FileSystem" />
52+
<Reference Include="System.Net.Http" />
5253
<Reference Include="System.Windows.Forms" />
5354
<Reference Include="System.Xml.Linq" />
5455
<Reference Include="System.Data.DataSetExtensions" />
@@ -58,6 +59,7 @@
5859
</ItemGroup>
5960
<ItemGroup>
6061
<Compile Include="DllsUpdater.cs" />
62+
<Compile Include="DownloadClient.cs" />
6163
<Compile Include="ProgressDialog.cs">
6264
<SubType>Form</SubType>
6365
</Compile>

ModApi.UpdateManager/UpdateManager.cs

Lines changed: 52 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -136,73 +136,79 @@ public static void CheckForUpdates()
136136
}
137137
}
138138

139-
if (!File.Exists(UpdaterBlockPath) && HasInternetConnection())
139+
if (!File.Exists(UpdaterBlockPath))
140140
{
141141
try
142142
{
143-
using (var infoClient = new WebClient())
143+
List<Exception> exceptions = new List<Exception>();
144+
bool didDownload = false;
145+
146+
// Try to download the update info file from the override path first
147+
if (File.Exists(UpdaterOverridePath))
144148
{
145-
infoClient.Headers.Add("User-Agent", HttpUserAgent);
149+
PathPrefix = File.ReadAllText(UpdaterOverridePath);
146150

147-
List<Exception> exceptions = new List<Exception>();
148-
bool didDownload = false;
149-
150-
// Try to download the update info file from the override path first
151-
if (File.Exists(UpdaterOverridePath))
151+
// remove override if the URL is in our URL list
152+
foreach (string url in LauncherKitUpdateUrls)
152153
{
153-
PathPrefix = File.ReadAllText(UpdaterOverridePath);
154+
if (url == PathPrefix)
155+
{
156+
File.Delete(UpdaterOverridePath);
157+
break;
158+
}
159+
}
154160

155-
// remove override if the URL is in our URL list
156-
foreach (string url in LauncherKitUpdateUrls)
161+
try
162+
{
163+
using (var downloadClient = new DownloadClient(Path.Combine(PathPrefix, "update.info")))
157164
{
158-
if (url == PathPrefix)
159-
{
160-
File.Delete(UpdaterOverridePath);
161-
break;
162-
}
165+
downloadClient.SetTimeout(TimeSpan.FromSeconds(5));
166+
downloadClient.DownloadFile(UpdateInfoDestPath);
163167
}
164168

169+
// Hides exceptions if the download was successful
170+
didDownload = true;
171+
}
172+
catch (Exception ex)
173+
{
174+
exceptions.Add(ex);
175+
}
176+
}
177+
// Try to download the update info file from each URL in the list
178+
else
179+
{
180+
foreach (string url in LauncherKitUpdateUrls)
181+
{
165182
try
166183
{
167-
infoClient.DownloadFile(Path.Combine(PathPrefix, "update.info"), UpdateInfoDestPath);
184+
using (var downloadClient = new DownloadClient(Path.Combine(PathPrefix, "update.info")))
185+
{
186+
downloadClient.SetTimeout(TimeSpan.FromSeconds(5));
187+
downloadClient.DownloadFile(UpdateInfoDestPath);
188+
}
168189

169190
// Hides exceptions if the download was successful
170191
didDownload = true;
192+
PathPrefix = url;
193+
break;
171194
}
172195
catch (Exception ex)
173196
{
174197
exceptions.Add(ex);
175198
}
176199
}
177-
// Try to download the update info file from each URL in the list
178-
else
179-
{
180-
foreach (string url in LauncherKitUpdateUrls)
181-
{
182-
try
183-
{
184-
infoClient.DownloadFile(Path.Combine(url, "update.info"), UpdateInfoDestPath);
185-
186-
// Hides exceptions if the download was successful
187-
didDownload = true;
188-
PathPrefix = url;
189-
break;
190-
}
191-
catch (Exception ex)
192-
{
193-
exceptions.Add(ex);
194-
}
195-
}
196-
}
200+
}
197201

198-
// If no download was successful, show all exceptions, one at a time
199-
if (!didDownload)
202+
// If no download was successful, show all exceptions, one at a time
203+
if (!didDownload)
204+
{
205+
foreach (var ex in exceptions)
200206
{
201-
foreach (var ex in exceptions)
202-
{
203-
ShowUpdateCheckFailedMessage(ex);
204-
}
207+
ShowUpdateCheckFailedMessage(ex);
205208
}
209+
210+
// early return when failed
211+
return;
206212
}
207213

208214
if (File.Exists(UpdateInfoDestPath))
@@ -223,13 +229,13 @@ public static void CheckForUpdates()
223229
}
224230
else
225231
{
226-
var installerClient = new WebClient();
227-
installerClient.Headers.Add("User-Agent", HttpUserAgent);
228232

229233
if (File.Exists(UpdaterDestPath))
230234
File.Delete(UpdaterDestPath);
231235

232-
installerClient.DownloadFile(updateInfoLines[3], UpdaterDestPath);
236+
var downloadClient = new DownloadClient(updateInfoLines[3]);
237+
downloadClient.SetTimeout(TimeSpan.FromMinutes(5));
238+
downloadClient.DownloadFile(UpdaterDestPath);
233239

234240
if (File.Exists(UpdaterDestPath))
235241
{
@@ -303,23 +309,5 @@ static void ShowUnrecognizedUpdateInfoVersionMessage()
303309
{
304310
MessageBox.Show("This update to the Spore ModAPI Launcher Kit must be downloaded manually.");
305311
}
306-
307-
static bool HasInternetConnection()
308-
{
309-
try
310-
{
311-
using (var client = new WebClient())
312-
{
313-
client.Headers.Add("User-Agent", HttpUserAgent);
314-
client.DownloadString("https://1.1.1.1");
315-
return true;
316-
}
317-
}
318-
catch (Exception ex)
319-
{
320-
MessageBox.Show("The Launcher Kit could not connect to the internet to check for updates. The Launcher Kit will still work, but you may be missing the latest features and improvements.\n\nCurrent version: " + CurrentVersion + "\n\n" + ex.ToString());
321-
return false;
322-
}
323-
}
324312
}
325313
}

0 commit comments

Comments
 (0)