• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

rwjdk / TrelloDotNet / 5992095035

27 Aug 2023 04:43PM UTC coverage: 69.438% (-1.4%) from 70.85%
5992095035

push

github

rwjdk
Version 1.8.0

824 of 1507 branches covered (0.0%)

Branch coverage included in aggregate %.

77 of 77 new or added lines in 9 files covered. (100.0%)

2082 of 2678 relevant lines covered (77.74%)

62.07 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

95.54
/TrelloDotNet/TrelloDotNet/Control/ApiRequestController.cs
1
using System;
2
using System.IO;
3
using System.Net;
4
using System.Net.Http;
5
using System.Net.Http.Headers;
6
using System.Text;
7
using System.Text.Json;
8
using System.Threading;
9
using System.Threading.Tasks;
10
using TrelloDotNet.Model;
11

12
namespace TrelloDotNet.Control
13
{
14
    internal class ApiRequestController
15
    {
16
        private const string BaseUrl = "https://api.trello.com/1/";
17
        private readonly HttpClient _httpClient;
18
        private readonly string _apiKey;
19
        private readonly string _token;
20
        private readonly TrelloClient _client;
21

22
        internal ApiRequestController(HttpClient httpClient, string apiKey, string token, TrelloClient client)
183✔
23
        {
24
            _httpClient = httpClient;
183✔
25
            _httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
183✔
26
            _apiKey = apiKey;
183✔
27
            _token = token;
183✔
28
            _client = client;
183✔
29
        }
183✔
30

31
        public string Token => _token;
21✔
32

33
        internal async Task<T> Get<T>(string suffix, CancellationToken cancellationToken, params QueryParameter[] parameters)
34
        {
35
            string json = await Get(suffix, cancellationToken, 0, parameters);
301✔
36
            var @object = JsonSerializer.Deserialize<T>(json);
301✔
37
            return @object;
301✔
38
        }
301✔
39

40
        internal async Task<string> Get(string suffix, CancellationToken cancellationToken, int retryCount, params QueryParameter[] parameters)
41
        {
42
            var uri = BuildUri(suffix, parameters);
358✔
43
            var response = await _httpClient.GetAsync(uri, cancellationToken);
358✔
44
            var responseContent = await response.Content.ReadAsStringAsync();
358✔
45
            if (response.StatusCode != HttpStatusCode.OK)
358✔
46
            {
47
                return await PreformRetryIfNeededOrThrow(uri, responseContent, retry => Get(suffix, cancellationToken, retry, parameters), retryCount, cancellationToken);
108✔
48
            }
49
            return responseContent; //Content is assumed JSON
302✔
50
        }
354✔
51

52
        internal async Task<T> Post<T>(string suffix, CancellationToken cancellationToken, params QueryParameter[] parameters)
53
        {
54
            string json = await Post(suffix, cancellationToken, 0, parameters);
240✔
55
            var @object = JsonSerializer.Deserialize<T>(json);
240✔
56
            return @object;
240✔
57
        }
240✔
58

59
        internal async Task<T> PostWithAttachmentFileUpload<T>(string suffix, AttachmentFileUpload attachmentFile, CancellationToken cancellationToken, params QueryParameter[] parameters)
60
        {
61
            string json = await PostWithAttachmentFileUpload(suffix, attachmentFile, cancellationToken, 0, parameters);
1✔
62
            var @object = JsonSerializer.Deserialize<T>(json);
1✔
63
            return @object;
1✔
64
        }
1✔
65

66
        internal async Task<string> PostWithAttachmentFileUpload(string suffix, AttachmentFileUpload attachmentFile, CancellationToken cancellationToken, int retryCount, params QueryParameter[] parameters)
67
        {
68
            var uri = BuildUri(suffix, parameters);
1✔
69
            using (var multipartFormContent = new MultipartFormDataContent())
1✔
70
            {
71
                multipartFormContent.Add(new StreamContent(attachmentFile.Stream), name: @"file", fileName: attachmentFile.Filename);
1✔
72
                var response = await _httpClient.PostAsync(uri, multipartFormContent, cancellationToken);
1✔
73
                var responseContent = await response.Content.ReadAsStringAsync();
1✔
74
                if (response.StatusCode != HttpStatusCode.OK)
1!
75
                {
76
                    return await PreformRetryIfNeededOrThrow(uri, responseContent, retry => PostWithAttachmentFileUpload(suffix, attachmentFile, cancellationToken, retry, parameters), retryCount, cancellationToken);
×
77
                }
78
                return responseContent; //Content is assumed JSON
1✔
79
            }
80
        }
1✔
81

82
        internal async Task<string> Post(string suffix, CancellationToken cancellationToken, int retryCount, params QueryParameter[] parameters)
83
        {
84
            var uri = BuildUri(suffix, parameters);
256✔
85
            var response = await _httpClient.PostAsync(uri, null, cancellationToken);
256✔
86
            var content = await response.Content.ReadAsStringAsync();
256✔
87
            if (response.StatusCode != HttpStatusCode.OK)
256✔
88
            {
89
                return await PreformRetryIfNeededOrThrow(uri, content, retry => Post(suffix, cancellationToken, retry, parameters), retryCount, cancellationToken);
27✔
90
            }
91
            return content; //Content is assumed JSON
242✔
92
        }
255✔
93

94
        internal async Task<T> Put<T>(string suffix, CancellationToken cancellationToken, params QueryParameter[] parameters)
95
        {
96
            string json = await Put(suffix, cancellationToken, 0, parameters);
36✔
97
            var @object = JsonSerializer.Deserialize<T>(json);
36✔
98
            return @object;
36✔
99
        }
36✔
100

101
        internal async Task<string> Put(string suffix, CancellationToken cancellationToken, int retryCount, params QueryParameter[] parameters)
102
        {
103
            var uri = BuildUri(suffix, parameters);
43✔
104
            var response = await _httpClient.PutAsync(uri, null, cancellationToken);
43✔
105
            var responseContent = await response.Content.ReadAsStringAsync();
43✔
106
            if (response.StatusCode != HttpStatusCode.OK)
43✔
107
            {
108
                return await PreformRetryIfNeededOrThrow(uri, responseContent, retry => Put(suffix, cancellationToken, retry, parameters), retryCount, cancellationToken);
5✔
109
            }
110
            return responseContent; //Content is assumed JSON
40✔
111
        }
42✔
112

113
        internal async Task<T> PutWithJsonPayload<T>(string suffix, CancellationToken cancellationToken, string payload, params QueryParameter[] parameters)
114
        {
115
            string json = await PutWithJsonPayload(suffix, cancellationToken, payload, 0, parameters);
38✔
116
            var @object = JsonSerializer.Deserialize<T>(json);
38✔
117
            return @object;
38✔
118
        }
38✔
119

120
        internal async Task<string> PutWithJsonPayload(string suffix, CancellationToken cancellationToken, string payload, int retryCount, params QueryParameter[] parameters)
121
        {
122
            var uri = BuildUri(suffix, parameters);
41✔
123
            var response = await _httpClient.PutAsync(uri, new StringContent(payload, Encoding.UTF8, "application/json"), cancellationToken);
41✔
124
            var responseContent = await response.Content.ReadAsStringAsync();
41✔
125
            if (response.StatusCode != HttpStatusCode.OK)
41✔
126
            {
127
                return await PreformRetryIfNeededOrThrow(uri, responseContent, retry => PutWithJsonPayload(suffix, cancellationToken, payload, retry, parameters), retryCount, cancellationToken);
4✔
128
            }
129
            return responseContent; //Content is assumed JSON
39✔
130
        }
41✔
131

132
        private string FormatExceptionUrlAccordingToClientOptions(string fullUrl)
133
        {
134
            switch (_client.Options.ApiCallExceptionOption)
7!
135
            {
136
                case ApiCallExceptionOption.IncludeUrlAndCredentials:
137
                    return fullUrl;
1✔
138
                case ApiCallExceptionOption.IncludeUrlButMaskCredentials:
139
                    // ReSharper disable StringLiteralTypo
140
                    return fullUrl.Replace($"?key={_apiKey}&token={_token}", "?key=XXXXX&token=XXXXXXXXXX");
5✔
141
                case ApiCallExceptionOption.DoNotIncludeTheUrl:
142
                    return string.Empty.PadLeft(5, 'X');
1✔
143
                default:
144
                    throw new ArgumentOutOfRangeException();
×
145
            }
146
        }
147

148
        private static StringBuilder GetParametersAsString(QueryParameter[] parameters)
149
        {
150
            StringBuilder parameterString = new StringBuilder();
768✔
151
            foreach (var parameter in parameters)
6,114✔
152
            {
153
                parameterString.Append($"&{parameter.Name}={parameter.GetValueAsApiFormattedString()}");
2,289✔
154
            }
155

156
            return parameterString;
768✔
157
        }
158

159
        private Uri BuildUri(string suffix, params QueryParameter[] parameters)
160
        {
161
            return new Uri($@"{BaseUrl}{suffix}?key={_apiKey}&token={_token}" + GetParametersAsString(parameters));
768!
162
        }
163

164
        internal async Task<string> Delete(string suffix, CancellationToken cancellationToken, int retryCount)
165
        {
166
            var uri = BuildUri(suffix);
69✔
167
            var response = await _httpClient.DeleteAsync(uri, cancellationToken);
69✔
168
            var responseContent = await response.Content.ReadAsStringAsync();
69✔
169
            if (response.StatusCode != HttpStatusCode.OK)
69✔
170
            {
171
                return await PreformRetryIfNeededOrThrow(uri, responseContent, retry => Delete(suffix, cancellationToken, retry), retryCount, cancellationToken);
43✔
172
            }
173
            return null;
47✔
174
        }
68✔
175

176
        private async Task<string> PreformRetryIfNeededOrThrow(Uri uri, string responseContent, Func<int,Task<string>> toRetry, int retryCount, CancellationToken cancellationToken)
177
        {
178
            if (responseContent.Contains("API_TOKEN_LIMIT_EXCEEDED") && retryCount <= _client.Options.MaxRetryCountForTokenLimitExceeded)
97✔
179
            {
180
                await Task.Delay(TimeSpan.FromSeconds(_client.Options.DelayInSecondsToWaitInTokenLimitExceededRetry), cancellationToken);
90✔
181
                retryCount++;
90✔
182
                return await toRetry(retryCount);
90✔
183
            }
184
            throw new TrelloApiException(responseContent, FormatExceptionUrlAccordingToClientOptions(uri.AbsoluteUri)); //Content is assumed Error Message       
7✔
185
        }
90✔
186
    }
187
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc