diff --git a/casdk-docs/docs/architecture/decisions/0016-watt-time-v3.md b/casdk-docs/docs/architecture/decisions/0016-watt-time-v3.md
index 0e726d313..a2b199c64 100644
--- a/casdk-docs/docs/architecture/decisions/0016-watt-time-v3.md
+++ b/casdk-docs/docs/architecture/decisions/0016-watt-time-v3.md
@@ -38,7 +38,7 @@ The following is configured at `CarbonAware.DataSources.WattTime/src/Constants/
| Forecast | Get forecast| /forecast | /forecast | **TODO: CHECK IMPACT**
No longer be used for historical data
_Request_
`ba` is now `region` `extended_forecast` removed `horizon_hours` added `signal_type` added Historical forecasts are now at `/forecast/historical`
_Response_ `signal_type` added
| Historical | Get historical forecast data | /historical (?) | /forecast/historical (?) | **We need to validate why historical was being used for the API, and what historical used to be, and whether this should be the new /forecast/historical or not.**
| Balancing Authority From Location | Get balancing authority from location | /ba-from-loc | /region-from-loc | Check if the CA SDK uses BA at all
_Request_ `name` is now `region_full_name` `abbrev` is now `region` `signal_type` added
_Response_ `id` removed `signal_type` added |
-| Login | User login | https://api2.watttime.org/v2/login | https://api.watttime.org/login | Path has changed from being version specific to being unique from the API version.
**TODO: CHECK HOW BASE URL IS DEFINED AS THIS WILL NOW HAVE DIFFERENT VALUES**
+| Login | User login | https://api2.watttime.org/v2/login | https://api.watttime.org/login | Path has changed from being version specific to being no longer related to the API version.
**TODO: CHECK HOW BASE URL IS DEFINED AS THIS WILL NOW HAVE DIFFERENT VALUES**
### Query Strings
diff --git a/src/CarbonAware.DataSources/CarbonAware.DataSources.WattTime/src/Client/IWattTimeClient.cs b/src/CarbonAware.DataSources/CarbonAware.DataSources.WattTime/src/Client/IWattTimeClient.cs
index fbe1fdef1..4cdf21f18 100644
--- a/src/CarbonAware.DataSources/CarbonAware.DataSources.WattTime/src/Client/IWattTimeClient.cs
+++ b/src/CarbonAware.DataSources/CarbonAware.DataSources.WattTime/src/Client/IWattTimeClient.cs
@@ -8,6 +8,7 @@ namespace CarbonAware.DataSources.WattTime.Client;
internal interface IWattTimeClient
{
public const string NamedClient = "WattTimeClient";
+ public const string NamedAuthenticationClient = "WattTimeAuthenticationClient"
///
/// Async method to get observed emission data for a given balancing authority and time period.
diff --git a/src/CarbonAware.DataSources/CarbonAware.DataSources.WattTime/src/Client/WattTimeClient.cs b/src/CarbonAware.DataSources/CarbonAware.DataSources.WattTime/src/Client/WattTimeClient.cs
index ed4e10e5d..9b17882ae 100644
--- a/src/CarbonAware.DataSources/CarbonAware.DataSources.WattTime/src/Client/WattTimeClient.cs
+++ b/src/CarbonAware.DataSources/CarbonAware.DataSources.WattTime/src/Client/WattTimeClient.cs
@@ -25,6 +25,7 @@ internal class WattTimeClient : IWattTimeClient
};
private HttpClient _client;
+ private HttpClient _authenticationClient;
private IOptionsMonitor _configurationMonitor { get; }
@@ -37,12 +38,19 @@ internal class WattTimeClient : IWattTimeClient
public WattTimeClient(IHttpClientFactory factory, IOptionsMonitor configurationMonitor, ILogger log, IMemoryCache memoryCache)
{
_client = factory.CreateClient(IWattTimeClient.NamedClient);
+ _authenticationClient = factory.CreateClient(IWattTimeClient.NamedAuthenticationClient);
+
_configurationMonitor = configurationMonitor;
_log = log;
_configuration.Validate();
_client.BaseAddress = new Uri(this._configuration.BaseUrl);
_client.DefaultRequestHeaders.Accept.Clear();
_client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue(MediaTypeNames.Application.Json));
+
+ _authenticationClient.BaseAddress = new Uri(this._configuration.AuthenticationBaseUrl);
+ _authenticationClient.DefaultRequestHeaders.Accept.Clear();
+ _authenticationClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue(MediaTypeNames.Application.Json));
+
_memoryCache = memoryCache;
}
@@ -215,7 +223,7 @@ private async Task UpdateAuthTokenAsync()
_log.LogInformation("Attempting to log in user {username}", this._configuration.Username);
this.SetBasicAuthenticationHeader();
- HttpResponseMessage response = await this._client.GetAsync(Paths.Login);
+ HttpResponseMessage response = await this._authenticationClient.GetAsync(Paths.Login);
LoginResult? data = null;
@@ -239,6 +247,7 @@ private void SetBasicAuthenticationHeader()
{
var authToken = Encoding.UTF8.GetBytes($"{this._configuration.Username}:{this._configuration.Password}");
this._client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(AuthenticationHeaderTypes.Basic, Convert.ToBase64String(authToken));
+ this._authenticationClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(AuthenticationHeaderTypes.Basic, Convert.ToBase64String(authToken));
}
internal void SetBearerAuthenticationHeader(string token)
diff --git a/src/CarbonAware.DataSources/CarbonAware.DataSources.WattTime/src/Configuration/WattTimeClientConfiguration.cs b/src/CarbonAware.DataSources/CarbonAware.DataSources.WattTime/src/Configuration/WattTimeClientConfiguration.cs
index 746cd2b4c..104aeb759 100644
--- a/src/CarbonAware.DataSources/CarbonAware.DataSources.WattTime/src/Configuration/WattTimeClientConfiguration.cs
+++ b/src/CarbonAware.DataSources/CarbonAware.DataSources.WattTime/src/Configuration/WattTimeClientConfiguration.cs
@@ -25,6 +25,12 @@ internal class WattTimeClientConfiguration
///
public string BaseUrl { get; set; } = "https://api2.watttime.org/v2/";
+ ///
+ /// Authentication base url. This changed between v2 and v3
+ /// to be different to the API base url.
+ ///
+ public string AuthenticationBaseUrl { get; set; } = "https://api.watttime.org/";
+
///
/// Gets or sets the cached expiration time (in seconds) for a BalancingAuthority instance.
/// It defaults to 86400 secs.
@@ -51,6 +57,11 @@ public void Validate()
throw new ConfigurationException($"{Key}:{nameof(this.BaseUrl)} is not a valid absolute url.");
}
+ if (!Uri.IsWellFormedUriString(this.AuthenticationBaseUrl, UriKind.Absolute))
+ {
+ throw new ConfigurationException($"{Key}:{nameof(this.AuthenticationBaseUrl)} is not a valid absolute url.");
+ }
+
// Validate credential encoding/decoding with UTF8
if (!Encoding.UTF8.GetString(Encoding.UTF8.GetBytes(this.Username)).Equals(this.Username))
{