aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcrupest <crupest@outlook.com>2019-04-24 00:22:25 +0800
committercrupest <crupest@outlook.com>2019-04-24 00:22:25 +0800
commit3d6938ca60691f73bc0b570e7ca4af4f8251741c (patch)
treef0b1f683254cdd80f20ea84ea6e044e80ef61fdd
parent94cb3d601af2f658f93f8092f39c326c90c8d13f (diff)
downloadtimeline-3d6938ca60691f73bc0b570e7ca4af4f8251741c.tar.gz
timeline-3d6938ca60691f73bc0b570e7ca4af4f8251741c.tar.bz2
timeline-3d6938ca60691f73bc0b570e7ca4af4f8251741c.zip
Add ObjectExists implementation in cos. Remove Test host environment.
-rw-r--r--Timeline.Tests/Helpers/WebApplicationFactoryExtensions.cs1
-rw-r--r--Timeline.Tests/QCloudCosServiceUnitTest.cs33
-rw-r--r--Timeline/EnvironmentConstants.cs14
-rw-r--r--Timeline/Services/TencentCloudCosService.cs88
-rw-r--r--Timeline/Startup.cs11
-rw-r--r--Timeline/appsettings.Test.json14
6 files changed, 112 insertions, 49 deletions
diff --git a/Timeline.Tests/Helpers/WebApplicationFactoryExtensions.cs b/Timeline.Tests/Helpers/WebApplicationFactoryExtensions.cs
index a34217f4..a7616b41 100644
--- a/Timeline.Tests/Helpers/WebApplicationFactoryExtensions.cs
+++ b/Timeline.Tests/Helpers/WebApplicationFactoryExtensions.cs
@@ -15,7 +15,6 @@ namespace Timeline.Tests.Helpers
return factory.WithWebHostBuilder(builder =>
{
builder
- .UseEnvironment(EnvironmentConstants.TestEnvironmentName)
.ConfigureLogging(logging =>
{
logging.AddXunit(outputHelper);
diff --git a/Timeline.Tests/QCloudCosServiceUnitTest.cs b/Timeline.Tests/QCloudCosServiceUnitTest.cs
index c02f70be..b99352b9 100644
--- a/Timeline.Tests/QCloudCosServiceUnitTest.cs
+++ b/Timeline.Tests/QCloudCosServiceUnitTest.cs
@@ -1,12 +1,24 @@
-using System;
+using Microsoft.AspNetCore.Mvc.Testing;
+using Microsoft.Extensions.DependencyInjection;
+using System;
using System.Collections.Generic;
+using System.Threading.Tasks;
using Timeline.Services;
+using Timeline.Tests.Helpers;
using Xunit;
+using Xunit.Abstractions;
namespace Timeline.Tests
{
- public class QCloudCosServiceUnitTest
+ public class QCloudCosServiceUnitTest : IClassFixture<WebApplicationFactory<Startup>>
{
+ private readonly WebApplicationFactory<Startup> _factory;
+
+ public QCloudCosServiceUnitTest(WebApplicationFactory<Startup> factory, ITestOutputHelper outputHelper)
+ {
+ _factory = factory.WithTestConfig(outputHelper);
+ }
+
[Fact]
public void GenerateSignatureTest()
{
@@ -37,5 +49,22 @@ namespace Timeline.Tests
Assert.Equal("q-sign-algorithm=sha1&q-ak=AKIDQjz3ltompVjBni5LitkWHFlFpwkn9U5q&q-sign-time=1417773892;1417853898&q-key-time=1417773892;1417853898&q-header-list=host;x-cos-content-sha1;x-cos-storage-class&q-url-param-list=&q-signature=0ab12f43e74cbe148d705cd9fae8adc9a6d39cc1", QCloudCosService.GenerateSign(credential, request, signValidTime));
}
+
+ /*
+ [Fact]
+ public async Task ObjectExistsTest()
+ {
+ _factory.CreateDefaultClient().Dispose();
+
+ using (var serviceScope = _factory.Server.Host.Services.CreateScope())
+ {
+ var services = serviceScope.ServiceProvider;
+ var service = services.GetRequiredService<IQCloudCosService>();
+ Assert.True(await service.ObjectExists("avatar", "__default"));
+ Assert.False(await service.ObjectExists("avatar", "haha"));
+ Assert.False(await service.ObjectExists("haha", "haha"));
+ }
+ }
+ */
}
}
diff --git a/Timeline/EnvironmentConstants.cs b/Timeline/EnvironmentConstants.cs
deleted file mode 100644
index 5ffc3623..00000000
--- a/Timeline/EnvironmentConstants.cs
+++ /dev/null
@@ -1,14 +0,0 @@
-using Microsoft.AspNetCore.Hosting;
-
-namespace Timeline
-{
- public static class EnvironmentConstants
- {
- public const string TestEnvironmentName = "Test";
-
- public static bool IsTest(this IHostingEnvironment environment)
- {
- return environment.EnvironmentName == TestEnvironmentName;
- }
- }
-}
diff --git a/Timeline/Services/TencentCloudCosService.cs b/Timeline/Services/TencentCloudCosService.cs
index 1bfcf745..8dbd3614 100644
--- a/Timeline/Services/TencentCloudCosService.cs
+++ b/Timeline/Services/TencentCloudCosService.cs
@@ -5,6 +5,7 @@ using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net;
+using System.Net.Http;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
@@ -20,13 +21,15 @@ namespace Timeline.Services
public class QCloudCosService : IQCloudCosService
{
- private readonly QCloudCosConfig _config;
+ private readonly IOptionsMonitor<QCloudCosConfig> _config;
private readonly ILogger<QCloudCosService> _logger;
+ private readonly IHttpClientFactory _httpClientFactory;
- public QCloudCosService(IOptions<QCloudCosConfig> config, ILogger<QCloudCosService> logger)
+ public QCloudCosService(IOptionsMonitor<QCloudCosConfig> config, ILogger<QCloudCosService> logger, IHttpClientFactory httpClientFactory)
{
- _config = config.Value;
+ _config = config;
_logger = logger;
+ _httpClientFactory = httpClientFactory;
}
public class QCloudCredentials
@@ -45,6 +48,17 @@ namespace Timeline.Services
public class TimeDuration
{
+ public TimeDuration()
+ {
+
+ }
+
+ public TimeDuration(DateTimeOffset start, DateTimeOffset end)
+ {
+ Start = start;
+ End = end;
+ }
+
public DateTimeOffset Start { get; set; }
public DateTimeOffset End { get; set; }
}
@@ -57,14 +71,15 @@ namespace Timeline.Services
Debug.Assert(request != null);
Debug.Assert(request.Method != null);
Debug.Assert(request.Uri != null);
- Debug.Assert(request.Parameters != null);
- Debug.Assert(request.Headers != null);
Debug.Assert(signValidTime != null);
Debug.Assert(signValidTime.Start < signValidTime.End, "Start must be before End in sign valid time.");
List<(string key, string value)> Transform(IEnumerable<KeyValuePair<string, string>> raw)
{
- var sorted= raw.Select(p => (key: p.Key.ToLower(), value: WebUtility.UrlEncode(p.Value))).ToList();
+ if (raw == null)
+ return new List<(string key, string value)>();
+
+ var sorted = raw.Select(p => (key: p.Key.ToLower(), value: WebUtility.UrlEncode(p.Value))).ToList();
sorted.Sort((left, right) => string.CompareOrdinal(left.key, right.key));
return sorted;
}
@@ -103,7 +118,7 @@ namespace Timeline.Services
}
var httpString = new StringBuilder()
- .Append(request.Method).Append('\n')
+ .Append(request.Method.ToLower()).Append('\n')
.Append(request.Uri).Append('\n')
.Append(Join(transformedParameters)).Append('\n')
.Append(Join(transformedHeaders)).Append('\n')
@@ -130,9 +145,64 @@ namespace Timeline.Services
return Join(result);
}
- public Task<bool> ObjectExists(string bucket, string key)
+ private QCloudCredentials GetCredentials()
{
- throw new NotImplementedException();
+ var config = _config.CurrentValue;
+ return new QCloudCredentials
+ {
+ SecretId = config.SecretId,
+ SecretKey = config.SecretKey
+ };
+ }
+
+ private string GetHost(string bucket)
+ {
+ var config = _config.CurrentValue;
+ return $"{bucket}-{config.AppId}.cos.{config.Region}.myqcloud.com";
+ }
+
+ public async Task<bool> ObjectExists(string bucket, string key)
+ {
+ if (bucket == null)
+ throw new ArgumentNullException(nameof(bucket));
+ if (key == null)
+ throw new ArgumentNullException(nameof(key));
+
+ var client = _httpClientFactory.CreateClient();
+
+ var host = GetHost(bucket);
+
+ var request = new HttpRequestMessage();
+ request.Method = HttpMethod.Head;
+ request.RequestUri = new Uri($"https://{host}/{key}");
+ request.Headers.Host = host;
+ request.Headers.Date = DateTimeOffset.Now;
+ request.Headers.TryAddWithoutValidation("Authorization", GenerateSign(GetCredentials(), new RequestInfo
+ {
+ Method = "head",
+ Uri = "/" + key,
+ Headers = new Dictionary<string, string>
+ {
+ ["Host"] = host
+ }
+ }, new TimeDuration(DateTimeOffset.Now, DateTimeOffset.Now.AddMinutes(2))));
+
+ try
+ {
+ var response = await client.SendAsync(request);
+
+ if (response.IsSuccessStatusCode)
+ return true;
+ if (response.StatusCode == HttpStatusCode.NotFound)
+ return false;
+
+ throw new Exception($"Unknown response code. {response.ToString()}");
+ }
+ catch (Exception e)
+ {
+ _logger.LogError(e, "An error occured when test a cos object existence.");
+ return false;
+ }
}
public string GetObjectUrl(string bucket, string key)
diff --git a/Timeline/Startup.cs b/Timeline/Startup.cs
index 12d60843..46d0afe5 100644
--- a/Timeline/Startup.cs
+++ b/Timeline/Startup.cs
@@ -81,6 +81,8 @@ namespace Timeline
});
});
+ services.AddHttpClient();
+
services.Configure<QCloudCosConfig>(Configuration.GetSection(nameof(QCloudCosConfig)));
services.AddSingleton<IQCloudCosService, QCloudCosService>();
}
@@ -88,15 +90,6 @@ namespace Timeline
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app)
{
- if (Environment.IsDevelopment())
- {
- app.UseDeveloperExceptionPage();
- }
- else
- {
- app.UseExceptionHandler("/Error");
- }
-
app.UseCors(corsPolicyName);
app.UseForwardedHeaders(new ForwardedHeadersOptions
diff --git a/Timeline/appsettings.Test.json b/Timeline/appsettings.Test.json
deleted file mode 100644
index ea32348b..00000000
--- a/Timeline/appsettings.Test.json
+++ /dev/null
@@ -1,14 +0,0 @@
-{
- "Logging": {
- "LogLevel": {
- "Default": "Debug",
- "System": "Information",
- "Microsoft": "Information",
- "Microsoft.AspNetCore.Authentication": "Debug",
- "Microsoft.AspNetCore.Authorization": "Debug"
- }
- },
- "JwtConfig": {
- "SigningKey": "crupest hahahahahahahhahahahahaha"
- }
-}