Closed abjerner closed 2 years ago
Couldn't help adding the HMAC logic to Skybrud.Essentials, so now we can replace:
// Hmac hash needed for authing with Skyfish - https://api.skyfish.com/#sectionHead-21
int unixTimestamp = (int)(DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1))).TotalSeconds;
string hmac = "";
var keyByte = Encoding.UTF8.GetBytes(SecretKey);
using (var hmacsha1 = new HMACSHA1(keyByte))
{
hmacsha1.ComputeHash(Encoding.UTF8.GetBytes($"{ApiKey}:{unixTimestamp}"));
hmac += StringExtensions.ByteToString(hmacsha1.Hash);
}
with this one liner:
// Hmac hash needed for authing with Skyfish - https://api.skyfish.com/#sectionHead-21
string hmac = SecurityUtils.GetHmacSha1Hash(SecretKey, $"{ApiKey}:{OAuthUtils.GetTimestamp()}");
😎
Closing this issue a Jesper's follow up PR #2 is now merged...
Based on commit: 6f4a1c49fb375cf7dfe265341e3c20105966758d
Formatting
Since we have the
.editorconfig
file in the VS solution, it might be a good idea to re-format the code. I think the shortcut isCTRL + K
+CTRL + D
even without ReSharper.Naming
Generally the .NET convention is to use Pascal casing for type and member names - also for abbreviations, although Microsoft them selves doesn't always follow this. So a property like
ThumbnailUrlSSL
should ideally be namedThumbnailUrlSSL
.File name and file size are also separate words, so they should ideally be
FileName
andFileSize
.Remove setters
In most cases throughout the package, there isn't a need to set the properties from outside of the class the properties belong to, so it might be a good idea to remove the setter methods from those properties.
For instance, the
SkyfishHttpService
class currently haspublic SkyfishHttpClient Client { get; set; }
, which could be changed topublic SkyfishHttpClient Client { get; }
.Client vs Service
For our other integration packages, the purposes of the HTTP client class is to handle what I call the "raw" communication with the underlying API. Methods should therefore ideally return instances of
IHttpResponse
we can then deal with later in the HTTP service class.The HTTP service class is then responsible for turning the
IHttpResponse
s into object oriented models mapping the JSON model received from the API. Typically the two classes should have the same methods (if we ignore the return type).I would prefer it this way as well here, although it's not something I'm going to mandate 😉
Separation of code
The package currently has some logic for getting the token and keeping it in memory. But this being an integration package, I believe it should fully support making the necessary calls to the Skyfish API, but then let it up to the user (eg. our Skybrud.VideoPicker.Skyfish package) to deal with how the token is stored/cached.
StringExtensions
The
ByteToString
extension method would be a good fit for moving to Skybrud.Essentials. You might want to rewrite it a bit to avoid string concatenation - see more here.SkyfishHttpClient
Skybrud.Essentials (+.Http)
UNIX Timestamp
You can get the current UNIX timestamp from Skybrud.Essentials via
(int) UnixTimeUtils.CurrentSeconds)
- or perhaps even better in this case, use Skybrud.Essentials.Http'sOAuthUtils.GetTimestamp
method.HMACSHA1
The
HMACSHA1
class extends theHashAlgorithm
class, so you should be able to replace parts of your hashing code with the SecurityUtils.GetHash method. We could even create an extension method that also initializes theHMACSHA1
so you can do the hashing with a single method call.Notice that the methods in Skybrud.Essentials return the hex values in lower case.
HttpClient
Skybrud.Essentials.Http comes with a
HttpClient
class with is written for integration packages like this. So if you makeSkyfishHttpClient
extendHttpClient
, you can change this:into this:
The
HttpClient
class exposes methods for the different HTTP verbs - eg. theGet
andPost
methods. If you use these, the request are routed through thePrepareHttpRequest
- which we can override and use to modify the request a bit before the request is sent to the destination.In the example with Skyfish, we can append the correct scheme and domain to the URLs of the different requests, and we can add the
Authorization
here as well - both making the other methods a simpler.JsonUtils.ParseJsonObject
Like we talked about on Slack, this isn't super necessary as Skyfish are using UNIX timestamp. But it might still be a good idea to use
JsonUtils.ParseJsonObject
overJObject.Parse
- eg. replace this:with this:
JsonUtils.ParseJsonObject
disables Netwonsoft.Json's default date time handling (which we don't need here due to the UNIX timestamps), but IMO it also makes the code more readable.SkyfishAuthResponse
To make the package easier to use, it might be a good idea to convert the
ValidUntilUnix
property fromlong
to eitherDateTimeOffset
or our ownEssentialsTime
.For the parsing of the timestamp, you can replace
ValidUntilUnix = long.Parse(obj.GetString("validUntil"))
withValidUntilUnix = obj.GetInt64("validUntil"))
(Int64
is the CLR name oflong
).or if we do change the type, change the line to: