Last-Modified: Tue, 04 Aug 2026 14:40:22 GMT
Expires: Fri, 01 Aug 2036 14:40:22 GMT
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Authentication;
using System.Text;
using System.Threading.Tasks;
using Tango.Transport.Web;
using Tango.Web.Security;
namespace Tango.Web
{
public abstract class TangoWebClient<TLoginRequest, TLoginResponse> : IDisposable where TLoginRequest : WebRequestMessage where TLoginResponse : WebTokenResponse
{
private WebTransportClient _client;
private bool _disposed;
private TLoginRequest _lastLoginRequest;
private DeploymentSlot? _environment;
public DeploymentSlot? Environment
{
get { return _environment; }
set
{
if (_environment != value)
{
_lastLoginRequest = null;
IsAuthenticated = false;
}
_environment = value;
}
}
public String Address { get; set; }
public String Controller { get; private set; }
public String Token { get; private set; }
public WebToken WebToken { get; private set; }
public bool IsAuthenticated { get; private set; }
public TimeSpan RequestTimeout
{
get { return _client.RequestTimeout; }
set { _client.RequestTimeout = value; }
}
public TangoWebClient(DeploymentSlot environment, String controller)
{
_client = new WebTransportClient();
Controller = controller;
Environment = environment;
}
public TangoWebClient(DeploymentSlot environment, String controller, String token) : this(environment, controller)
{
Token = token;
}
public TangoWebClient(String address, String controller, String token)
{
_client = new WebTransportClient();
Address = address;
Controller = controller;
Token = token;
}
public TangoWebClient(TangoWebClient<TLoginRequest, TLoginResponse> cloned)
{
_client = new WebTransportClient();
Environment = cloned.Environment;
Address = cloned.Address;
Controller = cloned.Controller;
IsAuthenticated = cloned.IsAuthenticated;
RequestTimeout = cloned.RequestTimeout;
WebToken = cloned.WebToken;
_lastLoginRequest = cloned._lastLoginRequest;
Token = cloned.Token;
}
public T Clone<T>() where T : TangoWebClient<TLoginRequest, TLoginResponse>
{
return Activator.CreateInstance(typeof(T), new object[] { this }) as T;
}
public async Task<TLoginResponse> Login(TLoginRequest request)
{
var response = await _client.PostJson<TLoginRequest, TLoginResponse>(GetActionAddress("Login"), request);
Token = response.AccessToken;
_client.AuthenticationToken = Token;
WebToken = WebToken.FromToken(Token);
_lastLoginRequest = request;
IsAuthenticated = true;
return response;
}
protected virtual async Task<TResponse> Post<TRequest, TResponse>(String action, TRequest request) where TRequest : class, IWebRequestMessage where TResponse : class, IWebResponseMessage
{
if (IsAuthenticated)
{
if (DateTime.UtcNow >= WebToken.Expiration)
{
await Login(_lastLoginRequest);
}
}
try
{
var response = await _client.PostJson<TRequest, TResponse>(GetActionAddress(action), request);
return response;
}
catch (TokenExpiredException ex)
{
try
{
await Login(_lastLoginRequest);
var response = await _client.PostJson<TRequest, TResponse>(GetActionAddress(action), request);
return response;
}
catch
{
throw;
}
}
catch (Exception ex)
{
throw;
}
}
private String GetActionAddress(String action)
{
return GetServiceAddress() + action;
}
protected virtual String GetServiceAddress()
{
if (Environment != null)
{
return Environment.Value.ToAddress() + $"/api/{Controller}/";
}
else
{
return Address + $"/api/{Controller}/";
}
}
public virtual void Dispose()
{
if (!_disposed)
{
_disposed = true;
_client.Dispose();
}
}
}
}