/// <summary> /// Provides all logic for constructing a new HttpRequestMessage. /// At this point, all information for querying the service is known. Here, it is simply /// mapped into the a HttpRequestMessage. /// </summary> /// <param name="method">The http verb.</param> /// <param name="path">The target path (or resource).</param> /// <param name="options">The additional request options.</param> /// <param name="configuration">A per-request configuration object. It is assumed that any merge with /// GlobalConfiguration has been done before calling this method.</param> /// <returns>[private] A new HttpRequestMessage instance.</returns> /// <exception cref="ArgumentNullException"></exception> private HttpRequestMessage NewRequest( HttpMethod method, string path, RequestOptions options, IReadableConfiguration configuration) { if (path == null) { throw new ArgumentNullException("path"); } if (options == null) { throw new ArgumentNullException("options"); } if (configuration == null) { throw new ArgumentNullException("configuration"); } WebRequestPathBuilder builder = new WebRequestPathBuilder(_baseUrl, path); builder.AddPathParameters(options.PathParameters); builder.AddQueryParameters(options.QueryParameters); HttpRequestMessage request = new HttpRequestMessage(method, builder.GetFullUri()); if (configuration.UserAgent != null) { request.Headers.TryAddWithoutValidation("User-Agent", configuration.UserAgent); } if (configuration.DefaultHeaders != null) { foreach (var headerParam in configuration.DefaultHeaders) { request.Headers.Add(headerParam.Key, headerParam.Value); } } if (options.HeaderParameters != null) { foreach (var headerParam in options.HeaderParameters) { foreach (var value in headerParam.Value) { // Todo make content headers actually content headers request.Headers.TryAddWithoutValidation(headerParam.Key, value); } } } List <Tuple <HttpContent, string, string> > contentList = new List <Tuple <HttpContent, string, string> >(); string contentType = null; if (options.HeaderParameters != null && options.HeaderParameters.ContainsKey("Content-Type")) { var contentTypes = options.HeaderParameters["Content-Type"]; contentType = contentTypes.FirstOrDefault(); } if (contentType == "multipart/form-data") { request.Content = PrepareMultipartFormDataContent(options); } else if (contentType == "application/x-www-form-urlencoded") { request.Content = new FormUrlEncodedContent(options.FormParameters); } else { if (options.Data != null) { if (options.Data is FileParameter fp) { contentType = contentType ?? "application/octet-stream"; var streamContent = new StreamContent(fp.Content); streamContent.Headers.ContentType = new MediaTypeHeaderValue(contentType); request.Content = streamContent; } else { var serializer = new CustomJsonCodec(SerializerSettings, configuration); request.Content = new StringContent(serializer.Serialize(options.Data), new UTF8Encoding(), "application/json"); } } } // TODO provide an alternative that allows cookies per request instead of per API client if (options.Cookies != null && options.Cookies.Count > 0) { request.Properties["CookieContainer"] = options.Cookies; } return(request); }
/// <summary> /// Provides all logic for constructing a new HttpRequestMessage. /// At this point, all information for querying the service is known. Here, it is simply /// mapped into the a HttpRequestMessage. /// </summary> /// <param name="method">The http verb.</param> /// <param name="path">The target path (or resource).</param> /// <param name="options">The additional request options.</param> /// <param name="configuration">A per-request configuration object. It is assumed that any merge with /// GlobalConfiguration has been done before calling this method.</param> /// <returns>[private] A new HttpRequestMessage instance.</returns> /// <exception cref="ArgumentNullException"></exception> private HttpRequestMessage NewRequest( HttpMethod method, String path, RequestOptions options, IReadableConfiguration configuration) { if (path == null) { throw new ArgumentNullException("path"); } if (options == null) { throw new ArgumentNullException("options"); } if (configuration == null) { throw new ArgumentNullException("configuration"); } WebRequestPathBuilder builder = new WebRequestPathBuilder(_baseUrl, path); builder.AddPathParameters(options.PathParameters); // In case of POST or PUT pass query parameters in request body if (method != HttpMethod.Post && method != HttpMethod.Put) { builder.AddQueryParameters(options.QueryParameters); } HttpRequestMessage request = new HttpRequestMessage(method, builder.GetFullUri()); if (configuration.DefaultHeaders != null) { foreach (var headerParam in configuration.DefaultHeaders) { request.Headers.Add(headerParam.Key, headerParam.Value); } } if (options.HeaderParameters != null) { foreach (var headerParam in options.HeaderParameters) { foreach (var value in headerParam.Value) { // Todo make content headers actually content headers request.Headers.TryAddWithoutValidation(headerParam.Key, value); } } } List <Tuple <HttpContent, string, string> > contentList = new List <Tuple <HttpContent, string, string> >(); if (options.FormParameters != null && options.FormParameters.Count > 0) { contentList.Add(new Tuple <HttpContent, string, string>(new FormUrlEncodedContent(options.FormParameters), null, null)); } if (options.Data != null) { var serializer = new CustomJsonCodec(SerializerSettings, configuration); contentList.Add( new Tuple <HttpContent, string, string>(new StringContent(serializer.Serialize(options.Data), new UTF8Encoding(), "application/json"), null, null)); } if (options.FileParameters != null && options.FileParameters.Count > 0) { foreach (var fileParam in options.FileParameters) { var bytes = ClientUtils.ReadAsBytes(fileParam.Value); var fileStream = fileParam.Value as FileStream; contentList.Add(new Tuple <HttpContent, string, string>(new ByteArrayContent(bytes), fileParam.Key, fileStream?.Name ?? "no_file_name_provided")); } } if (contentList.Count > 1) { string boundary = "---------" + Guid.NewGuid().ToString().ToUpperInvariant(); var multipartContent = new MultipartFormDataContent(boundary); foreach (var content in contentList) { if (content.Item2 != null) { multipartContent.Add(content.Item1, content.Item2, content.Item3); } else { multipartContent.Add(content.Item1); } } request.Content = multipartContent; } else { request.Content = contentList.FirstOrDefault()?.Item1; } // TODO provide an alternative that allows cookies per request instead of per API client if (options.Cookies != null && options.Cookies.Count > 0) { request.Properties["CookieContainer"] = options.Cookies; } return(request); }