diff --git a/Nexmo.Api/Account.cs b/Nexmo.Api/Account.cs index e001098b4..457e144f0 100644 --- a/Nexmo.Api/Account.cs +++ b/Nexmo.Api/Account.cs @@ -106,7 +106,7 @@ public class Number /// Balance data public static Balance GetBalance(Credentials credentials = null) { - return ApiRequest.DoRequest(ApiRequest.GetBaseUriFor(typeof(Account), + return ApiRequest.DoGetRequest(ApiRequest.GetBaseUriFor(typeof(Account), "/account/get-balance"), // TODO: using this method sig allows us to have the api auth injected at the expense of opaque code here new Dictionary(), @@ -131,7 +131,7 @@ public static Pricing GetPricing(string country, string type = null, Credentials parameters.Add("type", type); } - return ApiRequest.DoRequest(ApiRequest.GetBaseUriFor(typeof(Account), + return ApiRequest.DoGetRequest(ApiRequest.GetBaseUriFor(typeof(Account), "/account/get-pricing/outbound/"), parameters, credentials); @@ -145,7 +145,7 @@ public static Pricing GetPrefixPricing(string prefix, string type, Credentials c { "type", type } }; - return ApiRequest.DoRequest(ApiRequest.GetBaseUriFor(typeof(Account), + return ApiRequest.DoGetRequest(ApiRequest.GetBaseUriFor(typeof(Account), "/account/get-prefix-pricing/outbound/"), parameters, credentials); @@ -169,7 +169,7 @@ public static Settings SetSettings(string newsecret = null, string httpMoCallbac if (null != httpDrCallbackurlCom) parameters.Add("drCallBackUrl", httpDrCallbackurlCom); - return ApiRequest.DoPostRequest(ApiRequest.GetBaseUriFor(typeof(Account), "/account/settings"), parameters, credentials); + return ApiRequest.DoPostRequestWithUrlContent(ApiRequest.GetBaseUriFor(typeof(Account), "/account/settings"), parameters, credentials); } /// @@ -179,7 +179,7 @@ public static Settings SetSettings(string newsecret = null, string httpMoCallbac /// (Optional) Overridden credentials for only this request public static void TopUp(string transaction, Credentials credentials = null) { - ApiRequest.DoRequest(ApiRequest.GetBaseUriFor(typeof(Account), "/account/top-up"), new Dictionary + ApiRequest.DoGetRequest(ApiRequest.GetBaseUriFor(typeof(Account), "/account/top-up"), new Dictionary { {"trx", transaction} }, @@ -206,7 +206,7 @@ public static NumbersResponse GetNumbers(Credentials credentials = null) /// public static NumbersResponse GetNumbers(NumbersRequest request, Credentials credentials = null) { - return ApiRequest.DoRequest(ApiRequest.GetBaseUriFor(typeof(Account), "/account/numbers"), request, credentials); + return ApiRequest.DoGetRequest(ApiRequest.GetBaseUriFor(typeof(Account), "/account/numbers"), request, ApiRequest.AuthType.Query, credentials); } } } \ No newline at end of file diff --git a/Nexmo.Api/ApiSecret.cs b/Nexmo.Api/ApiSecret.cs index 00b3d3c3a..ccb4b4308 100644 --- a/Nexmo.Api/ApiSecret.cs +++ b/Nexmo.Api/ApiSecret.cs @@ -36,7 +36,7 @@ public class SecretRequest /// List of secrets public static List ListSecrets(string apiKey, Credentials creds = null) { - return ApiRequest.DoRequest>(ApiRequest.GetBaseUriFor(typeof(ApiSecret), + return ApiRequest.DoGetRequest>(ApiRequest.GetBaseUriFor(typeof(ApiSecret), $"/accounts/{apiKey}/secrets"), // TODO: using this method sig allows us to have the api auth injected at the expense of opaque code here new Dictionary(), @@ -51,7 +51,7 @@ public static List ListSecrets(string apiKey, Credentials creds = null) /// The secret public static Secret GetSecret(string apiKey, string secretId, Credentials creds = null) { - return ApiRequest.DoRequest(ApiRequest.GetBaseUriFor(typeof(ApiSecret), + return ApiRequest.DoGetRequest(ApiRequest.GetBaseUriFor(typeof(ApiSecret), $"/accounts/{apiKey}/secrets/{secretId}"), // TODO: using this method sig allows us to have the api auth injected at the expense of opaque code here new Dictionary(), @@ -72,7 +72,7 @@ public static Secret GetSecret(string apiKey, string secretId, Credentials creds /// The created secret public static Secret CreateSecret(string apiKey, string newSecret, Credentials creds = null) { - var response = ApiRequest.DoRequest("POST", ApiRequest.GetBaseUriFor(typeof(ApiSecret), $"/accounts/{apiKey}/secrets"), new SecretRequest { Secret = newSecret }, ApiRequest.AuthType.Basic, creds); + var response = ApiRequest.DoRequestWithJsonContent("POST", ApiRequest.GetBaseUriFor(typeof(ApiSecret), $"/accounts/{apiKey}/secrets"), new SecretRequest { Secret = newSecret }, ApiRequest.AuthType.Basic, creds); return JsonConvert.DeserializeObject(response.JsonResponse); } @@ -84,7 +84,7 @@ public static Secret CreateSecret(string apiKey, string newSecret, Credentials c /// ID of the API Secret public static bool DeleteSecret(string apiKey, string secretId, Credentials creds = null) { - var response = ApiRequest.DoRequest("DELETE", ApiRequest.GetBaseUriFor(typeof(ApiSecret), + var response = ApiRequest.DoRequestWithJsonContent("DELETE", ApiRequest.GetBaseUriFor(typeof(ApiSecret), $"/accounts/{apiKey}/secrets/{secretId}"), null, ApiRequest.AuthType.Basic, creds); return response.Status == HttpStatusCode.NoContent; diff --git a/Nexmo.Api/Application.cs b/Nexmo.Api/Application.cs index be90dd52b..d5b273fb3 100644 --- a/Nexmo.Api/Application.cs +++ b/Nexmo.Api/Application.cs @@ -127,7 +127,7 @@ public static List List(int PageSize = 10, int PageIndex = { return new List { - ApiRequest.DoRequest(ApiRequest.GetBaseUriFor(typeof(Application), + ApiRequest.DoGetRequest(ApiRequest.GetBaseUriFor(typeof(Application), $"/v1/applications/{AppId}"), // TODO: using this method sig allows us to have the api auth injected at the expense of opaque code here new Dictionary(), @@ -135,7 +135,7 @@ public static List List(int PageSize = 10, int PageIndex = }; } - return ApiRequest.DoRequest(ApiRequest.GetBaseUriFor(typeof(Application), "/v1/applications"), + return ApiRequest.DoGetRequest(ApiRequest.GetBaseUriFor(typeof(Application), "/v1/applications"), new Dictionary { { "page_size", PageSize.ToString()}, @@ -154,7 +154,7 @@ public static List List(int PageSize = 10, int PageIndex = public static ApplicationResponse Update(ApplicationRequest request, Credentials creds = null) { var sb = ApiRequest.GetQueryStringBuilderFor(request, ApiRequest.AuthType.Query); - return ApiRequest.DoPutRequest(ApiRequest.GetBaseUriFor(typeof(Application), + return ApiRequest.DoPutRequestWithUrlContent(ApiRequest.GetBaseUriFor(typeof(Application), $"/v1/applications/{request.id}?{sb}"), null, creds); } @@ -167,7 +167,7 @@ public static ApplicationResponse Update(ApplicationRequest request, Credentials public static bool Delete(string appId, Credentials creds = null) { var sb = ApiRequest.GetQueryStringBuilderFor(new object(), ApiRequest.AuthType.Query); - var response = ApiRequest.DoDeleteRequest(ApiRequest.GetBaseUriFor(typeof(Application), + var response = ApiRequest.DoDeleteRequestWithUrlContent(ApiRequest.GetBaseUriFor(typeof(Application), $"/v1/applications/{appId}?{sb}"), null, creds); return response.Status == HttpStatusCode.NoContent; diff --git a/Nexmo.Api/ApplicationV2.cs b/Nexmo.Api/ApplicationV2.cs index 07f4f153b..5cfc49f67 100644 --- a/Nexmo.Api/ApplicationV2.cs +++ b/Nexmo.Api/ApplicationV2.cs @@ -181,7 +181,7 @@ public class ApplicationV2 /// public static AppResponse Create(AppRequest request, Credentials credentials = null) { - var response = ApiRequest.DoRequest("POST",ApiRequest.GetBaseUriFor(typeof(ApplicationV2), "/v2/applications"), request, ApiRequest.AuthType.Basic, credentials); + var response = ApiRequest.DoRequestWithJsonContent("POST",ApiRequest.GetBaseUriFor(typeof(ApplicationV2), "/v2/applications"), request, ApiRequest.AuthType.Basic, credentials); return JsonConvert.DeserializeObject(response.JsonResponse); } @@ -194,7 +194,7 @@ public static AppResponse Create(AppRequest request, Credentials credentials = n /// public static AppResponse Get(string appId, Credentials credentials = null) { - return ApiRequest.DoRequest(ApiRequest.GetBaseUriFor(typeof(ApplicationV2), $"/v2/applications/{appId}"), ApiRequest.AuthType.Query, credentials); + return ApiRequest.DoGetRequest(ApiRequest.GetBaseUriFor(typeof(ApplicationV2), $"/v2/applications/{appId}"), ApiRequest.AuthType.Query, credentials); } /// @@ -208,7 +208,7 @@ public static AppResponse Get(string appId, Credentials credentials = null) public static List List(int pageSize = 10, int page = 0, Credentials credentials = null) { var filter = new AppListFilter() { page = page, page_size = pageSize }; - return ApiRequest.DoRequest(ApiRequest.GetBaseUriFor(typeof(ApplicationV2), "/v2/applications"), filter, ApiRequest.AuthType.Basic, credentials)._embedded.Applications; + return ApiRequest.DoGetRequest(ApiRequest.GetBaseUriFor(typeof(ApplicationV2), "/v2/applications"), filter, ApiRequest.AuthType.Basic, credentials)._embedded.Applications; } @@ -226,7 +226,7 @@ public static List List() /// public static AppResponse Update(AppRequest request, Credentials credentials = null) { - var response = ApiRequest.DoRequest("PUT",ApiRequest.GetBaseUriFor(typeof(ApplicationV2), + var response = ApiRequest.DoRequestWithJsonContent("PUT",ApiRequest.GetBaseUriFor(typeof(ApplicationV2), $"/v2/applications/{request.Id}"), request, ApiRequest.AuthType.Basic, credentials); return JsonConvert.DeserializeObject(response.JsonResponse); @@ -240,7 +240,7 @@ public static AppResponse Update(AppRequest request, Credentials credentials = n /// public static bool Delete(string appId, Credentials credentials = null) { - var response = ApiRequest.DoRequest("DELETE",ApiRequest.GetBaseUriFor(typeof(ApplicationV2), + var response = ApiRequest.DoRequestWithJsonContent("DELETE",ApiRequest.GetBaseUriFor(typeof(ApplicationV2), $"/v2/applications/{appId}"), null, ApiRequest.AuthType.Basic, credentials); return response.Status == HttpStatusCode.NoContent; diff --git a/Nexmo.Api/Configuration.cs b/Nexmo.Api/Configuration.cs index 0eca0715a..680b59ccc 100644 --- a/Nexmo.Api/Configuration.cs +++ b/Nexmo.Api/Configuration.cs @@ -18,7 +18,7 @@ static Configuration() private Configuration() { - var logger = Api.Logger.LogProvider.GetLogger(LOGGER_CATEGORY); + var logger = Logger.LogProvider.GetLogger(LOGGER_CATEGORY); var builder = new ConfigurationBuilder() .AddInMemoryCollection(new Dictionary { diff --git a/Nexmo.Api/Number.cs b/Nexmo.Api/Number.cs index c628fbb72..f1f9431e9 100644 --- a/Nexmo.Api/Number.cs +++ b/Nexmo.Api/Number.cs @@ -99,7 +99,7 @@ public class SearchResults public static SearchResults ListOwnNumbers(SearchRequest request, Credentials creds = null) { - return ApiRequest.DoRequest(ApiRequest.GetBaseUriFor(typeof(Account), "/account/numbers/"), request, creds); + return ApiRequest.DoGetRequest(ApiRequest.GetBaseUriFor(typeof(Account), "/account/numbers/"), request, ApiRequest.AuthType.Query, creds); } /// /// Retrieve the list of virtual numbers available for a specific country. @@ -109,7 +109,7 @@ public static SearchResults ListOwnNumbers(SearchRequest request, Credentials cr /// public static SearchResults Search(SearchRequest request, Credentials creds = null) { - return ApiRequest.DoRequest(ApiRequest.GetBaseUriFor(typeof(Number), "/number/search/"), request, creds); + return ApiRequest.DoGetRequest(ApiRequest.GetBaseUriFor(typeof(Number), "/number/search/"), request, ApiRequest.AuthType.Query, creds); } /// @@ -121,7 +121,7 @@ public static SearchResults Search(SearchRequest request, Credentials creds = nu /// public static ResponseBase Buy(string country, string number, Credentials creds = null) { - return ApiRequest.DoPostRequest(ApiRequest.GetBaseUriFor(typeof(Number), "/number/buy"), new Dictionary + return ApiRequest.DoPostRequestWithUrlContent(ApiRequest.GetBaseUriFor(typeof(Number), "/number/buy"), new Dictionary { {"country", country}, {"msisdn", number} @@ -149,7 +149,7 @@ public static ResponseBase Update(NumberUpdateCommand cmd, Credentials creds = n /// public static ResponseBase Cancel(string country, string number, Credentials creds = null) { - return ApiRequest.DoPostRequest(ApiRequest.GetBaseUriFor(typeof(Number), "/number/cancel"), new Dictionary + return ApiRequest.DoPostRequestWithUrlContent(ApiRequest.GetBaseUriFor(typeof(Number), "/number/cancel"), new Dictionary { {"country", country}, {"msisdn", number} diff --git a/Nexmo.Api/NumberInsight.cs b/Nexmo.Api/NumberInsight.cs index df736bc53..f200e3bf0 100644 --- a/Nexmo.Api/NumberInsight.cs +++ b/Nexmo.Api/NumberInsight.cs @@ -302,7 +302,7 @@ public static NumberInsightAsyncRequestResponse RequestAsync(NumberInsightAsyncR parameters.Add("ip", request.IPAddress); } - return ApiRequest.DoPostRequest(ApiRequest.GetBaseUriFor(typeof(NumberVerify), "/ni/advanced/async/json"), parameters, creds); + return ApiRequest.DoPostRequestWithUrlContent(ApiRequest.GetBaseUriFor(typeof(NumberVerify), "/ni/advanced/async/json"), parameters, creds); } public class NumberInsightResponseException : Exception diff --git a/Nexmo.Api/NumberVerify.cs b/Nexmo.Api/NumberVerify.cs index 8143c6c66..483d17ae6 100644 --- a/Nexmo.Api/NumberVerify.cs +++ b/Nexmo.Api/NumberVerify.cs @@ -92,7 +92,7 @@ public class VerifyResponse : VerifyResponseBase /// public static VerifyResponse Verify(VerifyRequest request, Credentials creds = null) { - var response = ApiRequest.DoRequest(ApiRequest.GetBaseUriFor(typeof(NumberVerify), "/verify/json"), request, creds); + var response = ApiRequest.DoGetRequest(ApiRequest.GetBaseUriFor(typeof(NumberVerify), "/verify/json"), request, ApiRequest.AuthType.Query, creds); ValidateVerifyResponse(response); return response; } @@ -137,7 +137,7 @@ public class CheckResponse : VerifyResponseBase /// public static CheckResponse Check(CheckRequest request, Credentials creds = null) { - var response = ApiRequest.DoRequest(ApiRequest.GetBaseUriFor(typeof(NumberVerify), "/verify/check/json"), + var response = ApiRequest.DoGetRequest(ApiRequest.GetBaseUriFor(typeof(NumberVerify), "/verify/check/json"), new Dictionary { {"request_id", request.request_id}, @@ -224,7 +224,7 @@ public class CheckObj /// public static SearchResponse Search(SearchRequest request, Credentials creds = null) { - return ApiRequest.DoRequest(ApiRequest.GetBaseUriFor(typeof(NumberVerify), "/verify/search/json"), new Dictionary() + return ApiRequest.DoGetRequest(ApiRequest.GetBaseUriFor(typeof(NumberVerify), "/verify/search/json"), new Dictionary() { {"request_id", request.request_id}, {"request_ids", request.request_ids} @@ -262,7 +262,7 @@ public class ControlResponse : VerifyResponseBase /// public static ControlResponse Control(ControlRequest request, Credentials creds = null) { - var response = ApiRequest.DoRequest(ApiRequest.GetBaseUriFor(typeof(NumberVerify), "/verify/control/json"), request, creds); + var response = ApiRequest.DoGetRequest(ApiRequest.GetBaseUriFor(typeof(NumberVerify), "/verify/control/json"), request, ApiRequest.AuthType.Query, creds); ValidateVerifyResponse(response); return response; } diff --git a/Nexmo.Api/Redact.cs b/Nexmo.Api/Redact.cs index ac2e3c4ba..e15735624 100644 --- a/Nexmo.Api/Redact.cs +++ b/Nexmo.Api/Redact.cs @@ -52,7 +52,7 @@ public RedactRequest(string id, string product, string type) /// public static NexmoResponse RedactTransaction(RedactRequest redactRequest, Credentials creds = null) { - return ApiRequest.DoRequest("POST",ApiRequest.GetBaseUriFor(typeof(Redact), "/v1/redact/transaction"), redactRequest, ApiRequest.AuthType.Basic, creds); + return ApiRequest.DoRequestWithJsonContent("POST",ApiRequest.GetBaseUriFor(typeof(Redact), "/v1/redact/transaction"), redactRequest, ApiRequest.AuthType.Basic, creds); } } } diff --git a/Nexmo.Api/Request/ApiRequest.cs b/Nexmo.Api/Request/ApiRequest.cs index 672157967..adb54ac59 100644 --- a/Nexmo.Api/Request/ApiRequest.cs +++ b/Nexmo.Api/Request/ApiRequest.cs @@ -31,6 +31,11 @@ public enum AuthType private static string _userAgent; + /// + /// Sets the user agent for an HTTP request + /// + /// + /// internal static void SetUserAgent(ref HttpRequestMessage request, Credentials creds) { if (string.IsNullOrEmpty(_userAgent)) @@ -67,6 +72,12 @@ internal static void SetUserAgent(ref HttpRequestMessage request, Credentials cr request.Headers.UserAgent.ParseAdd(_userAgent); } + /// + /// Builds a query string for a get request - if there is a security secret a signature is built for the request and added to the query string + /// + /// + /// + /// private static StringBuilder BuildQueryString(IDictionary parameters, Credentials creds = null) { var apiKey = (creds?.ApiKey ?? Configuration.Instance.Settings["appSettings:Nexmo.api_key"])?.ToLower(); @@ -121,6 +132,11 @@ private static StringBuilder BuildQueryString(IDictionary parame return sb; } + /// + /// extracts parameters from an object into a dictionary + /// + /// + /// internal static Dictionary GetParameters(object parameters) { var paramType = parameters.GetType().GetTypeInfo(); @@ -144,6 +160,12 @@ internal static Dictionary GetParameters(object parameters) return apiParams; } + /// + /// Retrieves the Base URI for a given component and appends the given url to the end of it. + /// + /// + /// + /// internal static Uri GetBaseUriFor(Type component, string url = null) { Uri baseUri; @@ -162,6 +184,13 @@ internal static Uri GetBaseUriFor(Type component, string url = null) return string.IsNullOrEmpty(url) ? baseUri : new Uri(baseUri, url); } + /// + /// Creates a query string for the given parameters - if the auth type is zero the credentials are appended to the end of the query string + /// + /// + /// + /// + /// internal static StringBuilder GetQueryStringBuilderFor(object parameters, AuthType type, Credentials creds = null) { var apiParams = GetParameters(parameters); @@ -188,17 +217,12 @@ internal static StringBuilder GetQueryStringBuilderFor(object parameters, AuthTy /// The URI to GET /// Parameters required by the endpoint (do not include credentials) /// (Optional) Overridden credentials for only this request + /// Thrown if the API encounters a non-zero result /// - public static T DoRequest(Uri uri, Dictionary parameters, Credentials creds = null) + public static T DoGetRequest(Uri uri, Dictionary parameters, Credentials creds = null) { var sb = BuildQueryString(parameters, creds); - return DoRequest(new Uri(uri, "?" + sb), AuthType.Query, creds); - } - - internal static T DoRequest(Uri uri, object parameters, Credentials creds = null) - { - var sb = GetQueryStringBuilderFor(parameters, AuthType.Query, creds); - return DoRequest(new Uri(uri, "?" + sb), AuthType.Query, creds); + return DoGetRequest(new Uri(uri, "?" + sb), AuthType.Query, creds); } /// @@ -208,17 +232,25 @@ internal static T DoRequest(Uri uri, object parameters, Credentials creds = n /// The URI to GET /// Parameters required by the endpoint (do not include credentials) /// (Optional) Overridden credentials for only this request - /// - public static T DoRequest(Uri uri, object parameters, AuthType authType, Credentials creds = null) + /// Thrown if the API encounters a non-zero result + public static T DoGetRequest(Uri uri, object parameters, AuthType authType, Credentials creds = null) { - var sb = GetQueryStringBuilderFor(parameters, authType); + var sb = GetQueryStringBuilderFor(parameters, authType, creds); - return DoRequest(new Uri(uri, "?" + sb), authType, creds); + return DoGetRequest(new Uri(uri, "?" + sb), authType, creds); } - internal static T DoRequest(Uri uri, AuthType authType, Credentials creds) + /// + /// Sends an HTTP GET request to the Nexmo API without any additional parameters + /// + /// + /// + /// + /// + /// Thrown if the API encounters a non-zero result + public static T DoGetRequest(Uri uri, AuthType authType, Credentials creds) { - var logger = Api.Logger.LogProvider.GetLogger(LOGGER_CATEGORY); + var logger = Logger.LogProvider.GetLogger(LOGGER_CATEGORY); var appId = creds?.ApplicationId ?? Configuration.Instance.Settings["appSettings:Nexmo.Application.Id"]; var appKeyPath = creds?.ApplicationKey ?? Configuration.Instance.Settings["appSettings:Nexmo.Application.Key"]; var apiKey = (creds?.ApiKey ?? Configuration.Instance.Settings["appSettings:Nexmo.api_key"])?.ToLower(); @@ -243,21 +275,22 @@ internal static T DoRequest(Uri uri, AuthType authType, Credentials creds) Jwt.CreateToken(appId, appKeyPath)); } logger.LogDebug($"GET {uri}"); - return JsonConvert.DeserializeObject(SendRequest(req).JsonResponse); + return JsonConvert.DeserializeObject(SendHttpRequest(req).JsonResponse); } /// - /// Send a request to the Nexmo API. + /// Send a request to the Nexmo API using the specified HTTP method and the provided parameters. /// Do not include credentials in the parameters object. If you need to override credentials, use the optional Credentials parameter. /// /// HTTP method (POST, PUT, DELETE, etc) /// The URI to communicate with /// Parameters required by the endpoint (do not include credentials) /// (Optional) Overridden credentials for only this request + /// thrown if an error is encountered when talking to the API /// - public static NexmoResponse DoRequest(string method, Uri uri, Dictionary parameters, Credentials creds = null) + public static NexmoResponse DoRequestWithUrlContent(string method, Uri uri, Dictionary parameters, Credentials creds = null) { - var logger = Api.Logger.LogProvider.GetLogger(LOGGER_CATEGORY); + var logger = Logger.LogProvider.GetLogger(LOGGER_CATEGORY); var sb = new StringBuilder(); // if parameters is null, assume that key and secret have been taken care of if (null != parameters) @@ -277,11 +310,18 @@ public static NexmoResponse DoRequest(string method, Uri uri, Dictionary + /// Sends an HttpRequest on to the Nexmo API + /// + /// + /// thrown if an error is encountered when talking to the API + /// + public static NexmoResponse SendHttpRequest(HttpRequestMessage req) { - var logger = Api.Logger.LogProvider.GetLogger(LOGGER_CATEGORY); + var logger = Logger.LogProvider.GetLogger(LOGGER_CATEGORY); var response = Configuration.Instance.Client.SendAsync(req).Result; var stream = response.Content.ReadAsStreamAsync().Result; string json; @@ -302,7 +342,7 @@ public static NexmoResponse SendRequest(HttpRequestMessage req) catch (HttpRequestException exception) { logger.LogError($"FAIL: {response.StatusCode}"); - throw new NexmoHttpRequestException(exception.Message) { StatusCode = response.StatusCode, Json = json }; + throw new NexmoHttpRequestException(exception.Message) { HttpStatusCode = response.StatusCode, Json = json }; } } @@ -315,13 +355,13 @@ public static NexmoResponse SendRequest(HttpRequestMessage req) /// Parameters required by the endpoint (do not include credentials) /// Authorization type used on the API /// (Optional) Overridden credentials for only this request - public static NexmoResponse DoRequest(string method, Uri uri, object payload, AuthType authType, Credentials creds) + /// thrown if an error is encountered when talking to the API + public static NexmoResponse DoRequestWithJsonContent(string method, Uri uri, object payload, AuthType authType, Credentials creds) { var appId = creds?.ApplicationId ?? Configuration.Instance.Settings["appSettings:Nexmo.Application.Id"]; var appKeyPath = creds?.ApplicationKey ?? Configuration.Instance.Settings["appSettings:Nexmo.Application.Key"]; var apiKey = (creds?.ApiKey ?? Configuration.Instance.Settings["appSettings:Nexmo.api_key"])?.ToLower(); - var apiSecret = creds?.ApiSecret ?? Configuration.Instance.Settings["appSettings:Nexmo.api_secret"]; - var logger = Api.Logger.LogProvider.GetLogger(LOGGER_CATEGORY); + var apiSecret = creds?.ApiSecret ?? Configuration.Instance.Settings["appSettings:Nexmo.api_secret"]; var req = new HttpRequestMessage { @@ -352,11 +392,19 @@ public static NexmoResponse DoRequest(string method, Uri uri, object payload, Au req.Content = new ByteArrayContent(data); req.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/json"); - return SendRequest(req); + return SendHttpRequest(req); } - internal static HttpResponseMessage DoRequestJwt(Uri uri, Credentials creds) + + /// + /// Sends a GET request to the Nexmo API using a JWT and returns the full HTTP resonse message + /// this is primarily for pulling a raw stream off an API call -e.g. a recording + /// + /// + /// + /// HttpResponseMessage + public static HttpResponseMessage DoGetRequestWithJwt(Uri uri, Credentials creds) { - var logger = Api.Logger.LogProvider.GetLogger(LOGGER_CATEGORY); + var logger = Logger.LogProvider.GetLogger(LOGGER_CATEGORY); var appId = creds?.ApplicationId ?? Configuration.Instance.Settings["appSettings:Nexmo.Application.Id"]; var appKeyPath = creds?.ApplicationKey ?? Configuration.Instance.Settings["appSettings:Nexmo.Application.Key"]; @@ -373,37 +421,52 @@ internal static HttpResponseMessage DoRequestJwt(Uri uri, Credentials creds) logger.LogDebug($"GET {uri}"); - var sendTask = Configuration.Instance.Client.SendAsync(req); - sendTask.Wait(); + var result = Configuration.Instance.Client.SendAsync(req).Result; - if (!sendTask.Result.IsSuccessStatusCode) + try { - logger.LogError($"FAIL: {sendTask.Result.StatusCode}"); - - if (string.Compare(Configuration.Instance.Settings["appSettings:Nexmo.Api.EnsureSuccessStatusCode"], - "true", StringComparison.OrdinalIgnoreCase) == 0) - { - sendTask.Result.EnsureSuccessStatusCode(); - } + result.EnsureSuccessStatusCode(); + return result; + } + catch (HttpRequestException ex) + { + logger.LogError($"FAIL: {result.StatusCode}"); + throw new NexmoHttpRequestException(ex.Message, ex) { HttpStatusCode = result.StatusCode }; } - return sendTask.Result; + } - internal static T DoPostRequest(Uri uri, object parameters, Credentials creds = null) + /// + /// Sends a Post request to the specified endpoint with the given parameters + /// + /// + /// + /// + /// + /// + public static T DoPostRequest(Uri uri, object parameters, Credentials creds = null) { var apiParams = GetParameters(parameters); - return DoPostRequest(uri, apiParams, creds); + return DoPostRequestWithUrlContent(uri, apiParams, creds); } - internal static T DoPostRequest(Uri uri, Dictionary parameters, Credentials creds = null) + /// + /// Send a Post Request with Url Content + /// + /// + /// + /// + /// + /// + public static T DoPostRequestWithUrlContent(Uri uri, Dictionary parameters, Credentials creds = null) { - var response = DoRequest("POST", uri, parameters, creds); + var response = DoRequestWithUrlContent("POST", uri, parameters, creds); return JsonConvert.DeserializeObject(response.JsonResponse); } - internal static T DoPutRequest(Uri uri, Dictionary parameters, Credentials creds = null) { - var response = DoRequest("PUT", uri, parameters, creds); + public static T DoPutRequestWithUrlContent(Uri uri, Dictionary parameters, Credentials creds = null) { + var response = DoRequestWithUrlContent("PUT", uri, parameters, creds); return JsonConvert.DeserializeObject(response.JsonResponse); } - internal static NexmoResponse DoDeleteRequest(Uri uri, Dictionary parameters, Credentials creds = null) => DoRequest("DELETE", uri, parameters, creds); + public static NexmoResponse DoDeleteRequestWithUrlContent(Uri uri, Dictionary parameters, Credentials creds = null) => DoRequestWithUrlContent("DELETE", uri, parameters, creds); } } \ No newline at end of file diff --git a/Nexmo.Api/Request/NexmoHttpRequestException.cs b/Nexmo.Api/Request/NexmoHttpRequestException.cs index 161f945e6..ce4fdf207 100644 --- a/Nexmo.Api/Request/NexmoHttpRequestException.cs +++ b/Nexmo.Api/Request/NexmoHttpRequestException.cs @@ -10,6 +10,6 @@ public NexmoHttpRequestException() { } public NexmoHttpRequestException(string message) : base(message) { } public NexmoHttpRequestException(string message, Exception inner) : base(message, inner){} public string Json { get; set; } - public HttpStatusCode StatusCode { get; set; } + public HttpStatusCode HttpStatusCode { get; set; } } } diff --git a/Nexmo.Api/Search.cs b/Nexmo.Api/Search.cs index 9e9c44b73..9a8c82888 100644 --- a/Nexmo.Api/Search.cs +++ b/Nexmo.Api/Search.cs @@ -124,7 +124,7 @@ public class SearchRequest /// public static Message GetMessage(string id, Credentials creds = null) { - return ApiRequest.DoRequest(ApiRequest.GetBaseUriFor(typeof(Search), "/search/message"), new Dictionary + return ApiRequest.DoGetRequest(ApiRequest.GetBaseUriFor(typeof(Search), "/search/message"), new Dictionary { {"id", id} }, @@ -139,7 +139,7 @@ public static Message GetMessage(string id, Credentials creds = null) /// public static Messages GetMessages(SearchRequest request, Credentials creds = null) { - return ApiRequest.DoRequest>(ApiRequest.GetBaseUriFor(typeof(Search), "/search/messages"), request, creds); + return ApiRequest.DoGetRequest>(ApiRequest.GetBaseUriFor(typeof(Search), "/search/messages"), request, ApiRequest.AuthType.Query, creds); } /// @@ -150,7 +150,7 @@ public static Messages GetMessages(SearchRequest request, Credentials c /// public static Messages GetRejections(SearchRequest request, Credentials creds = null) { - return ApiRequest.DoRequest>(ApiRequest.GetBaseUriFor(typeof(Search), "/search/rejections"), request, creds); + return ApiRequest.DoGetRequest>(ApiRequest.GetBaseUriFor(typeof(Search), "/search/rejections"), request, ApiRequest.AuthType.Query, creds); } } } diff --git a/Nexmo.Api/ShortCode.cs b/Nexmo.Api/ShortCode.cs index 9ee1b7136..7993f412b 100644 --- a/Nexmo.Api/ShortCode.cs +++ b/Nexmo.Api/ShortCode.cs @@ -38,7 +38,7 @@ public static SMS.SMSResponse RequestTwoFactorAuth(TwoFactorAuthRequest request, { request.pin = new Random().Next(0, 9999); } - var response = ApiRequest.DoRequest(ApiRequest.GetBaseUriFor(typeof(ShortCode), "/sc/us/2fa/json"), request, creds); + var response = ApiRequest.DoGetRequest(ApiRequest.GetBaseUriFor(typeof(ShortCode), "/sc/us/2fa/json"), request, ApiRequest.AuthType.Query, creds); SMS.ValidateSmsResponse(response); return response; } @@ -57,7 +57,7 @@ public static SMS.SMSResponse RequestAlert(AlertRequest request, Dictionary(ApiRequest.GetBaseUriFor(typeof(ShortCode), "/sc/us/alert/json?" + sb), ApiRequest.AuthType.Query, creds); + var response = ApiRequest.DoGetRequest(ApiRequest.GetBaseUriFor(typeof(ShortCode), "/sc/us/alert/json?" + sb), ApiRequest.AuthType.Query, creds); SMS.ValidateSmsResponse(response); return response; } diff --git a/Nexmo.Api/Voice/Call.Stream.cs b/Nexmo.Api/Voice/Call.Stream.cs index b451364ab..96f602b89 100644 --- a/Nexmo.Api/Voice/Call.Stream.cs +++ b/Nexmo.Api/Voice/Call.Stream.cs @@ -25,7 +25,7 @@ public class StreamCommand /// (Optional) Overridden credentials for only this request public static CallCommandResponse BeginStream(string id, StreamCommand cmd, Credentials creds = null) { - var response = ApiRequest.DoRequest("PUT", ApiRequest.GetBaseUriFor(typeof(Call), $"/v1/calls/{id}/stream"), cmd, ApiRequest.AuthType.Bearer, creds); + var response = ApiRequest.DoRequestWithJsonContent("PUT", ApiRequest.GetBaseUriFor(typeof(Call), $"/v1/calls/{id}/stream"), cmd, ApiRequest.AuthType.Bearer, creds); return JsonConvert.DeserializeObject(response.JsonResponse); } @@ -37,7 +37,7 @@ public static CallCommandResponse BeginStream(string id, StreamCommand cmd, Cred /// (Optional) Overridden credentials for only this request public static CallCommandResponse EndStream(string id, Credentials creds = null) { - var response = ApiRequest.DoRequest("DELETE", ApiRequest.GetBaseUriFor(typeof(Call), $"/v1/calls/{id}/stream"), new {}, ApiRequest.AuthType.Bearer, creds); + var response = ApiRequest.DoRequestWithJsonContent("DELETE", ApiRequest.GetBaseUriFor(typeof(Call), $"/v1/calls/{id}/stream"), new {}, ApiRequest.AuthType.Bearer, creds); return JsonConvert.DeserializeObject(response.JsonResponse); } diff --git a/Nexmo.Api/Voice/Call.Talk.cs b/Nexmo.Api/Voice/Call.Talk.cs index 481ee9e1b..9397b3e58 100644 --- a/Nexmo.Api/Voice/Call.Talk.cs +++ b/Nexmo.Api/Voice/Call.Talk.cs @@ -43,7 +43,7 @@ public class DtmfCommand /// (Optional) Overridden credentials for only this request public static CallCommandResponse BeginTalk(string id, TalkCommand cmd, Credentials creds = null) { - var response = ApiRequest.DoRequest("PUT", ApiRequest.GetBaseUriFor(typeof(Call), $"/v1/calls/{id}/talk"), cmd, ApiRequest.AuthType.Bearer, creds); + var response = ApiRequest.DoRequestWithJsonContent("PUT", ApiRequest.GetBaseUriFor(typeof(Call), $"/v1/calls/{id}/talk"), cmd, ApiRequest.AuthType.Bearer, creds); return JsonConvert.DeserializeObject(response.JsonResponse); } @@ -55,7 +55,7 @@ public static CallCommandResponse BeginTalk(string id, TalkCommand cmd, Credenti /// (Optional) Overridden credentials for only this request public static CallCommandResponse EndTalk(string id, Credentials creds = null) { - var response = ApiRequest.DoRequest("DELETE", ApiRequest.GetBaseUriFor(typeof(Call), $"/v1/calls/{id}/talk"), new {}, ApiRequest.AuthType.Bearer, creds); + var response = ApiRequest.DoRequestWithJsonContent("DELETE", ApiRequest.GetBaseUriFor(typeof(Call), $"/v1/calls/{id}/talk"), new {}, ApiRequest.AuthType.Bearer, creds); return JsonConvert.DeserializeObject(response.JsonResponse); } @@ -68,7 +68,7 @@ public static CallCommandResponse EndTalk(string id, Credentials creds = null) /// (Optional) Overridden credentials for only this request public static CallCommandResponse SendDtmf(string id, DtmfCommand cmd, Credentials creds = null) { - var response = ApiRequest.DoRequest("PUT", ApiRequest.GetBaseUriFor(typeof(Call), $"/v1/calls/{id}/dtmf"), cmd, ApiRequest.AuthType.Bearer, creds); + var response = ApiRequest.DoRequestWithJsonContent("PUT", ApiRequest.GetBaseUriFor(typeof(Call), $"/v1/calls/{id}/dtmf"), cmd, ApiRequest.AuthType.Bearer, creds); return JsonConvert.DeserializeObject(response.JsonResponse); } diff --git a/Nexmo.Api/Voice/Call.cs b/Nexmo.Api/Voice/Call.cs index c25087cee..667db1932 100644 --- a/Nexmo.Api/Voice/Call.cs +++ b/Nexmo.Api/Voice/Call.cs @@ -286,7 +286,7 @@ public class CallList /// public static CallResponse Do(CallCommand cmd, Credentials creds = null) { - var response = ApiRequest.DoRequest("POST", ApiRequest.GetBaseUriFor(typeof(Call), "/v1/calls"), cmd, ApiRequest.AuthType.Bearer, creds); + var response = ApiRequest.DoRequestWithJsonContent("POST", ApiRequest.GetBaseUriFor(typeof(Call), "/v1/calls"), cmd, ApiRequest.AuthType.Bearer, creds); return JsonConvert.DeserializeObject(response.JsonResponse); } @@ -298,7 +298,7 @@ public static CallResponse Do(CallCommand cmd, Credentials creds = null) /// public static PaginatedResponse List(SearchFilter filter, Credentials creds = null) { - return ApiRequest.DoRequest>(ApiRequest.GetBaseUriFor(typeof(Call), "/v1/calls"), filter, ApiRequest.AuthType.Bearer, creds); + return ApiRequest.DoGetRequest>(ApiRequest.GetBaseUriFor(typeof(Call), "/v1/calls"), filter, ApiRequest.AuthType.Bearer, creds); } public static PaginatedResponse List() { @@ -315,7 +315,7 @@ public static PaginatedResponse List() /// (Optional) Overridden credentials for only this request public static CallResponse Get(string id, Credentials creds = null) { - return ApiRequest.DoRequest(ApiRequest.GetBaseUriFor(typeof(Call), $"/v1/calls/{id}"), new {}, ApiRequest.AuthType.Bearer, creds); + return ApiRequest.DoGetRequest(ApiRequest.GetBaseUriFor(typeof(Call), $"/v1/calls/{id}"), new {}, ApiRequest.AuthType.Bearer, creds); } /// @@ -326,14 +326,14 @@ public static CallResponse Get(string id, Credentials creds = null) /// (Optional) Overridden credentials for only this request public static CallResponse Edit(string id, CallEditCommand cmd, Credentials creds = null) { - var response = ApiRequest.DoRequest("PUT", ApiRequest.GetBaseUriFor(typeof(Call), $"/v1/calls/{id}"), cmd, ApiRequest.AuthType.Bearer, creds); + var response = ApiRequest.DoRequestWithJsonContent("PUT", ApiRequest.GetBaseUriFor(typeof(Call), $"/v1/calls/{id}"), cmd, ApiRequest.AuthType.Bearer, creds); return JsonConvert.DeserializeObject(response.JsonResponse); } public static CallGetRecordingResponse GetRecording(string url, Credentials creds = null) { - using (var response = ApiRequest.DoRequestJwt(new Uri(url), creds)) + using (var response = ApiRequest.DoGetRequestWithJwt(new Uri(url), creds)) { var readTask = response.Content.ReadAsStreamAsync(); byte[] bytes;