2 using System.Collections.Generic;
5 using System.Net.Http.Headers;
7 using Microsoft.AspNetCore.Http.Headers;
8 using Microsoft.Net.Http.Headers;
9 using Microsoft.Extensions.Primitives;
21 public const string ApplicationJson =
"application/json";
26 const string ApiVersionHeader =
"Api";
31 const string usernameHeader =
"Username";
36 const string instanceIdHeader =
"Instance";
41 const string jwtAuthenticationScheme =
"Bearer";
46 const string passwordAuthenticationScheme =
"Password";
51 static readonly AssemblyName assemblyName = Assembly.GetExecutingAssembly().GetName();
56 public static Version Version => assemblyName.
Version;
61 public long? InstanceId {
get;
set; }
66 public ProductHeaderValue UserAgent {
get; }
71 public Version ApiVersion {
get; }
76 public string Token {
get; }
81 public string Username {
get; }
86 public string Password {
get; }
91 public bool IsTokenAuthentication => Token != null;
98 public static bool CheckCompatibility(Version otherVersion) => !(Version.Major != otherVersion.Major || Version.Minor != otherVersion.Minor || Version.Build > otherVersion.Build);
105 public ApiHeaders(ProductHeaderValue userAgent,
string token) : this(userAgent, token, null, null)
107 if (userAgent == null)
108 throw new ArgumentNullException(nameof(userAgent));
110 throw new ArgumentNullException(nameof(token));
119 public ApiHeaders(ProductHeaderValue userAgent,
string username,
string password) : this(userAgent, null, username, password)
121 if (userAgent == null)
122 throw new ArgumentNullException(nameof(userAgent));
123 if (username == null)
124 throw new ArgumentNullException(nameof(username));
125 if (password == null)
126 throw new ArgumentNullException(nameof(password));
135 var jsonAccept =
new Microsoft.Net.Http.Headers.MediaTypeHeaderValue(ApplicationJson);
136 if (!requestHeaders.Accept.Any(x => x.MediaType == jsonAccept.MediaType))
137 throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture,
"Client does not accept {0}!", ApplicationJson));
139 if (!requestHeaders.Headers.TryGetValue(HeaderNames.UserAgent, out var userAgentValues) || !ProductInfoHeaderValue.TryParse(userAgentValues.FirstOrDefault(), out var clientUserAgent))
140 throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture,
"Missing {0} headers!", HeaderNames.UserAgent));
143 if (String.IsNullOrWhiteSpace(clientUserAgent.Product.Name) || !Version.TryParse(clientUserAgent.Product.Version, out var clientVersion))
144 throw new InvalidOperationException(
"Malformed client user agent!");
147 if (!requestHeaders.Headers.TryGetValue(ApiVersionHeader, out var apiUserAgentHeaderValues) || !ProductInfoHeaderValue.TryParse(apiUserAgentHeaderValues.FirstOrDefault(), out var apiUserAgent) || apiUserAgent.Product.Name != assemblyName.Name)
148 throw new InvalidOperationException(
"Missing API version!");
150 if (!Version.TryParse(apiUserAgent.Product.Version, out var apiVersion))
151 throw new InvalidOperationException(
"Malformed API version!");
153 ApiVersion = apiVersion;
154 UserAgent = clientUserAgent.Product;
156 if (!requestHeaders.Headers.TryGetValue(HeaderNames.Authorization, out StringValues authorization))
157 throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture,
"Missing {0} header!", HeaderNames.Authorization));
158 var auth = authorization.First();
159 var splits =
new List<string>(auth.Split(
' '));
160 var scheme = splits.First();
161 if (String.IsNullOrWhiteSpace(scheme))
162 throw new InvalidOperationException(
"Missing authentication scheme!");
165 var parameter = String.Concat(splits);
166 if (String.IsNullOrEmpty(parameter))
167 throw new InvalidOperationException(
"Missing authentication parameter!");
169 if (requestHeaders.Headers.TryGetValue(instanceIdHeader, out var instanceIdValues))
171 var instanceIdString = instanceIdValues.FirstOrDefault();
172 if (instanceIdString !=
default && Int64.TryParse(instanceIdString, out var instanceId))
173 InstanceId = instanceId;
178 case jwtAuthenticationScheme:
181 case passwordAuthenticationScheme:
182 Password = parameter;
183 var fail = !requestHeaders.Headers.TryGetValue(usernameHeader, out var values);
186 Username = values.FirstOrDefault();
187 fail = String.IsNullOrWhiteSpace(Username);
190 throw new InvalidOperationException(
"Missing Username header!");
193 throw new InvalidOperationException(
"Invalid authentication scheme!");
204 ApiHeaders(ProductHeaderValue userAgent,
string token,
string username,
string password)
206 UserAgent = userAgent;
210 ApiVersion = Version;
217 public bool Compatible() => CheckCompatibility(ApiVersion);
227 throw new ArgumentNullException(nameof(headers));
228 if (instanceId.HasValue && InstanceId.HasValue && instanceId != InstanceId)
229 throw new InvalidOperationException(
"Specified instance ID in constructor and SetRequestHeaders!");
232 headers.Accept.Add(
new MediaTypeWithQualityHeaderValue(ApplicationJson));
233 if (IsTokenAuthentication)
234 headers.Authorization =
new AuthenticationHeaderValue(jwtAuthenticationScheme, Token);
237 headers.Authorization =
new AuthenticationHeaderValue(passwordAuthenticationScheme, Password);
238 headers.Add(usernameHeader, Username);
240 headers.UserAgent.Add(
new ProductInfoHeaderValue(UserAgent));
241 headers.Add(ApiVersionHeader,
new ProductHeaderValue(assemblyName.Name, ApiVersion.ToString()).ToString());
242 instanceId = instanceId ?? InstanceId;
243 if (instanceId.HasValue)
244 headers.Add(instanceIdHeader, instanceId.ToString());