forked from Meowv/Plus.Core
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
23 changed files
with
989 additions
and
0 deletions.
There are no files selected for viewing
9 changes: 9 additions & 0 deletions
9
Plus.Core/Plus/Http/Client/Authentication/IRemoteServiceHttpClientAuthenticator.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
using System.Threading.Tasks; | ||
|
||
namespace Plus.Http.Client.Authentication | ||
{ | ||
public interface IRemoteServiceHttpClientAuthenticator | ||
{ | ||
Task AuthenticateAsync(RemoteServiceHttpClientAuthenticateContext context); | ||
} | ||
} |
14 changes: 14 additions & 0 deletions
14
Plus.Core/Plus/Http/Client/Authentication/NullRemoteServiceHttpClientAuthenticator.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
using Plus.DependencyInjection; | ||
using System.Threading.Tasks; | ||
|
||
namespace Plus.Http.Client.Authentication | ||
{ | ||
[Dependency(TryRegister = true)] | ||
public class NullRemoteServiceHttpClientAuthenticator : IRemoteServiceHttpClientAuthenticator, ISingletonDependency | ||
{ | ||
public Task AuthenticateAsync(RemoteServiceHttpClientAuthenticateContext context) | ||
{ | ||
return Task.CompletedTask; | ||
} | ||
} | ||
} |
27 changes: 27 additions & 0 deletions
27
Plus.Core/Plus/Http/Client/Authentication/RemoteServiceHttpClientAuthenticateContext.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
using System.Net.Http; | ||
|
||
namespace Plus.Http.Client.Authentication | ||
{ | ||
public class RemoteServiceHttpClientAuthenticateContext | ||
{ | ||
public HttpClient Client { get; } | ||
|
||
public HttpRequestMessage Request { get; } | ||
|
||
public RemoteServiceConfiguration RemoteService { get; } | ||
|
||
public string RemoteServiceName { get; } | ||
|
||
public RemoteServiceHttpClientAuthenticateContext( | ||
HttpClient client, | ||
HttpRequestMessage request, | ||
RemoteServiceConfiguration remoteService, | ||
string remoteServiceName) | ||
{ | ||
Client = client; | ||
Request = request; | ||
RemoteService = remoteService; | ||
RemoteServiceName = remoteServiceName; | ||
} | ||
} | ||
} |
42 changes: 42 additions & 0 deletions
42
Plus.Core/Plus/Http/Client/DynamicProxying/ApiDescriptionCache.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
using Nito.AsyncEx; | ||
using Plus.DependencyInjection; | ||
using Plus.Http.Modeling; | ||
using Plus.Threading; | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Threading; | ||
using System.Threading.Tasks; | ||
|
||
namespace Plus.Http.Client.DynamicProxying | ||
{ | ||
public class ApiDescriptionCache : IApiDescriptionCache, ISingletonDependency | ||
{ | ||
protected ICancellationTokenProvider CancellationTokenProvider { get; } | ||
|
||
private readonly Dictionary<string, ApplicationApiDescriptionModel> _cache; | ||
private readonly SemaphoreSlim _semaphore; | ||
|
||
public ApiDescriptionCache(ICancellationTokenProvider cancellationTokenProvider) | ||
{ | ||
CancellationTokenProvider = cancellationTokenProvider; | ||
_cache = new Dictionary<string, ApplicationApiDescriptionModel>(); | ||
_semaphore = new SemaphoreSlim(1, 1); | ||
} | ||
|
||
public async Task<ApplicationApiDescriptionModel> GetAsync( | ||
string baseUrl, | ||
Func<Task<ApplicationApiDescriptionModel>> factory) | ||
{ | ||
using (await _semaphore.LockAsync(CancellationTokenProvider.Token)) | ||
{ | ||
var model = _cache.GetOrDefault(baseUrl); | ||
if (model == null) | ||
{ | ||
_cache[baseUrl] = model = await factory(); | ||
} | ||
|
||
return model; | ||
} | ||
} | ||
} | ||
} |
116 changes: 116 additions & 0 deletions
116
Plus.Core/Plus/Http/Client/DynamicProxying/ApiDescriptionFinder.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,116 @@ | ||
using Newtonsoft.Json; | ||
using Newtonsoft.Json.Serialization; | ||
using Plus.DependencyInjection; | ||
using Plus.Http.Modeling; | ||
using Plus.Threading; | ||
using System; | ||
using System.Linq; | ||
using System.Net.Http; | ||
using System.Reflection; | ||
using System.Threading.Tasks; | ||
|
||
namespace Plus.Http.Client.DynamicProxying | ||
{ | ||
public class ApiDescriptionFinder : IApiDescriptionFinder, ITransientDependency | ||
{ | ||
public ICancellationTokenProvider CancellationTokenProvider { get; set; } | ||
|
||
protected IApiDescriptionCache Cache { get; } | ||
|
||
private static readonly JsonSerializerSettings SharedJsonSerializerSettings = new JsonSerializerSettings | ||
{ | ||
ContractResolver = new CamelCasePropertyNamesContractResolver() | ||
}; | ||
|
||
public ApiDescriptionFinder(IApiDescriptionCache cache) | ||
{ | ||
Cache = cache; | ||
CancellationTokenProvider = NullCancellationTokenProvider.Instance; | ||
} | ||
|
||
public async Task<ActionApiDescriptionModel> FindActionAsync(HttpClient client, string baseUrl, Type serviceType, MethodInfo method) | ||
{ | ||
var apiDescription = await GetApiDescriptionAsync(client, baseUrl); | ||
|
||
//TODO: Cache finding? | ||
|
||
var methodParameters = method.GetParameters().ToArray(); | ||
|
||
foreach (var module in apiDescription.Modules.Values) | ||
{ | ||
foreach (var controller in module.Controllers.Values) | ||
{ | ||
if (!controller.Implements(serviceType)) | ||
{ | ||
continue; | ||
} | ||
|
||
foreach (var action in controller.Actions.Values) | ||
{ | ||
if (action.Name == method.Name && action.ParametersOnMethod.Count == methodParameters.Length) | ||
{ | ||
var found = true; | ||
|
||
for (int i = 0; i < methodParameters.Length; i++) | ||
{ | ||
if (!TypeMatches(action.ParametersOnMethod[i], methodParameters[i])) | ||
{ | ||
found = false; | ||
break; | ||
} | ||
} | ||
|
||
if (found) | ||
{ | ||
return action; | ||
} | ||
} | ||
} | ||
} | ||
} | ||
|
||
throw new PlusException($"Could not found remote action for method: {method} on the URL: {baseUrl}"); | ||
} | ||
|
||
public virtual async Task<ApplicationApiDescriptionModel> GetApiDescriptionAsync(HttpClient client, string baseUrl) | ||
{ | ||
return await Cache.GetAsync(baseUrl, () => GetApiDescriptionFromServerAsync(client, baseUrl)); | ||
} | ||
|
||
protected virtual async Task<ApplicationApiDescriptionModel> GetApiDescriptionFromServerAsync(HttpClient client, string baseUrl) | ||
{ | ||
var response = await client.GetAsync( | ||
baseUrl.EnsureEndsWith('/') + "api/Plus/api-definition", | ||
CancellationTokenProvider.Token | ||
); | ||
|
||
if (!response.IsSuccessStatusCode) | ||
{ | ||
throw new PlusException("Remote service returns error! StatusCode = " + response.StatusCode); | ||
} | ||
|
||
var content = await response.Content.ReadAsStringAsync(); | ||
|
||
var result = JsonConvert.DeserializeObject( | ||
content, | ||
typeof(ApplicationApiDescriptionModel), SharedJsonSerializerSettings); | ||
|
||
return (ApplicationApiDescriptionModel)result; | ||
} | ||
|
||
protected virtual bool TypeMatches(MethodParameterApiDescriptionModel actionParameter, ParameterInfo methodParameter) | ||
{ | ||
return NormalizeTypeName(actionParameter.TypeAsString) == | ||
NormalizeTypeName(methodParameter.ParameterType.GetFullNameWithAssemblyName()); | ||
} | ||
|
||
protected virtual string NormalizeTypeName(string typeName) | ||
{ | ||
const string placeholder = "%COREFX%"; | ||
const string netCoreLib = "System.Private.CoreLib"; | ||
const string netFxLib = "mscorlib"; | ||
|
||
return typeName.Replace(netCoreLib, placeholder).Replace(netFxLib, placeholder); | ||
} | ||
} | ||
} |
22 changes: 22 additions & 0 deletions
22
Plus.Core/Plus/Http/Client/DynamicProxying/ApiVersionInfo.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
using System; | ||
|
||
namespace Plus.Http.Client.DynamicProxying | ||
{ | ||
public class ApiVersionInfo //TODO: Rename to not conflict with api versioning apis | ||
{ | ||
public string BindingSource { get; } | ||
public string Version { get; } | ||
|
||
public ApiVersionInfo(string bindingSource, string version) | ||
{ | ||
BindingSource = bindingSource; | ||
Version = version; | ||
} | ||
|
||
public bool ShouldSendInQueryString() | ||
{ | ||
//TODO: Constant! TODO: Other sources! | ||
return !BindingSource.IsIn("Path"); | ||
} | ||
} | ||
} |
25 changes: 25 additions & 0 deletions
25
Plus.Core/Plus/Http/Client/DynamicProxying/DefaultDynamicProxyHttpClientFactory.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
using Plus.DependencyInjection; | ||
using System.Net.Http; | ||
|
||
namespace Plus.Http.Client.DynamicProxying | ||
{ | ||
public class DefaultDynamicProxyHttpClientFactory : IDynamicProxyHttpClientFactory, ITransientDependency | ||
{ | ||
private readonly IHttpClientFactory _httpClientFactory; | ||
|
||
public DefaultDynamicProxyHttpClientFactory(IHttpClientFactory httpClientFactory) | ||
{ | ||
_httpClientFactory = httpClientFactory; | ||
} | ||
|
||
public HttpClient Create() | ||
{ | ||
return _httpClientFactory.CreateClient(); | ||
} | ||
|
||
public HttpClient Create(string name) | ||
{ | ||
return _httpClientFactory.CreateClient(name); | ||
} | ||
} | ||
} |
17 changes: 17 additions & 0 deletions
17
Plus.Core/Plus/Http/Client/DynamicProxying/DynamicHttpClientProxyConfig.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
using System; | ||
|
||
namespace Plus.Http.Client.DynamicProxying | ||
{ | ||
public class DynamicHttpClientProxyConfig | ||
{ | ||
public Type Type { get; } | ||
|
||
public string RemoteServiceName { get; } | ||
|
||
public DynamicHttpClientProxyConfig(Type type, string remoteServiceName) | ||
{ | ||
Type = type; | ||
RemoteServiceName = remoteServiceName; | ||
} | ||
} | ||
} |
Oops, something went wrong.