internal Event(IProjectSettings prjSettings, IKeenHttpClientProvider keenHttpClientProvider) { if (null == prjSettings) { throw new ArgumentNullException(nameof(prjSettings), "Project Settings must be provided."); } if (null == keenHttpClientProvider) { throw new ArgumentNullException(nameof(keenHttpClientProvider), "A KeenHttpClient provider must be provided."); } if (string.IsNullOrWhiteSpace(prjSettings.KeenUrl) || !Uri.IsWellFormedUriString(prjSettings.KeenUrl, UriKind.Absolute)) { throw new KeenException( "A properly formatted KeenUrl must be provided via Project Settings."); } var serverBaseUrl = new Uri(prjSettings.KeenUrl); _keenHttpClient = keenHttpClientProvider.GetForUrl(serverBaseUrl); _eventsRelativeUrl = KeenHttpClient.GetRelativeUrl(prjSettings.ProjectId, KeenConstants.EventsResource); _readKey = prjSettings.ReadKey; _writeKey = prjSettings.WriteKey; }
/// <summary> /// Create and send a GET request to the given relative resource using the given key for /// authentication. /// </summary> /// <param name="resource">The relative resource to GET.</param> /// <param name="authKey">The key to use for authenticating this request.</param> /// <returns>The response message.</returns> public Task <HttpResponseMessage> GetAsync(Uri resource, string authKey) { KeenHttpClient.RequireAuthKey(authKey); HttpRequestMessage get = CreateRequest(HttpMethod.Get, resource, authKey); return(_httpClient.SendAsync(get)); }
/// <summary> /// Create and send a DELETE request to the given relative resource using the given key for /// authentication. /// </summary> /// <param name="resource">The relative resource to DELETE.</param> /// <param name="authKey">The key to use for authenticating this request.</param> /// <returns>The response message.</returns> public Task <HttpResponseMessage> DeleteAsync(Uri resource, string authKey) { KeenHttpClient.RequireAuthKey(authKey); HttpRequestMessage delete = CreateRequest(HttpMethod.Delete, resource, authKey); return(_httpClient.SendAsync(delete)); }
internal EventCollection(IProjectSettings prjSettings, IKeenHttpClientProvider keenHttpClientProvider) { if (null == prjSettings) { throw new ArgumentNullException(nameof(prjSettings), "Project Settings must be provided."); } if (null == keenHttpClientProvider) { throw new ArgumentNullException(nameof(keenHttpClientProvider), "A KeenHttpClient provider must be provided."); } if (string.IsNullOrWhiteSpace(prjSettings.KeenUrl) || !Uri.IsWellFormedUriString(prjSettings.KeenUrl, UriKind.Absolute)) { throw new KeenException( "A properly formatted KeenUrl must be provided via Project Settings."); } var serverBaseUrl = new Uri(prjSettings.KeenUrl); _keenHttpClient = keenHttpClientProvider.GetForUrl(serverBaseUrl); _eventsRelativeUrl = KeenHttpClient.GetRelativeUrl(prjSettings.ProjectId, KeenConstants.EventsResource); // TODO : It's possible we may want to change back to dynamically grabbing the keys // from a stored IProjectSettings so client code can lazily assign keys. It creates a // minor potential race condition, but will allow for scenarios like creating a // KeenClient instance with only a master key in order to generate/acquire access keys // to then set as the other keys. Otherwise a new KeenClient must be created or at // least a new instance of the IEventCollection/IEvent/IQueries implementations. _readKey = prjSettings.ReadKey; _writeKey = prjSettings.WriteKey; _masterKey = prjSettings.MasterKey; }
private async Task <HttpResponseMessage> DispatchWithContentAsync(HttpMethod httpMethod, Uri resource, string authKey, string content) { KeenHttpClient.RequireAuthKey(authKey); if (string.IsNullOrWhiteSpace(content)) { // Technically, we can encode an empty string or whitespace, but why? For now // we use GET for querying. If we ever need to POST with no content, we should // reorganize the logic below to never create/set the content stream. throw new ArgumentNullException(nameof(content), "Unexpected empty content."); } // If we switch PCL profiles, instead use MediaTypeFormatters (or ObjectContent<T>)?, // like here?: https://msdn.microsoft.com/en-us/library/system.net.http.httpclientextensions.putasjsonasync(v=vs.118).aspx using (var contentStream = new StreamContent(new MemoryStream(Encoding.UTF8.GetBytes(content)))) { // TODO : Make sure this is the same as Add("content-type", "application/json") contentStream.Headers.ContentType = new MediaTypeHeaderValue(KeenHttpClient.JSON_CONTENT_TYPE); HttpRequestMessage request = CreateRequest(httpMethod, resource, authKey); request.Content = contentStream; return(await _httpClient.SendAsync(request).ConfigureAwait(false)); // TODO : Should we do the KeenUtil.CheckApiErrorCode() here? // TODO : Should we check the if (!responseMsg.IsSuccessStatusCode) here too? // TODO : If we centralize error checking in this class we could have variations // of these helpers that return string or JToken or JArray or JObject. It might // also be nice for those options to optionally hand back the raw // HttpResponseMessage in an out param if desired? // TODO : Use CallerMemberNameAttribute to print error messages? // http://stackoverflow.com/questions/3095696/how-do-i-get-the-calling-method-name-and-type-using-reflection?noredirect=1&lq=1 } }
// NOTE : BaseUrl should have a final slash or the last Uri part is discarded. Also, // relative urls can *not* start with a slash. // Not exposed so that 3rd party code doesn't accidentally build a KeenHttpClient without // our handlers installed, which wouldn't be ideal. private static KeenHttpClient Create(Uri baseUrl, IHttpClientProvider httpClientProvider, Func <HttpMessageHandler> getHandlerChain) { if (!baseUrl.IsAbsoluteUri) { throw new ArgumentException( "The given base Url must be in the form of an absolute Uri.", nameof(baseUrl)); } // Delay actual creation of the handler chain by passing in a Func<> to create it. This // way if HttpClient already exists, we won't bother creating/modifying handlers. var httpClient = httpClientProvider.GetOrCreateForUrl( baseUrl, getHandlerChain, KeenHttpClientFactory.DEFAULT_HEADERS); var newClient = new KeenHttpClient(httpClient); return(newClient); }