Skip to content

Commit 58d281d

Browse files
authored
Merge pull request #178 from taooceros/UpdateHttpMaster
Move Old HttpWebRequest to HttpClient Instance
2 parents a47f8b3 + c485578 commit 58d281d

File tree

8 files changed

+196
-84
lines changed

8 files changed

+196
-84
lines changed

Flow.Launcher.Core/Updater.cs

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
using System.Windows;
99
using JetBrains.Annotations;
1010
using Squirrel;
11-
using Newtonsoft.Json;
1211
using Flow.Launcher.Core.Resource;
1312
using Flow.Launcher.Plugin.SharedCommands;
1413
using Flow.Launcher.Infrastructure;
@@ -17,6 +16,7 @@
1716
using System.IO;
1817
using Flow.Launcher.Infrastructure.UserSettings;
1918
using Flow.Launcher.Plugin;
19+
using System.Text.Json.Serialization;
2020

2121
namespace Flow.Launcher.Core
2222
{
@@ -29,7 +29,7 @@ public Updater(string gitHubRepository)
2929
GitHubRepository = gitHubRepository;
3030
}
3131

32-
public async Task UpdateApp(IPublicAPI api , bool silentUpdate = true)
32+
public async Task UpdateApp(IPublicAPI api, bool silentUpdate = true)
3333
{
3434
UpdateManager updateManager;
3535
UpdateInfo newUpdateInfo;
@@ -39,7 +39,7 @@ public async Task UpdateApp(IPublicAPI api , bool silentUpdate = true)
3939

4040
try
4141
{
42-
updateManager = await GitHubUpdateManager(GitHubRepository);
42+
updateManager = await GitHubUpdateManager(GitHubRepository).ConfigureAwait(false);
4343
}
4444
catch (Exception e) when (e is HttpRequestException || e is WebException || e is SocketException)
4545
{
@@ -50,7 +50,7 @@ public async Task UpdateApp(IPublicAPI api , bool silentUpdate = true)
5050
try
5151
{
5252
// UpdateApp CheckForUpdate will return value only if the app is squirrel installed
53-
newUpdateInfo = await updateManager.CheckForUpdate().NonNull();
53+
newUpdateInfo = await updateManager.CheckForUpdate().NonNull().ConfigureAwait(false);
5454
}
5555
catch (Exception e) when (e is HttpRequestException || e is WebException || e is SocketException)
5656
{
@@ -85,8 +85,8 @@ public async Task UpdateApp(IPublicAPI api , bool silentUpdate = true)
8585
updateManager.Dispose();
8686
return;
8787
}
88-
89-
await updateManager.ApplyReleases(newUpdateInfo);
88+
89+
await updateManager.ApplyReleases(newUpdateInfo).ConfigureAwait(false);
9090

9191
if (DataLocation.PortableDataLocationInUse())
9292
{
@@ -98,11 +98,11 @@ public async Task UpdateApp(IPublicAPI api , bool silentUpdate = true)
9898
}
9999
else
100100
{
101-
await updateManager.CreateUninstallerRegistryEntry();
101+
await updateManager.CreateUninstallerRegistryEntry().ConfigureAwait(false);
102102
}
103103

104104
var newVersionTips = NewVersinoTips(newReleaseVersion.ToString());
105-
105+
106106
Log.Info($"|Updater.UpdateApp|Update success:{newVersionTips}");
107107

108108
// always dispose UpdateManager
@@ -117,13 +117,13 @@ public async Task UpdateApp(IPublicAPI api , bool silentUpdate = true)
117117
[UsedImplicitly]
118118
private class GithubRelease
119119
{
120-
[JsonProperty("prerelease")]
120+
[JsonPropertyName("prerelease")]
121121
public bool Prerelease { get; [UsedImplicitly] set; }
122122

123-
[JsonProperty("published_at")]
123+
[JsonPropertyName("published_at")]
124124
public DateTime PublishedAt { get; [UsedImplicitly] set; }
125125

126-
[JsonProperty("html_url")]
126+
[JsonPropertyName("html_url")]
127127
public string HtmlUrl { get; [UsedImplicitly] set; }
128128
}
129129

@@ -133,13 +133,13 @@ private async Task<UpdateManager> GitHubUpdateManager(string repository)
133133
var uri = new Uri(repository);
134134
var api = $"https://api.github.com/repos{uri.AbsolutePath}/releases";
135135

136-
var json = await Http.Get(api);
136+
var jsonStream = await Http.GetStreamAsync(api).ConfigureAwait(false);
137137

138-
var releases = JsonConvert.DeserializeObject<List<GithubRelease>>(json);
138+
var releases = await System.Text.Json.JsonSerializer.DeserializeAsync<List<GithubRelease>>(jsonStream).ConfigureAwait(false);
139139
var latest = releases.Where(r => !r.Prerelease).OrderByDescending(r => r.PublishedAt).First();
140140
var latestUrl = latest.HtmlUrl.Replace("/tag/", "/download/");
141141

142-
var client = new WebClient { Proxy = Http.WebProxy() };
142+
var client = new WebClient { Proxy = Http.WebProxy };
143143
var downloader = new FileDownloader(client);
144144

145145
var manager = new UpdateManager(latestUrl, urlDownloader: downloader);

Flow.Launcher.Infrastructure/Http/Http.cs

Lines changed: 85 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -6,85 +6,127 @@
66
using JetBrains.Annotations;
77
using Flow.Launcher.Infrastructure.Logger;
88
using Flow.Launcher.Infrastructure.UserSettings;
9+
using System;
10+
using System.ComponentModel;
911

1012
namespace Flow.Launcher.Infrastructure.Http
1113
{
1214
public static class Http
1315
{
1416
private const string UserAgent = @"Mozilla/5.0 (Trident/7.0; rv:11.0) like Gecko";
1517

18+
private static HttpClient client;
19+
20+
private static SocketsHttpHandler socketsHttpHandler = new SocketsHttpHandler()
21+
{
22+
UseProxy = true,
23+
Proxy = WebProxy
24+
};
25+
1626
static Http()
1727
{
1828
// need to be added so it would work on a win10 machine
1929
ServicePointManager.Expect100Continue = true;
2030
ServicePointManager.SecurityProtocol |= SecurityProtocolType.Tls
2131
| SecurityProtocolType.Tls11
2232
| SecurityProtocolType.Tls12;
33+
34+
client = new HttpClient(socketsHttpHandler, false);
35+
client.DefaultRequestHeaders.Add("User-Agent", UserAgent);
2336
}
2437

25-
public static HttpProxy Proxy { private get; set; }
26-
public static IWebProxy WebProxy()
38+
private static HttpProxy proxy;
39+
40+
public static HttpProxy Proxy
2741
{
28-
if (Proxy != null && Proxy.Enabled && !string.IsNullOrEmpty(Proxy.Server))
42+
private get { return proxy; }
43+
set
2944
{
30-
if (string.IsNullOrEmpty(Proxy.UserName) || string.IsNullOrEmpty(Proxy.Password))
31-
{
32-
var webProxy = new WebProxy(Proxy.Server, Proxy.Port);
33-
return webProxy;
34-
}
35-
else
45+
proxy = value;
46+
proxy.PropertyChanged += UpdateProxy;
47+
}
48+
}
49+
50+
public static WebProxy WebProxy { get; } = new WebProxy();
51+
52+
/// <summary>
53+
/// Update the Address of the Proxy to modify the client Proxy
54+
/// </summary>
55+
public static void UpdateProxy(ProxyProperty property)
56+
{
57+
(WebProxy.Address, WebProxy.Credentials) = property switch
58+
{
59+
ProxyProperty.Enabled => Proxy.Enabled switch
3660
{
37-
var webProxy = new WebProxy(Proxy.Server, Proxy.Port)
61+
true => Proxy.UserName switch
3862
{
39-
Credentials = new NetworkCredential(Proxy.UserName, Proxy.Password)
40-
};
41-
return webProxy;
42-
}
63+
var userName when !string.IsNullOrEmpty(userName) =>
64+
(new Uri($"http://{Proxy.Server}:{Proxy.Port}"), null),
65+
_ => (new Uri($"http://{Proxy.Server}:{Proxy.Port}"),
66+
new NetworkCredential(Proxy.UserName, Proxy.Password))
67+
},
68+
false => (null, null)
69+
},
70+
ProxyProperty.Server => (new Uri($"http://{Proxy.Server}:{Proxy.Port}"), WebProxy.Credentials),
71+
ProxyProperty.Port => (new Uri($"http://{Proxy.Server}:{Proxy.Port}"), WebProxy.Credentials),
72+
ProxyProperty.UserName => (WebProxy.Address, new NetworkCredential(Proxy.UserName, Proxy.Password)),
73+
ProxyProperty.Password => (WebProxy.Address, new NetworkCredential(Proxy.UserName, Proxy.Password)),
74+
_ => throw new ArgumentOutOfRangeException()
75+
};
76+
}
77+
78+
public static async Task Download([NotNull] string url, [NotNull] string filePath)
79+
{
80+
using var response = await client.GetAsync(url);
81+
if (response.StatusCode == HttpStatusCode.OK)
82+
{
83+
await using var fileStream = new FileStream(filePath, FileMode.CreateNew);
84+
await response.Content.CopyToAsync(fileStream);
4385
}
4486
else
4587
{
46-
return WebRequest.GetSystemWebProxy();
88+
throw new HttpRequestException($"Error code <{response.StatusCode}> returned from <{url}>");
4789
}
4890
}
4991

50-
public static void Download([NotNull] string url, [NotNull] string filePath)
92+
/// <summary>
93+
/// Asynchrously get the result as string from url.
94+
/// When supposing the result is long and large, try using GetStreamAsync to avoid reading as string
95+
/// </summary>
96+
/// <param name="url"></param>
97+
/// <returns></returns>
98+
public static Task<string> GetAsync([NotNull] string url)
5199
{
52-
var client = new WebClient { Proxy = WebProxy() };
53-
client.Headers.Add("user-agent", UserAgent);
54-
client.DownloadFile(url, filePath);
100+
Log.Debug($"|Http.Get|Url <{url}>");
101+
return GetAsync(new Uri(url.Replace("#", "%23")));
55102
}
56103

57-
public static async Task<string> Get([NotNull] string url, string encoding = "UTF-8")
104+
public static async Task<string> GetAsync([NotNull] Uri url)
58105
{
59106
Log.Debug($"|Http.Get|Url <{url}>");
60-
var request = WebRequest.CreateHttp(url);
61-
request.Method = "GET";
62-
request.Timeout = 6000;
63-
request.Proxy = WebProxy();
64-
request.UserAgent = UserAgent;
65-
var response = await request.GetResponseAsync() as HttpWebResponse;
66-
response = response.NonNull();
67-
var stream = response.GetResponseStream().NonNull();
68-
69-
using var reader = new StreamReader(stream, Encoding.GetEncoding(encoding));
70-
var content = await reader.ReadToEndAsync();
71-
if (response.StatusCode != HttpStatusCode.OK)
72-
throw new HttpRequestException($"Error code <{response.StatusCode}> with content <{content}> returned from <{url}>");
73-
74-
return content;
107+
using var response = await client.GetAsync(url);
108+
var content = await response.Content.ReadAsStringAsync();
109+
if (response.StatusCode == HttpStatusCode.OK)
110+
{
111+
return content;
112+
}
113+
else
114+
{
115+
throw new HttpRequestException(
116+
$"Error code <{response.StatusCode}> with content <{content}> returned from <{url}>");
117+
}
75118
}
76119

120+
/// <summary>
121+
/// Asynchrously get the result as stream from url.
122+
/// </summary>
123+
/// <param name="url"></param>
124+
/// <returns></returns>
77125
public static async Task<Stream> GetStreamAsync([NotNull] string url)
78126
{
79127
Log.Debug($"|Http.Get|Url <{url}>");
80-
var request = WebRequest.CreateHttp(url);
81-
request.Method = "GET";
82-
request.Timeout = 6000;
83-
request.Proxy = WebProxy();
84-
request.UserAgent = UserAgent;
85-
var response = await request.GetResponseAsync() as HttpWebResponse;
86-
response = response.NonNull();
87-
return response.GetResponseStream().NonNull();
128+
var response = await client.GetAsync(url);
129+
return await response.Content.ReadAsStreamAsync();
88130
}
89131
}
90132
}
Lines changed: 75 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,80 @@
1-
namespace Flow.Launcher.Infrastructure.UserSettings
1+
using System.ComponentModel;
2+
3+
namespace Flow.Launcher.Infrastructure.UserSettings
24
{
5+
public enum ProxyProperty
6+
{
7+
Enabled,
8+
Server,
9+
Port,
10+
UserName,
11+
Password
12+
}
13+
314
public class HttpProxy
415
{
5-
public bool Enabled { get; set; } = false;
6-
public string Server { get; set; }
7-
public int Port { get; set; }
8-
public string UserName { get; set; }
9-
public string Password { get; set; }
16+
private bool _enabled = false;
17+
private string _server;
18+
private int _port;
19+
private string _userName;
20+
private string _password;
21+
22+
public bool Enabled
23+
{
24+
get => _enabled;
25+
set
26+
{
27+
_enabled = value;
28+
OnPropertyChanged(ProxyProperty.Enabled);
29+
}
30+
}
31+
32+
public string Server
33+
{
34+
get => _server;
35+
set
36+
{
37+
_server = value;
38+
OnPropertyChanged(ProxyProperty.Server);
39+
}
40+
}
41+
42+
public int Port
43+
{
44+
get => _port;
45+
set
46+
{
47+
_port = value;
48+
OnPropertyChanged(ProxyProperty.Port);
49+
}
50+
}
51+
52+
public string UserName
53+
{
54+
get => _userName;
55+
set
56+
{
57+
_userName = value;
58+
OnPropertyChanged(ProxyProperty.UserName);
59+
}
60+
}
61+
62+
public string Password
63+
{
64+
get => _password;
65+
set
66+
{
67+
_password = value;
68+
OnPropertyChanged(ProxyProperty.Password);
69+
}
70+
}
71+
72+
public delegate void ProxyPropertyChangedHandler(ProxyProperty property);
73+
public event ProxyPropertyChangedHandler PropertyChanged;
74+
75+
private void OnPropertyChanged(ProxyProperty property)
76+
{
77+
PropertyChanged?.Invoke(property);
78+
}
1079
}
1180
}

Plugins/Flow.Launcher.Plugin.PluginsManager/Main.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ public class Main : ISettingProvider, IPlugin, ISavable, IContextMenu, IPluginI1
2222

2323
internal PluginsManager pluginManager;
2424

25-
private DateTime lastUpdateTime;
25+
private DateTime lastUpdateTime = DateTime.MinValue;
2626

2727
public Control CreateSettingPanel()
2828
{

Plugins/Flow.Launcher.Plugin.PluginsManager/Models/PluginsManifest.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ namespace Flow.Launcher.Plugin.PluginsManager.Models
1010
internal class PluginsManifest
1111
{
1212
internal List<UserPlugin> UserPlugins { get; private set; }
13+
1314
internal PluginsManifest()
1415
{
1516
Task.Run(async () => await DownloadManifest()).Wait();
@@ -30,7 +31,6 @@ internal async Task DownloadManifest()
3031

3132
UserPlugins = new List<UserPlugin>();
3233
}
33-
3434
}
3535
}
36-
}
36+
}

0 commit comments

Comments
 (0)