diff --git a/HackMD.API/HackMD.API.csproj b/HackMD.API/HackMD.API.csproj index 9a41e29..c3092cd 100644 --- a/HackMD.API/HackMD.API.csproj +++ b/HackMD.API/HackMD.API.csproj @@ -17,4 +17,8 @@ https://github.com/isdaviddong/HackMD.API https://github.com/isdaviddong/HackMD.API + + + + diff --git a/HackMD.API/HackMDClinet.cs b/HackMD.API/HackMDClinet.cs index c97f8a1..dbb4a0b 100644 --- a/HackMD.API/HackMDClinet.cs +++ b/HackMD.API/HackMDClinet.cs @@ -1,6 +1,10 @@ using System; using System.Net.Http; +using System.Net.Http.Headers; using System.Text; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Authentication.JwtBearer; namespace HackMD.API { @@ -8,85 +12,113 @@ public class HackMDClient { private string token; - public string Token + private static readonly Lazy s_socketLazy = new Lazy(() => { - get { return token; } - set { token = value; } - } + var socketsHandler = new SocketsHttpHandler + { + PooledConnectionLifetime = TimeSpan.FromMinutes(10), + PooledConnectionIdleTimeout = TimeSpan.FromMinutes(5), + MaxConnectionsPerServer = 10 + }; + return socketsHandler; + }); + + private readonly string _token; public HackMDClient(string token) { - this.Token = token; + this._token = token; + } + + static HttpClient CreateHttpClient(string token) + { + return new HttpClient(s_socketLazy.Value) + { + DefaultRequestHeaders = + { + Authorization = new AuthenticationHeaderValue(JwtBearerDefaults.AuthenticationScheme, + token) + }, + BaseAddress = new Uri("https://api.hackmd.io/v1/") + }; } - private string endpoint = "https://api.hackmd.io/v1/"; #region "User API" - public User GetUserInformation() + + public User GetUserInformation() => this.GetUserInformationAsync().Result; + + public async Task GetUserInformationAsync(CancellationToken cancel = default) { - HttpClient client = new HttpClient(); - string uri = endpoint + $"/me"; - - // Request headers. - client.DefaultRequestHeaders.Add("Authorization", $"Bearer {this.Token}"); - var response = client.GetAsync(uri).Result; - var ResponseBody = response.Content.ReadAsStringAsync().Result; - var UserObj = System.Text.Json.JsonSerializer.Deserialize(ResponseBody); - return UserObj; + var client = CreateHttpClient(this._token); + string uri = "me"; + + var request = CreateDefaultHttpRequest(token, uri); + var response = await client.SendAsync(request, cancel); + var responseBody = await response.Content.ReadAsStringAsync(); + var result = System.Text.Json.JsonSerializer.Deserialize(responseBody); + return result; } + #endregion #region "User Notes API" + /// /// Create a note /// /// /// - public NoteResponse CreateNote(Note newHackMDNote) + public NoteResponse CreateNote(Note newHackMDNote) => this.CreateNoteAsync(newHackMDNote).Result; + + public async Task CreateNoteAsync(Note newHackMDNote, CancellationToken cancel = default) { - HttpClient client = new HttpClient(); - string uri = endpoint + "/notes"; + var client = CreateHttpClient(this._token); + string uri = "notes"; + + var requestBody = System.Text.Json.JsonSerializer.Serialize(newHackMDNote); + var requestContent = new StringContent(requestBody, Encoding.UTF8, "application/json"); - // Request headers. - client.DefaultRequestHeaders.Add("Authorization", $"Bearer {this.Token}"); - var JSON = System.Text.Json.JsonSerializer.Serialize(newHackMDNote); - var content = new StringContent(JSON, Encoding.UTF8, "application/json"); // Asynchronously call the REST API method. - var response = client.PostAsync(uri, content).Result; - var ResponseBody = response.Content.ReadAsStringAsync().Result; - var CreateNoteResponseObj = System.Text.Json.JsonSerializer.Deserialize(ResponseBody); - return CreateNoteResponseObj; + var response = await client.PostAsync(uri, requestContent, cancel); + var responseBody = await response.Content.ReadAsStringAsync(); + var result = System.Text.Json.JsonSerializer.Deserialize(responseBody); + return result; } - public NoteResponse GetNote(string noteId) + + public NoteResponse GetNote(string noteId) => this.GetNoteAsync(noteId).Result; + + public async Task GetNoteAsync(string noteId) { - HttpClient client = new HttpClient(); - string uri = endpoint + $"/notes/{noteId}"; - - // Request headers. - client.DefaultRequestHeaders.Add("Authorization", $"Bearer {this.Token}"); - var response = client.GetAsync(uri).Result; - var ResponseBody = response.Content.ReadAsStringAsync().Result; - var CreateNoteResponseObj = System.Text.Json.JsonSerializer.Deserialize(ResponseBody); - return CreateNoteResponseObj; + var client = CreateHttpClient(this._token); + string uri = $"notes/{noteId}"; + + var response = await client.GetAsync(uri); + var responseBody = await response.Content.ReadAsStringAsync(); + var result = System.Text.Json.JsonSerializer.Deserialize(responseBody); + return result; } - public bool UpdateNote(string noteId, string content, ReadWritePermission readPermission, ReadWritePermission writePermission, string permalink) + + public bool UpdateNote(string noteId, string content, ReadWritePermission readPermission, + ReadWritePermission writePermission, string permalink) => + this.UpdateNoteAsync(noteId, content, readPermission, writePermission, permalink).Result; + + public async Task UpdateNoteAsync(string noteId, string content, ReadWritePermission readPermission, + ReadWritePermission writePermission, string permalink) { - HttpClient client = new HttpClient(); - string uri = endpoint + $"/notes/{noteId}"; + var client = CreateHttpClient(this._token); + + string uri = $"notes/{noteId}"; - var obj = new + var requestBody = System.Text.Json.JsonSerializer.Serialize(new { - content = content, + content, readPermission = readPermission.ToString(), writePermission = writePermission.ToString(), - permalink = permalink - }; - - // Request headers. - client.DefaultRequestHeaders.Add("Authorization", $"Bearer {this.Token}"); - var JSON = System.Text.Json.JsonSerializer.Serialize(obj); - var body = new StringContent(JSON, Encoding.UTF8, "application/json"); - var response = client.PatchAsync(uri, body).Result; - var ResponseBody = response.Content.ReadAsStringAsync().Result; + permalink + }); + var requestContent = new StringContent(requestBody, Encoding.UTF8, "application/json"); + var response = await client.PatchAsync(uri, requestContent); + var responseBody = await response.Content.ReadAsStringAsync(); return response.StatusCode == System.Net.HttpStatusCode.Accepted; } @@ -95,17 +127,25 @@ public bool UpdateNote(string noteId, string content, ReadWritePermission readPe /// /// /// - public bool DeleteNote(string noteId) + public bool DeleteNote(string noteId) => this.DeleteNoteAsync(noteId).Result; + + public async Task DeleteNoteAsync(string noteId) { - HttpClient client = new HttpClient(); - string uri = endpoint + $"/notes/{noteId}"; + var client = CreateHttpClient(this._token); - // Request headers. - client.DefaultRequestHeaders.Add("Authorization", $"Bearer {this.Token}"); + string uri = $"notes/{noteId}"; - var response = client.DeleteAsync(uri).Result; + var response = await client.DeleteAsync(uri); return response.StatusCode == System.Net.HttpStatusCode.NoContent; } + #endregion + + private static HttpRequestMessage CreateDefaultHttpRequest(string token, string uri) + { + var request = new HttpRequestMessage(HttpMethod.Get, uri); + request.Headers.Add("Authorization", $"Bearer {token}"); + return request; + } } -} +} \ No newline at end of file diff --git a/HackMD.APITests/HackMDClinetTests.cs b/HackMD.APITests/HackMDClinetTests.cs index 266bf52..df38f2c 100644 --- a/HackMD.APITests/HackMDClinetTests.cs +++ b/HackMD.APITests/HackMDClinetTests.cs @@ -1,8 +1,5 @@ using Microsoft.VisualStudio.TestTools.UnitTesting; -using HackMD.API; using System; -using System.Collections.Generic; -using System.Text; namespace HackMD.API.Tests { @@ -25,7 +22,7 @@ public HackMDClientTests() public void CreateNoteTest() { // 建立HackMDClient 物件 - HackMDClient c = new HackMDClient(token); //須提供token + HackMDClient c = new HackMDClient(this.token); //須提供token //建立新 Note var ret = c.CreateNote( new Note() @@ -39,14 +36,14 @@ public void CreateNoteTest() //取得 NoteId TempNoteId = ret.id; Assert.IsTrue(!string.IsNullOrEmpty(ret.id)); - //c.DeleteNote(ret.id); + // c.DeleteNote(ret.id); } [TestMethod()] public void DeleteNoteTest() { // 建立HackMDClient 物件 - HackMDClient c = new HackMDClient(token); //須提供token + HackMDClient c = new HackMDClient(this.token); //須提供token var ret = c.CreateNote( new Note() { @@ -67,7 +64,7 @@ public void DeleteNoteTest() public void UpdateNoteTest() { // 建立HackMDClient 物件 - HackMDClient c = new HackMDClient(token); //須提供token + HackMDClient c = new HackMDClient(this.token); //須提供token var ret = c.CreateNote( new Note() { @@ -94,7 +91,7 @@ public void UpdateNoteTest() public void GetNoteTest() { // 建立HackMDClient 物件 - HackMDClient c = new HackMDClient(token); //須提供token + HackMDClient c = new HackMDClient(this.token); //須提供token //建立文件 var ret = c.CreateNote( new Note()