Skip to content

Commit f1dfa11

Browse files
Replace HttpWebRequest with HttpClient
Net framework implementation is less clean as HttpClient is missing synchronous methods.
1 parent a242312 commit f1dfa11

File tree

3 files changed

+110
-52
lines changed

3 files changed

+110
-52
lines changed

ShareFileModule-Installer/Globals.wxi

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<?xml version="1.0" encoding="utf-8"?>
22
<Include>
3-
<?define Version = "1.0.0.0" ?>
3+
<?define Version = "1.0.1.0" ?>
44
<?define Description = "PowerShell Module for ShareFile API. Version $(var.Version)" ?>
55
<?define Vendor = "Progress ShareFile" ?>
66
<?define SourceRootPath = "..\ShareFileModule\bin\Release\net48" ?>

ShareFileModule/PSShareFileClient.cs

Lines changed: 105 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@
1313
using System.Runtime.InteropServices;
1414
using System.Security;
1515
using System.Threading;
16+
#if NETFRAMEWORK
17+
using System.Threading.Tasks;
18+
#endif
1619

1720
namespace ShareFile.Api.Powershell
1821
{
@@ -24,6 +27,16 @@ namespace ShareFile.Api.Powershell
2427
/// </summary>
2528
public class PSShareFileClient
2629
{
30+
private static readonly HttpClient HttpClient =
31+
#if NETFRAMEWORK
32+
new HttpClient();
33+
#else
34+
new HttpClient(new SocketsHttpHandler
35+
{
36+
PooledConnectionLifetime = TimeSpan.FromMinutes(15)
37+
});
38+
#endif
39+
2740
public string Path { get; set; }
2841

2942
public ShareFileClient Client { get; set; }
@@ -109,30 +122,23 @@ public AuthenticationDomain AuthenticateUsernamePassword(string account, string
109122
AuthenticationDomain authDomain = null;
110123
var accountAndDomain = string.IsNullOrEmpty(account) ? domain : string.Format("{0}.{1}", account, domain);
111124
var uri = string.Format("https://{0}/oauth/token", accountAndDomain);
112-
var request = HttpWebRequest.CreateHttp(uri);
113-
request.Method = "POST";
114-
request.ContentType = "application/x-www-form-urlencoded";
115-
using (var body = new StreamWriter(request.GetRequestStream()))
116-
{
117125

118-
body.Write(
119-
Uri.EscapeDataString(string.Format("grant_type=password&client_id={0}&client_secret={1}&username={2}&password={3}",
120-
Resources.ClientId,
121-
Resources.ClientSecret,
122-
username,
123-
password)));
124-
}
125-
var response = (HttpWebResponse)request.GetResponse();
126-
using (var body = new StreamReader(response.GetResponseStream()))
126+
using var request = new HttpRequestMessage(HttpMethod.Post, uri);
127+
request.Content = new FormUrlEncodedContent(CreatePasswordForm(username, password));
128+
129+
using var response = SendHttpRequest(request);
130+
response.EnsureSuccessStatusCode();
131+
132+
using (var body = new StreamReader(GetResponseContentStream(response)))
127133
{
128134
var jobj = JsonConvert.DeserializeObject<JObject>(body.ReadToEnd());
129135
authDomain = new AuthenticationDomain();
130-
authDomain.OAuthToken = jobj["access_token"] != null ? jobj["access_token"].ToString() : null;
131-
uri = string.Format("https://{0}/{1}/{2}", accountAndDomain, Resources.ShareFileProvider, Resources.DefaultApiVersion);
132-
authDomain.Uri = uri;
133-
if (Domains.ContainsKey(authDomain.Uri)) Domains.Remove(authDomain.Uri);
134-
Domains.Add(authDomain.Uri, authDomain);
135-
if (Client == null) Client = CreateClient(authDomain);
136+
authDomain.OAuthToken = jobj["access_token"]?.ToString();
137+
authDomain.Uri = $"https://{accountAndDomain}/{Resources.ShareFileProvider}/{Resources.DefaultApiVersion}"; ;
138+
Domains[authDomain.Uri] = authDomain;
139+
140+
Client ??= CreateClient(authDomain);
141+
136142
var session = Client.Sessions.Get().Execute();
137143
authDomain.AuthID = session.Id;
138144
this.Save();
@@ -246,10 +252,9 @@ private EventHandlerResponse OnException(HttpResponseMessage response, int retry
246252
if (!string.IsNullOrEmpty(Domains[id].OAuthRefreshToken))
247253
{
248254
var token = GetTokenResponse(
249-
"POST",
250-
string.Format("https://{0}.{1}/oauth/token", Domains[id].Account, Domains[id].Domain),
251-
string.Format("grant_type=refresh_token&redirect_uri={0}&refresh_token={1}&client_id={2}&client_secret={3}",
252-
Resources.RedirectURL, Domains[id].OAuthRefreshToken, Resources.ClientId, Resources.ClientSecret));
255+
HttpMethod.Post,
256+
$"https://{Domains[id].Account}.{Domains[id].Domain}/oauth/token",
257+
CreateRefreshTokenForm(Domains[id].OAuthRefreshToken));
253258
Domains[id].OAuthToken = token.AccessToken;
254259
Domains[id].OAuthRefreshToken = token.RefreshToken;
255260
Client.AddOAuthCredentials(new Uri(Domains[id].Uri), token.AccessToken);
@@ -406,25 +411,76 @@ private ShareFileClient CreateClient(AuthenticationDomain domain)
406411
return client;
407412
}
408413

409-
private OAuthToken GetTokenResponse(string method, string uri, string body)
414+
private OAuthToken GetTokenResponse(HttpMethod method, string uri, Dictionary<string, string> formBody)
410415
{
411-
var request = HttpWebRequest.CreateHttp(uri);
412-
request.Method = method;
413-
if (body != null)
416+
using var request = new HttpRequestMessage(method, uri);
417+
418+
if (formBody?.Count > 0)
414419
{
415-
request.ContentType = "application/x-www-form-urlencoded";
416-
using (var writer = new StreamWriter(request.GetRequestStream()))
417-
{
418-
writer.Write(body);
419-
}
420+
request.Content = new FormUrlEncodedContent(formBody);
420421
}
421-
var response = (HttpWebResponse)request.GetResponse();
422-
using (var reader = new StreamReader(response.GetResponseStream()))
422+
423+
using var response = SendHttpRequest(request);
424+
response.EnsureSuccessStatusCode();
425+
using (var reader = new StreamReader(GetResponseContentStream(response)))
423426
{
424427
return JsonConvert.DeserializeObject<OAuthToken>(reader.ReadToEnd());
425428
}
426429
}
427430

431+
private static HttpResponseMessage SendHttpRequest(HttpRequestMessage request)
432+
{
433+
#if NETFRAMEWORK
434+
return Task.Run(() => HttpClient.SendAsync(request)).GetAwaiter().GetResult();
435+
#else
436+
return HttpClient.Send(request);
437+
#endif
438+
}
439+
440+
private static Stream GetResponseContentStream(HttpResponseMessage response)
441+
{
442+
#if NETFRAMEWORK
443+
return response.Content.ReadAsStreamAsync().GetAwaiter().GetResult();
444+
#else
445+
return response.Content.ReadAsStream();
446+
#endif
447+
}
448+
449+
private static Dictionary<string, string> CreateBaseFormDictionary(string grantType)
450+
=> new Dictionary<string, string>
451+
{
452+
{ "grant_type", grantType },
453+
{ "client_id", Resources.ClientId },
454+
{ "client_secret", Resources.ClientSecret },
455+
};
456+
457+
private static Dictionary<string, string> CreatePasswordForm(string userName, string password)
458+
{
459+
var retVal = CreateBaseFormDictionary("password");
460+
retVal["username"] = userName;
461+
retVal["password"] = password;
462+
463+
return retVal;
464+
}
465+
466+
private static Dictionary<string, string> CreateRefreshTokenForm(string refreshToken)
467+
{
468+
var retVal = CreateBaseFormDictionary("refresh_token");
469+
retVal["redirect_uri"] = Resources.RedirectURL;
470+
retVal["refresh_token"] = refreshToken;
471+
472+
return retVal;
473+
}
474+
475+
private static Dictionary<string, string> CreateAuthorizationCodeForm(string code)
476+
{
477+
var retVal = CreateBaseFormDictionary("authorization_code");
478+
retVal["code"] = code;
479+
retVal["requirev3"] = "true";
480+
481+
return retVal;
482+
}
483+
428484
private class WebDialogThread
429485
{
430486
public AuthenticationDomain Result
@@ -436,13 +492,13 @@ public AuthenticationDomain Result
436492
}
437493
}
438494
private AuthenticationDomain _result = null;
439-
private AutoResetEvent _waitHandle = new AutoResetEvent(false);
495+
private readonly AutoResetEvent _waitHandle = new AutoResetEvent(false);
440496

441-
private PSShareFileClient _psClient;
442-
private AuthenticationDomain _requestDomain;
443-
private Uri _formUri;
444-
private Uri _tokenUri;
445-
private string _root;
497+
private readonly PSShareFileClient _psClient;
498+
private readonly AuthenticationDomain _requestDomain;
499+
private readonly Uri _formUri;
500+
private readonly Uri _tokenUri;
501+
private readonly string _root;
446502

447503
public WebDialogThread(PSShareFileClient psClient, AuthenticationDomain domain, Uri formUri = null, Uri tokenUri = null, string root = null)
448504
{
@@ -487,10 +543,9 @@ public void Run()
487543
var appCP = query["appcp"];
488544

489545
token = _psClient.GetTokenResponse(
490-
"POST",
491-
string.Format("https://{0}.{1}/oauth/token", subdomain, appCP),
492-
string.Format("grant_type=authorization_code&code={0}&client_id={1}&client_secret={2}&requirev3=true", query["code"],
493-
Resources.ClientId, Resources.ClientSecret));
546+
HttpMethod.Post,
547+
$"https://{subdomain}.{appCP}/oauth/token",
548+
CreateAuthorizationCodeForm(query["code"]));
494549

495550
authDomain = new AuthenticationDomain();
496551
authDomain.OAuthToken = token.AccessToken;
@@ -522,10 +577,12 @@ public void Run()
522577
var kvpSplit = kvp.Split('=');
523578
if (kvpSplit.Length == 2) query.Add(kvpSplit[0], kvpSplit[1]);
524579
}
525-
var request = HttpWebRequest.CreateHttp(_tokenUri.ToString() + string.Format("?root={0}&code={1}", _root, query["code"]));
526-
var response = (HttpWebResponse)request.GetResponse();
580+
using var request = new HttpRequestMessage(HttpMethod.Get, $"{_tokenUri}?root={_root}&code={query["code"]}");
581+
using var response = SendHttpRequest(request);
582+
response.EnsureSuccessStatusCode();
583+
527584
Session session = null;
528-
using (var reader = new StreamReader(response.GetResponseStream()))
585+
using (var reader = new StreamReader(GetResponseContentStream(response)))
529586
{
530587
session = JsonConvert.DeserializeObject<Session>(reader.ReadToEnd());
531588
}

ShareFileModule/ShareFileModule.csproj

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,13 @@
22
<PropertyGroup>
33
<RootNamespace>ShareFile.Api.Powershell</RootNamespace>
44
<TargetFrameworks>net48;net8.0-windows</TargetFrameworks>
5+
<LangVersion>10.0</LangVersion>
56
<AssemblyTitle>ShareFileModule</AssemblyTitle>
67
<Product>ShareFileModule</Product>
7-
<Copyright>Copyright © 2024 Progress</Copyright>
8+
<Copyright>Copyright © 2025 Progress</Copyright>
89
<Deterministic>false</Deterministic>
9-
<AssemblyVersion>1.0.*</AssemblyVersion>
10-
<FileVersion>1.0.*</FileVersion>
10+
<AssemblyVersion>1.0.1.0</AssemblyVersion>
11+
<FileVersion>1.0.1.0</FileVersion>
1112
<OutputPath>bin\$(Configuration)\</OutputPath>
1213
<UseWindowsForms>true</UseWindowsForms>
1314
<!-- For Dispatcher found in System.Windows.Threading -->

0 commit comments

Comments
 (0)