-
Notifications
You must be signed in to change notification settings - Fork 14
/
Copy pathApiResolver.cs
126 lines (105 loc) · 3.82 KB
/
ApiResolver.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
// Licensed to Elasticsearch B.V under one or more agreements.
// Elasticsearch B.V licenses this file to you under the Apache 2.0 License.
// See the LICENSE file in the project root for more information
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using System.Linq;
#if NETFRAMEWORK
using System.Net;
#endif
using System.Net.Http;
#if !NETFRAMEWORK
using System.Security.Authentication;
#endif
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Text.RegularExpressions;
namespace Elastic.Stack.ArtifactsApi.Resolvers
{
public static class ApiResolver
{
private const string ArtifactsApiUrl = "https://artifacts-api.elastic.co/v1/";
private static readonly ConcurrentDictionary<string, bool> Releases = new ConcurrentDictionary<string, bool>();
private static HttpClient HttpClient { get; } =
#if NETFRAMEWORK
new HttpClient
#else
// SslProtocols is only available in .NET Framework 4.7.2 and above
new HttpClient(new HttpClientHandler { SslProtocols = SslProtocols.Tls12 })
#endif
{
BaseAddress = new Uri(ArtifactsApiUrl)
};
private static Regex BuildHashRegex { get; } =
new Regex(@"https://(?:snapshots|staging).elastic.co/(\d+\.\d+\.\d+-([^/]+)?)");
public static string FetchJson(string path)
{
using (var stream = HttpClient.GetStreamAsync(path).GetAwaiter().GetResult())
using (var fileStream = new StreamReader(stream))
return fileStream.ReadToEnd();
}
public static bool IsReleasedVersion(string version)
{
if (Releases.TryGetValue(version, out var released))
return released;
var versionPath = "https://github.com/elastic/elasticsearch/releases/tag/v" + version;
var message = new HttpRequestMessage { Method = HttpMethod.Head, RequestUri = new Uri(versionPath) };
using (var response = HttpClient.SendAsync(message).GetAwaiter().GetResult())
{
released = response.IsSuccessStatusCode;
Releases.TryAdd(version, released);
return released;
}
}
public static string LatestBuildHash(string version)
{
var json = FetchJson($"search/{version}/msi");
try
{
// if packages is empty it turns into an array[] otherwise its a dictionary :/
var packages = JsonSerializer.Deserialize<ArtifactsSearchResponse>(json).Packages;
if (packages.Count == 0)
throw new Exception("Can not get build hash for: " + version);
return GetBuildHash(packages.First().Value.DownloadUrl);
}
catch
{
throw new Exception("Can not get build hash for: " + version);
}
}
public static string GetBuildHash(string url)
{
var tokens = BuildHashRegex.Split(url).Where(s => !string.IsNullOrWhiteSpace(s)).ToArray();
if (tokens.Length < 2)
throw new Exception("Can not parse build hash from: " + url);
return tokens[1];
}
#if NETFRAMEWORK
static ApiResolver() =>
ServicePointManager.SecurityProtocol = ServicePointManager.SecurityProtocol
& ~SecurityProtocolType.Ssl3
& ~SecurityProtocolType.Tls
& ~SecurityProtocolType.Tls11;
#endif
}
internal class ArtifactsVersionsResponse
{
[JsonPropertyName("versions")] public List<string> Versions { get; set; }
}
internal class ArtifactsSearchResponse
{
[JsonPropertyName("packages")] public Dictionary<string, SearchPackage> Packages { get; set; }
}
internal class SearchPackage
{
[JsonPropertyName("url")] public string DownloadUrl { get; set; }
[JsonPropertyName("sha_url")] public string ShaUrl { get; set; }
[JsonPropertyName("asc_url")] public string AscUrl { get; set; }
[JsonPropertyName("type")] public string Type { get; set; }
[JsonPropertyName("architecture")] public string Architecture { get; set; }
[JsonPropertyName("os")] public string[] OperatingSystem { get; set; }
[JsonPropertyName("classifier")] public string Classifier { get; set; }
}
}