private static async Task <MultipartFormDataContent> CreateContent <T>(IContentSerializer contentSerializer, string projectAlias, object data,
                                                                               IDictionary <string, MultipartItem> files)
        {
            var content = new MultipartFormDataContent
            {
                Headers =
                {
                    { Constants.Headers.ProjectAlias, projectAlias }
                },
            };
            var postData = await contentSerializer.SerializeAsync(data).ConfigureAwait(false);

            content.Add(postData, "content");
            foreach (var file in files)
            {
                content.Add(file.Value.ToContent(), file.Key, file.Value.FileName);
            }
            return(content);
        }
예제 #2
0
        public static string ToQueryString(this object model)
        {
            var serialized   = serializer.SerializeAsync <object>(model).Result;
            var deserialized = serializer.DeserializeAsync <Dictionary <string, string> >(serialized).Result;
            var result       = String.Empty;

            var first = true;

            foreach (var pair in deserialized)
            {
                if (first)
                {
                    first   = false;
                    result += "?";
                }
                else
                {
                    result += "&";
                }
                result += pair.Key + "=" + pair.Value;
            }
            return(result);
        }
예제 #3
0
        Func <object[], Task <HttpRequestMessage> > BuildRequestFactoryForMethod(RestMethodInfo restMethod, string basePath, bool paramsContainsCancellationToken)
        {
            return(async paramList =>
            {
                // make sure we strip out any cancelation tokens
                if (paramsContainsCancellationToken)
                {
                    paramList = paramList.Where(o => o == null || o.GetType() != typeof(CancellationToken)).ToArray();
                }

                var ret = new HttpRequestMessage
                {
                    Method = restMethod.HttpMethod
                };

                // set up multipart content
                MultipartFormDataContent multiPartContent = null;
                if (restMethod.IsMultipart)
                {
                    multiPartContent = new MultipartFormDataContent("----MyGreatBoundary");
                    ret.Content = multiPartContent;
                }

                var urlTarget = (basePath == "/" ? string.Empty : basePath) + restMethod.RelativePath;
                var queryParamsToAdd = new List <KeyValuePair <string, string> >();
                var headersToAdd = new Dictionary <string, string>(restMethod.Headers);

                for (var i = 0; i < paramList.Length; i++)
                {
                    // if part of REST resource URL, substitute it in
                    if (restMethod.ParameterMap.ContainsKey(i))
                    {
                        urlTarget = Regex.Replace(
                            urlTarget,
                            "{" + restMethod.ParameterMap[i] + "}",
                            Uri.EscapeDataString(settings.UrlParameterFormatter
                                                 .Format(paramList[i], restMethod.ParameterInfoMap[i]) ?? string.Empty),
                            RegexOptions.IgnoreCase | RegexOptions.CultureInvariant);
                        continue;
                    }

                    // if marked as body, add to content
                    if (restMethod.BodyParameterInfo != null && restMethod.BodyParameterInfo.Item3 == i)
                    {
                        if (paramList[i] is HttpContent httpContentParam)
                        {
                            ret.Content = httpContentParam;
                        }
                        else if (paramList[i] is Stream streamParam)
                        {
                            ret.Content = new StreamContent(streamParam);
                        }
                        // Default sends raw strings
                        else if (restMethod.BodyParameterInfo.Item1 == BodySerializationMethod.Default &&
                                 paramList[i] is string stringParam)
                        {
                            ret.Content = new StringContent(stringParam);
                        }
                        else
                        {
                            switch (restMethod.BodyParameterInfo.Item1)
                            {
                            case BodySerializationMethod.UrlEncoded:
                                ret.Content = paramList[i] is string str ? (HttpContent) new StringContent(Uri.EscapeDataString(str), Encoding.UTF8, "application/x-www-form-urlencoded") :  new FormUrlEncodedContent(new FormValueMultimap(paramList[i], settings));
                                break;

                            case BodySerializationMethod.Default:
#pragma warning disable CS0618 // Type or member is obsolete
                            case BodySerializationMethod.Json:
#pragma warning restore CS0618 // Type or member is obsolete
                            case BodySerializationMethod.Serialized:
                                var content = await serializer.SerializeAsync(paramList[i]).ConfigureAwait(false);

                                switch (restMethod.BodyParameterInfo.Item2)
                                {
                                case false:
                                    ret.Content = new PushStreamContent(
                                        async(stream, _, __) => {
                                        using (stream)
                                        {
                                            await content.CopyToAsync(stream).ConfigureAwait(false);
                                        }
                                    }, content.Headers.ContentType);
                                    break;

                                case true:
                                    ret.Content = content;
                                    break;
                                }

                                break;
                            }
                        }

                        continue;
                    }

                    // if header, add to request headers
                    if (restMethod.HeaderParameterMap.ContainsKey(i))
                    {
                        headersToAdd[restMethod.HeaderParameterMap[i]] = paramList[i]?.ToString();
                        continue;
                    }

                    // ignore nulls
                    if (paramList[i] == null)
                    {
                        continue;
                    }

                    // for anything that fell through to here, if this is not
                    // a multipart method, add the parameter to the query string
                    if (!restMethod.IsMultipart)
                    {
                        var attr = restMethod.ParameterInfoMap[i].GetCustomAttribute <QueryAttribute>() ?? new QueryAttribute();
                        if (DoNotConvertToQueryMap(paramList[i]))
                        {
                            if (paramList[i] is IEnumerable paramValues)
                            {
                                switch (attr.CollectionFormat)
                                {
                                case CollectionFormat.Multi:
                                    foreach (var paramValue in paramValues)
                                    {
                                        queryParamsToAdd.Add(new KeyValuePair <string, string>(
                                                                 restMethod.QueryParameterMap[i],
                                                                 settings.UrlParameterFormatter.Format(paramValue, restMethod.ParameterInfoMap[i])));
                                    }
                                    continue;

                                case CollectionFormat.Csv:
                                case CollectionFormat.Ssv:
                                case CollectionFormat.Tsv:
                                case CollectionFormat.Pipes:
                                    var delimiter = attr.CollectionFormat == CollectionFormat.Csv ?  ","
                                            : attr.CollectionFormat == CollectionFormat.Ssv ? " "
                                            : attr.CollectionFormat == CollectionFormat.Tsv ? "\t" : "|";

                                    var formattedValues = paramValues
                                                          .Cast <object>()
                                                          .Select(v => settings.UrlParameterFormatter.Format(v, restMethod.ParameterInfoMap[i]));

                                    queryParamsToAdd.Add(new KeyValuePair <string, string>(
                                                             restMethod.QueryParameterMap[i],
                                                             string.Join(delimiter, formattedValues)));
                                    continue;
                                }
                            }
                            queryParamsToAdd.Add(new KeyValuePair <string, string>(restMethod.QueryParameterMap[i], settings.UrlParameterFormatter.Format(paramList[i], restMethod.ParameterInfoMap[i])));
                        }
                        else
                        {
                            foreach (var kvp in BuildQueryMap(paramList[i], attr.Delimiter))
                            {
                                var path = !string.IsNullOrWhiteSpace(attr.Prefix) ? $"{attr.Prefix}{attr.Delimiter}{kvp.Key}" : kvp.Key;
                                queryParamsToAdd.Add(new KeyValuePair <string, string>(path, settings.UrlParameterFormatter.Format(kvp.Value, restMethod.ParameterInfoMap[i])));
                            }
                        }

                        continue;
                    }

                    // we are in a multipart method, add the part to the content
                    // the parameter name should be either the attachment name or the parameter name (as fallback)
                    string itemName;
                    string parameterName;

                    if (!restMethod.AttachmentNameMap.TryGetValue(i, out var attachment))
                    {
                        itemName = restMethod.QueryParameterMap[i];
                        parameterName = itemName;
                    }
                    else
                    {
                        itemName = attachment.Item1;
                        parameterName = attachment.Item2;
                    }

                    // Check to see if it's an IEnumerable
                    var itemValue = paramList[i];
                    var enumerable = itemValue as IEnumerable <object>;
                    var typeIsCollection = enumerable != null;

                    if (typeIsCollection)
                    {
                        foreach (var item in enumerable)
                        {
                            await AddMultipartItemAsync(multiPartContent, itemName, parameterName, item).ConfigureAwait(false);
                        }
                    }
                    else
                    {
                        await AddMultipartItemAsync(multiPartContent, itemName, parameterName, itemValue).ConfigureAwait(false);
                    }
                }

                // NB: We defer setting headers until the body has been
                // added so any custom content headers don't get left out.
                if (headersToAdd.Count > 0)
                {
                    // We could have content headers, so we need to make
                    // sure we have an HttpContent object to add them to,
                    // provided the HttpClient will allow it for the method
                    if (ret.Content == null && !bodylessMethods.Contains(ret.Method))
                    {
                        ret.Content = new ByteArrayContent(new byte[0]);
                    }

                    foreach (var header in headersToAdd)
                    {
                        SetHeader(ret, header.Key, header.Value);
                    }
                }

                // NB: The URI methods in .NET are dumb. Also, we do this
                // UriBuilder business so that we preserve any hardcoded query
                // parameters as well as add the parameterized ones.
                var uri = new UriBuilder(new Uri(new Uri("http://api"), urlTarget));
                var query = HttpUtility.ParseQueryString(uri.Query ?? "");
                foreach (var key in query.AllKeys)
                {
                    queryParamsToAdd.Insert(0, new KeyValuePair <string, string>(key, query[key]));
                }

                if (queryParamsToAdd.Any())
                {
                    var pairs = queryParamsToAdd.Where(x => x.Key != null && x.Value != null)
                                .Select(x => Uri.EscapeDataString(x.Key) + "=" + Uri.EscapeDataString(x.Value));
                    uri.Query = string.Join("&", pairs);
                }
                else
                {
                    uri.Query = null;
                }

                ret.RequestUri = new Uri(uri.Uri.GetComponents(UriComponents.PathAndQuery, UriFormat.UriEscaped), UriKind.Relative);
                return ret;
            });
        }