public IEnumerable <string> Autocomplete(NuGetSearchTerm autocompleteSearchTerm, RequestWrapper request, WildcardPattern acceptedPattern, bool allowPrerelease)
        {
            try
            {
                request.Debug(Messages.DebugInfoCallMethod3, "NuGetAutoCompleteFeed3", "Autocomplete", autocompleteSearchTerm.ToString());
                return(base.Execute <IEnumerable <string> >((baseUrl) =>
                {
                    HttpQueryBuilder qb = new HttpQueryBuilder();
                    if (autocompleteSearchTerm.Term == NuGetSearchTerm.NuGetSearchTermType.Id)
                    {
                        qb.Add(Constants.PackageIdQueryParam, autocompleteSearchTerm.Text);
                    }
                    else if (autocompleteSearchTerm.Term == NuGetSearchTerm.NuGetSearchTermType.AutoComplete)
                    {
                        qb.Add(Constants.QueryQueryParam, autocompleteSearchTerm.Text);
                    }

                    if (allowPrerelease)
                    {
                        qb.Add(Constants.PrereleaseQueryParam, "true");
                    }

                    qb.Add(Constants.TakeQueryParam, Constants.SearchPageCount)
                    .Add(Constants.SemVerLevelQueryParam, Constants.SemVerLevel2);

                    return NuGetWebUtility.GetResults <dynamic, string>(request, (dynamic root) =>
                    {
                        long res = -1;
                        if (root.HasProperty("totalhits"))
                        {
                            res = root.totalhits;
                            request.Debug(Resources.Messages.TotalPackagesDiscovered, res);
                        }
                        else
                        {
                            request.Warning(Resources.Messages.JsonSchemaMismatch, "totalhits");
                            request.Debug(Resources.Messages.JsonObjectDump, DynamicJsonParser.Serialize(root));
                        }

                        return res;
                    }, (dynamic root) => GetAutoCompleteResults(root, autocompleteSearchTerm, acceptedPattern), (long resultsToSkip) =>
                    {
                        if (resultsToSkip > 0)
                        {
                            HttpQueryBuilder currentQb = qb.CloneAdd(Constants.SkipQueryParam, resultsToSkip.ToString());
                            return currentQb.AddQueryString(baseUrl);
                        }

                        return qb.AddQueryString(baseUrl);
                    }, (string content) =>
                    {
                        return DynamicJsonParser.Parse(content);
                    }, Constants.SearchPageCountInt);
                }));
            }
            finally
            {
                request.Debug(Messages.DebugInfoReturnCall, "NuGetAutoCompleteFeed3", "Autocomplete");
            }
        }
        private IEnumerable <IPackage> SearchPackagesWithBackup(string baseUrl, HttpQueryBuilder qb, RequestWrapper request, NuGetSearchContext searchContext, NuGetSearchTerm searchTerm)
        {
            // First execute the actual search
            HashSet <string> foundPackageIds = new HashSet <string>();

            return(NuGetWebUtility.GetResults <dynamic, PackageBase>(request, (dynamic root) =>
            {
                long res = -1;
                if (root.HasProperty("totalhits"))
                {
                    res = root.totalhits;
                    request.Debug(Resources.Messages.TotalPackagesDiscovered, res);
                }
                else
                {
                    request.Warning(Resources.Messages.JsonSchemaMismatch, "totalhits");
                    request.Debug(Resources.Messages.JsonObjectDump, DynamicJsonParser.Serialize(root));
                }

                return res;
            }, (dynamic root) => GetPackageCollectionsForSearchResult(root, searchContext, searchTerm, foundPackageIds, request), (long packagesToSkip) =>
            {
                if (packagesToSkip > 0)
                {
                    HttpQueryBuilder currentQb = qb.CloneAdd(Constants.SkipQueryParam, packagesToSkip.ToString());
                    return currentQb.AddQueryString(baseUrl);
                }

                return qb.AddQueryString(baseUrl);
            }, (string content) =>
            {
                return DynamicJsonParser.Parse(content);
            }, Constants.SearchPageCountInt));
        }
Beispiel #3
0
 private IEnumerable <IPackage> FindImpl(NuGetSearchContext findContext, RequestWrapper request)
 {
     request.Debug(Messages.DebugInfoCallMethod3, "NuGetPackageFeed3", "FindImpl", findContext.PackageInfo.Id);
     try
     {
         return(base.Execute <IEnumerable <IPackage> >((baseUrl) => GetPackagesForBaseUrl(baseUrl, findContext, request)));
     }
     finally
     {
         request.Debug(Messages.DebugInfoReturnCall, "NuGetPackageFeed3", "FindImpl");
     }
 }
Beispiel #4
0
        public NuGetSearchResult Find(NuGetSearchContext findContext, RequestWrapper request)
        {
            request.Debug(Messages.DebugInfoCallMethod3, "NuGetPackageFeed3", "Find", findContext.PackageInfo.Id);
            if (System.Management.Automation.WildcardPattern.ContainsWildcardCharacters(findContext.PackageInfo.Id))
            {
                // Short circuit when there's wildcards - this will never work
                return(findContext.MakeResult(new List <IPackage>()));
            }

            NuGetSearchResult result = findContext.MakeResult(FindImpl(findContext, request), versionPostFilterRequired: false);

            request.Debug(Messages.DebugInfoReturnCall, "NuGetPackageFeed3", "Find");
            return(result);
        }
 public bool DownloadPackage(PublicObjectView packageView, string destination, RequestWrapper request)
 {
     try
     {
         request.Debug(Messages.DebugInfoCallMethod3, "NuGetLocalPackageFeed", "DownloadPackage", destination);
         PackageItem package = packageView.GetValue <PackageItem>();
         // TODO: For now this has to require NuGetRequest, due to its usage of stuff like request.GetOptionValue and request.YieldPackage
         return(NuGetClient.InstallOrDownloadPackageHelper(package, request.Request, Constants.Install,
                                                           (packageItem, progressTracker) => NuGetClient.DownloadSinglePackage(packageItem, request.Request, destination, progressTracker)));
     }
     finally
     {
         request.Debug(Messages.DebugInfoReturnCall, "NuGetLocalPackageFeed", "DownloadPackage");
     }
 }
Beispiel #6
0
 public bool InstallPackage(PublicObjectView packageView, RequestWrapper request)
 {
     try
     {
         request.Debug(Messages.DebugInfoCallMethod, "NuGetFilesFeed3", "InstallPackage");
         PackageItem package = packageView.GetValue <PackageItem>();
         request.Debug(Messages.DebugInfoCallMethod3, "NuGetFilesFeed3", "InstallPackage", package.FastPath);
         return(NuGetClient.InstallOrDownloadPackageHelper(package, request.Request, Constants.Install,
                                                           (packageItem, progressTracker) => this.InstallSinglePackage(packageItem, request.Request, progressTracker)));
     }
     finally
     {
         request.Debug(Messages.DebugInfoReturnCall, "NuGetFilesFeed3", "InstallPackage");
     }
 }
        public NuGetSearchResult Search(NuGetSearchContext searchContext, RequestWrapper request)
        {
            request.Debug(Messages.DebugInfoCallMethod, "NuGetSearchFeed2", "Search");
            if (request == null)
            {
                return(searchContext.MakeResult());
            }

            string searchString = this.ResourcesCollection.GetSearchQueryDelegate(searchContext.SearchTerms);

            request.Debug(Messages.DebugInfoCallMethod3, "NuGetSearchFeed2", "Search", searchString);

            var searchQuery = searchString.MakeSearchQuery(this.baseUrl, searchContext.AllowPrerelease, searchContext.AllVersions);

            return(searchContext.MakeResult(NuGetWebUtility.SendRequest(searchQuery, request)));
        }
Beispiel #8
0
        public PackageEntryInfo GetVersionInfo(PackageEntryInfo packageInfo, RequestWrapper request)
        {
            try
            {
                request.Debug(Messages.DebugInfoCallMethod, "NuGetFilesFeed3", "GetVersionInfo");
                if (packageInfo == null)
                {
                    throw new ArgumentNullException("packageInfo");
                }
                if (request == null)
                {
                    throw new ArgumentNullException("request");
                }
                string query         = String.Format(CultureInfo.InvariantCulture, Constants.VersionIndexTemplate, this.baseUrl, this.baseUrl.EndsWith("/") ? String.Empty : "/", packageInfo.Id.ToLowerInvariant());
                Stream queryResponse = NuGetClient.DownloadDataToStream(query, request, ignoreNullResponse: true);
                if (queryResponse != null)
                {
                    dynamic root = DynamicJsonParser.Parse(new StreamReader(queryResponse).ReadToEnd());
                    if (root.HasProperty("versions"))
                    {
                        foreach (string v in root.versions)
                        {
                            packageInfo.AddVersion(new SemanticVersion(v));
                        }
                    }
                    else
                    {
                        request.Debug(Messages.VersionIndexDownloadFailed, packageInfo.Id);
                    }
                }
                else
                {
                    request.Debug(Messages.VersionIndexDownloadFailed, packageInfo.Id);
                }
            }
            finally
            {
                request.Debug(Messages.DebugInfoReturnCall, "NuGetFilesFeed3", "GetVersionInfo");
            }

            return(packageInfo);
        }
        public NuGetSearchResult Find(NuGetSearchContext findContext, RequestWrapper request)
        {
            if (string.IsNullOrWhiteSpace(findContext.PackageInfo.Id))
            {
                return(null);
            }

            request.Debug(Messages.DebugInfoCallMethod3, "NuGetPackageFeed2", "FindPackage", findContext.PackageInfo.Id);

            var query = findContext.PackageInfo.Id.MakeFindPackageByIdQuery(this.nugetFindPackageIdQueryFormat);

            var packages = NuGetClient.FindPackage(query, request).Where(package => findContext.PackageInfo.Id.Equals(package.Id, StringComparison.OrdinalIgnoreCase));

            if (findContext.RequiredVersion != null)
            {
                //Usually versions has a limited number, ToArray should be ok.
                var versions = findContext.RequiredVersion.GetComparableVersionStrings().ToArray();
                packages = packages.Where(package => versions.Contains(package.Version, StringComparer.OrdinalIgnoreCase));
            }

            //Will only enumerate packages once
            return(findContext.MakeResult(packages));
        }
Beispiel #10
0
        /// <summary>
        /// Find packages when the registration URL is already known.
        /// </summary>
        /// <param name="registrationUrl"></param>
        /// <param name="request"></param>
        /// <returns></returns>
        internal IEnumerable <PackageBase> Find(string registrationUrl, NuGetSearchContext context, RequestWrapper request, bool finalAttempt)
        {
            request.Debug(Messages.DebugInfoCallMethod3, "NuGetPackageFeed3", "Find", registrationUrl);
            List <PackageBase> packages = null;
            PackageBase        cachedPackage;

            if (!registrationUrl.Contains("index.json") && ConcurrentInMemoryCache.Instance.TryGet <PackageBase>(registrationUrl, out cachedPackage))
            {
                if (cachedPackage == null)
                {
                    return(packages);
                }
                else
                {
                    packages = new List <PackageBase>()
                    {
                        cachedPackage
                    };
                    return(packages);
                }
            }

            Stream s = NuGetClient.DownloadDataToStream(registrationUrl, request, ignoreNullResponse: true, tries: 1);

            if (s != null)
            {
                packages = new List <PackageBase>();
                // Now we can get the catalog entry
                dynamic root = DynamicJsonParser.Parse(new StreamReader(s).ReadToEnd());
                if (root.Metadata.HasProperty("type"))
                {
                    // First check if this is a Package or PackageRegistration type
                    // Package is from packageId + version
                    // PackageRegistration is from packageId
                    bool isRegistrationType = false;
                    foreach (string t in root.Metadata.type)
                    {
                        if (t.Equals("PackageRegistration", StringComparison.OrdinalIgnoreCase))
                        {
                            isRegistrationType = true;
                            break;
                        }
                    }

                    if (context.PackageInfo.AllVersions.Count == 0)
                    {
                        // Only when the version list is restricted is this method usually faster
                        this.ResourcesCollection.FilesFeed.GetVersionInfo(context.PackageInfo, request);
                    }

                    HashSet <SemanticVersion> packageSemanticVersions = null;
                    if (context.PackageInfo.AllVersions.Count > 0)
                    {
                        packageSemanticVersions = FilterVersionsByRequirements(context, context.PackageInfo);
                    }

                    if (isRegistrationType)
                    {
                        // This is a registration index, like: "https://api.nuget.org/v3/registration3/json/index.json"
                        // Get all versions from files service
                        // In addition, when DeepMetadataBypass is enabled, we MUST use the registration index to get package info
                        // If a call to -Name -RequiredVersion is done, DeepMetadataBypass will never be enabled (for now)
                        // If we wanted, we could enable this by checking if !isRegistrationType && context.EnableDeepMetadataBypass, then call into Find with the registration index URL
                        if (!context.AllVersions && packageSemanticVersions != null && !context.EnableDeepMetadataBypass)
                        {
                            foreach (SemanticVersion packageVersion in packageSemanticVersions)
                            {
                                NuGetSearchResult result = this.ResourcesCollection.PackagesFeed.Find(new NuGetSearchContext()
                                {
                                    PackageInfo              = context.PackageInfo,
                                    RequiredVersion          = packageVersion,
                                    EnableDeepMetadataBypass = context.EnableDeepMetadataBypass
                                }, request);
                                PackageBase package = result.Result == null ? null : result.Result.FirstOrDefault() as PackageBase;
                                if (package != null)
                                {
                                    packages.Add(package);
                                }
                            }
                        }
                        else
                        {
                            // Going to collect versions from the registration index in here
                            // Map of package version -> either PackageBase (if context.EnableDeepMetadataBypass) or catalog URL
                            Dictionary <SemanticVersion, object> catalogObjects = new Dictionary <SemanticVersion, object>();
                            // If the version list hasn't been built yet, we can build it from the registration page instead of using FilesFeed
                            bool buildPackageInfoVersions = context.PackageInfo.AllVersions.Count == 0;
                            // Fallback to catalog crawling in these cases:
                            //      - Bypass deep metadata
                            //      - Getting version list failed
                            //      - All versions required
                            foreach (dynamic catalogPage in root.items)
                            {
                                dynamic actualCatalogPage = catalogPage;
                                if (!actualCatalogPage.HasProperty("items"))
                                {
                                    // Sometimes the catalog page on the PackageRegistration entry doesn't have the actual page contents
                                    // In this case, the ID metadata tag points to the full catalog entry
                                    Stream fullCatalogPageResponseStream = NuGetClient.DownloadDataToStream(actualCatalogPage.Metadata.id, request);
                                    if (fullCatalogPageResponseStream != null)
                                    {
                                        actualCatalogPage = DynamicJsonParser.Parse(new StreamReader(fullCatalogPageResponseStream).ReadToEnd());
                                    }
                                }
                                foreach (dynamic packageEntry in actualCatalogPage.items)
                                {
                                    SemanticVersion version = new SemanticVersion(packageEntry.catalogentry.version);
                                    if (buildPackageInfoVersions)
                                    {
                                        context.PackageInfo.AddVersion(version);
                                    }

                                    bool hasCatalogEntry = packageEntry.HasProperty("catalogentry");
                                    if (context.EnableDeepMetadataBypass || !hasCatalogEntry)
                                    {
                                        // Bypass retrieving "deep" (but required) metadata like packageHash
                                        // Also do this if there's no catalog entry
                                        PackageBase pb = null;
                                        if (packageEntry.HasProperty("catalogentry"))
                                        {
                                            pb = this.ResourcesCollection.PackageConverter.Make(packageEntry.catalogentry, context.PackageInfo);
                                        }
                                        else
                                        {
                                            // In some implementations (lookin' at you MyGet) there's no catalogEntry object
                                            pb = this.ResourcesCollection.PackageConverter.Make(packageEntry, context.PackageInfo);
                                        }

                                        if (pb != null)
                                        {
                                            catalogObjects[version] = pb;
                                        }
                                    }
                                    else
                                    {
                                        catalogObjects[version] = this.ResourcesCollection.CatalogUrlConverter.Make(packageEntry);
                                    }
                                }
                            }

                            packageSemanticVersions = FilterVersionsByRequirements(context, context.PackageInfo);
                            foreach (SemanticVersion version in packageSemanticVersions)
                            {
                                if (!catalogObjects.ContainsKey(version))
                                {
                                    continue;
                                }

                                if (context.EnableDeepMetadataBypass)
                                {
                                    packages.Add((PackageBase)catalogObjects[version]);
                                }
                                else
                                {
                                    PackageBase pb = GetPackageFromCatalogUrl((string)catalogObjects[version], request, packageSemanticVersions, context);
                                    if (pb != null)
                                    {
                                        packages.Add(pb);
                                    }
                                }
                            }
                        }
                    }
                    else
                    {
                        // In some implementations (lookin' at you MyGet) there's no catalogEntry object

                        PackageBase pb = ConcurrentInMemoryCache.Instance.GetOrAdd <PackageBase>(registrationUrl, () =>
                        {
                            if (!root.HasProperty("catalogentry"))
                            {
                                if ((packageSemanticVersions == null || packageSemanticVersions.Contains(new SemanticVersion(root.version))))
                                {
                                    return(this.ResourcesCollection.PackageConverter.Make(root));
                                }
                                else
                                {
                                    return(null);
                                }
                            }
                            else
                            {
                                return(GetPackageFromCatalogUrl(this.ResourcesCollection.CatalogUrlConverter.Make(root), request, packageSemanticVersions, context));
                            }
                        });
                        if (pb != null)
                        {
                            packages.Add(pb);
                        }
                    }
                }
                else
                {
                    request.Warning(Messages.JsonSchemaMismatch, "type");
                    request.Debug(Messages.JsonObjectDump, DynamicJsonParser.Serialize(root));
                }

                if (context.RequiredVersion == null && context.MinimumVersion == null && context.MaximumVersion == null && packages != null)
                {
                    PackageBase absoluteLatestPackage = packages.Where(p => p.IsPrerelease).OrderByDescending(pb => ((IPackage)pb).Version).FirstOrDefault();
                    if (absoluteLatestPackage != null)
                    {
                        absoluteLatestPackage.IsAbsoluteLatestVersion = true;
                    }

                    PackageBase latestPackage = packages.Where(p => !p.IsPrerelease).OrderByDescending(pb => ((IPackage)pb).Version).FirstOrDefault();
                    if (latestPackage != null)
                    {
                        latestPackage.IsLatestVersion = true;
                    }
                }
            }
            else if (finalAttempt)
            {
                // This is the last retry of this URL. It's definitely not a good one.
                ConcurrentInMemoryCache.Instance.GetOrAdd <PackageBase>(registrationUrl, () => null);
            }

            return(packages);
        }
        public bool IsAvailable(RequestWrapper request)
        {
            bool       valid    = false;
            HttpClient client   = request.GetClient();
            string     queryUri = Constants.DummyPackageId.MakeFindPackageByIdQuery(PathUtility.UriCombine(this.baseUrl, NuGetConstant.FindPackagesById));

            HttpResponseMessage response = PathUtility.GetHttpResponse(client, queryUri, (() => request.IsCanceled()),
                                                                       ((msg, num) => request.Verbose(Resources.Messages.RetryingDownload, msg, num)), (msg) => request.Verbose(msg), (msg) => request.Debug(msg));

            // The link is not valid
            if (response != null && response.IsSuccessStatusCode)
            {
                valid = true;
            }

            return(valid);
        }
        private bool IsSingleEndpointAvailable(NuGetServiceInfo endpoint, RequestWrapper request)
        {
            HttpClient          client   = request.GetClient();
            HttpResponseMessage response = PathUtility.GetHttpResponse(client, endpoint.Url, (() => request.IsCanceled()),
                                                                       ((msg, num) => request.Verbose(Resources.Messages.RetryingDownload, msg, num)), (msg) => request.Verbose(msg), (msg) => request.Debug(msg));

            if (response != null)
            {
                return(true);
            }
            else
            {
                return(false);
            }
        }
        private static INuGetResourceCollection GetResourcesImpl(string baseUrl, RequestWrapper request)
        {
            INuGetResourceCollection res = null;
            HttpClient          client   = request.GetClientWithHeaders();
            HttpResponseMessage response = PathUtility.GetHttpResponse(client, baseUrl, (() => request.IsCanceled()),
                                                                       ((msg, num) => request.Verbose(Resources.Messages.RetryingDownload, msg, num)), (msg) => request.Verbose(msg), (msg) => request.Debug(msg));

            if (!response.IsSuccessStatusCode)
            {
                throw new Exception(Resources.Messages.NuGetEndpointDiscoveryFailed);
            }

            string content = new StreamReader(NuGetClient.DownloadDataToStream(baseUrl, request)).ReadToEnd();

            // If the response starts with the magic XML header, it's v2
            if (content.StartsWith(Constants.XmlStartContent))
            {
                res = NuGetResourceCollection2.Make(baseUrl);
            }
            else
            {
                try
                {
                    dynamic root    = DynamicJsonParser.Parse(content);
                    string  version = root.version;
                    if (version != null && version.StartsWith("3."))
                    {
                        // v3 feed
                        res = NuGetResourceCollection3.Make(root, baseUrl, request);
                    }
                }
                catch (Exception ex)
                {
                    Exception discoveryException = new Exception(Resources.Messages.NuGetEndpointDiscoveryFailed, ex);
                    throw discoveryException;
                }
            }

            if (res == null)
            {
                // Couldn't figure out what this is
                throw new Exception(Resources.Messages.NuGetEndpointDiscoveryFailed);
            }

            return(res);
        }
        public static NuGetResourceCollection3 Make(dynamic root, string baseUrl, RequestWrapper request)
        {
            request.Debug(Messages.DebugInfoCallMethod3, "NuGetResourceCollection3", "Make", baseUrl);
            NuGetResourceCollection3 collection = new NuGetResourceCollection3();
            Dictionary <NuGetServiceType, NuGetServiceInfo> currentServiceMap = new Dictionary <NuGetServiceType, NuGetServiceInfo>();

            foreach (dynamic resourceElement in root.resources)
            {
                NuGetServiceInfo serviceInfo = NuGetServiceInfo.GetV3Endpoint(resourceElement);
                if (serviceInfo == null)
                {
                    continue;
                }

                bool serviceUsed       = currentServiceMap.ContainsKey(serviceInfo.Type) && currentServiceMap[serviceInfo.Type].Preference <= serviceInfo.Preference;
                bool serviceSupplement = currentServiceMap.ContainsKey(serviceInfo.Type) && currentServiceMap[serviceInfo.Type].Preference == serviceInfo.Preference;
                switch (serviceInfo.Type)
                {
                case NuGetServiceType.AutoComplete:
                    // No feed yet OR no version (lowest possible stable version) OR greater version
                    if (serviceUsed || collection.AutoCompleteFeed == null)
                    {
                        serviceUsed = true;
                        if (serviceSupplement)
                        {
                            ((NuGetAutoCompleteFeed3)collection.AutoCompleteFeed).Endpoints.Add(serviceInfo);
                        }
                        else
                        {
                            collection.AutoCompleteFeed = new NuGetAutoCompleteFeed3(serviceInfo);
                        }
                    }

                    break;

                case NuGetServiceType.Registrations:
                    if (serviceUsed || collection.PackagesFeed == null)
                    {
                        serviceUsed = true;
                        if (serviceSupplement)
                        {
                            ((NuGetPackageFeed3)collection.PackagesFeed).Endpoints.Add(serviceInfo);
                        }
                        else
                        {
                            collection.PackagesFeed = new NuGetPackageFeed3(serviceInfo);
                        }
                    }

                    break;

                case NuGetServiceType.Query:
                    if (serviceUsed || collection.QueryFeed == null)
                    {
                        serviceUsed = true;
                        if (serviceSupplement)
                        {
                            ((NuGetQueryFeed3)collection.QueryFeed).Endpoints.Add(serviceInfo);
                        }
                        else
                        {
                            collection.QueryFeed = new NuGetQueryFeed3(serviceInfo);
                        }
                    }

                    break;

                case NuGetServiceType.Files:
                    if (serviceUsed || collection.FilesFeed == null)
                    {
                        serviceUsed          = true;
                        collection.FilesFeed = new NuGetFilesFeed3(serviceInfo.Url);
                    }

                    break;

                case NuGetServiceType.ReportAbuse:
                    if (serviceUsed || collection.AbuseFeed == null)
                    {
                        serviceUsed          = true;
                        collection.AbuseFeed = new NuGetAbuseFeed3(serviceInfo.Url);
                    }

                    break;
                }

                if (serviceUsed)
                {
                    request.Debug(Messages.NuGetEndpointDiscovered, serviceInfo.Type, serviceInfo.Url);
                    if (!serviceSupplement)
                    {
                        currentServiceMap[serviceInfo.Type] = serviceInfo;
                    }
                }
            }

            collection.GetSearchQueryDelegate = (searchTerms) =>
            {
                string searchString = String.Empty;
                // TODO: encode search terms?
                foreach (NuGetSearchTerm searchTerm in searchTerms)
                {
                    switch (searchTerm.Term)
                    {
                    case NuGetSearchTerm.NuGetSearchTermType.SearchTerm:
                        searchString += searchTerm.Text;
                        break;

                    case NuGetSearchTerm.NuGetSearchTermType.Tag:
                        HttpQueryBuilder tQb = new HttpQueryBuilder().Add(Constants.TagQueryParam, searchTerm.Text, separator: ":", encode: false);
                        searchString += " " + tQb.ToQueryString();
                        break;

                    case NuGetSearchTerm.NuGetSearchTermType.Contains:
                        HttpQueryBuilder cQb = new HttpQueryBuilder().Add(Constants.DescriptionQueryParam, searchTerm.Text, separator: ":", encode: false);
                        searchString += " " + cQb.ToQueryString();
                        break;

                    default:
                        break;
                    }
                }

                return(searchString.Trim());
            };

            collection.PackageConverter              = new PackageBaseConverter();
            collection.PackageDependencyConverter    = new PackageDependencyConverter();
            collection.PackageDependencySetConverter = new DependencyGroupConverter();
            collection.CatalogUrlConverter           = new CatalogUrlConverter();
            Uri uri = new Uri(baseUrl);

            if (uri.Host.Contains(Constants.NuGetOrgHost))
            {
                collection.GalleryFeed = new NuGetGalleryFeedOrg();
            }
            else if (uri.Host.Contains(Constants.MyGetOrgHost))
            {
                collection.GalleryFeed = new NuGetGalleryFeedMyGet(baseUrl);
            }

            request.Debug(Messages.DebugInfoReturnCall, "NuGetResourceCollection3", "Make");
            return(collection);
        }
        public static IEnumerable <PackageBase> SendRequest(string query, RequestWrapper request)
        {
            // Enforce use of TLS 1.2 when sending request
            var securityProtocol = System.Net.ServicePointManager.SecurityProtocol;

            System.Net.ServicePointManager.SecurityProtocol = System.Net.SecurityProtocolType.Tls12;

            const int bufferSize = 40;
            // number of threads sending the requests
            const int numberOfSenders = 4;

            var startPoint = 0;
            var tasks      = new List <Task <Stream> >();

            bool   stopSending = false;
            object stopLock    = new Object();

            // Send one request first

            // this initial query is of the form http://www.nuget.org/api/v2/FindPackagesById()?id='jquery'&$skip={0}&$top={1}
            UriBuilder initialQuery = new UriBuilder(query.InsertSkipAndTop());

            PackageBase firstPackage = null;

            // Send out an initial request
            // we send out 1 initial request first to check for redirection and check whether repository supports odata
            using (Stream stream = NuGetClient.InitialDownloadDataToStream(initialQuery, startPoint, bufferSize, request))
            {
                if (stream == null)
                {
                    yield break;
                }

                XDocument document = XmlUtility.LoadSafe(stream, ignoreWhiteSpace: true);

                var entries = document.Root.ElementsNoNamespace("entry").ToList();

                // If the initial request has different number of entries than the buffer size, return it because this means the server
                // does not understand odata request or there is no more data. in the former case, we have to stop to prevent infinite loop
                if (entries.Count != bufferSize)
                {
                    request.Debug(Messages.PackagesReceived, entries.Count);
                    stopSending = true;
                }

                foreach (XElement entry in entries)
                {
                    var package = new PackageBase();

                    // set the first package of the request. this is used later to verify that the case when the number of packages in the repository
                    // is the same as the buffer size and the repository does not support odata query. in that case, we want to check whether the first package
                    // exists anywhere in the second call. if it is, then we cancel the request (this is to prevent infinite loop)
                    if (firstPackage == null)
                    {
                        firstPackage = package;
                    }

                    PackageUtility.ReadEntryElement(ref package, entry);
                    yield return(package);
                }
            }

            if (stopSending || request.IsCanceled())
            {
                yield break;
            }

            // To avoid more redirection (for example, if the initial query is nuget.org, it will be changed to www.nuget.org

            query = initialQuery.Uri.ToString();

            // Sending the initial requests
            for (var i = 0; i < numberOfSenders; i++)
            {
                // Update the start point to fetch the packages
                startPoint += bufferSize;

                // Get the query
                var newQuery = string.Format(query, startPoint, bufferSize);

                // Send it
                tasks.Add(Task.Factory.StartNew(() =>
                {
                    Stream items = NuGetClient.DownloadDataToStream(newQuery, request);
                    return(items);
                }));
            }

            //Wait for the responses, parse the data, and send to the user
            while (tasks.Count > 0)
            {
                //Cast because the compiler warning: Co-variant array conversion from Task[] to Task[] can cause run-time exception on write operation.
                var index = Task.WaitAny(tasks.Cast <Task>().ToArray());

                using (Stream stream = tasks[index].Result)
                {
                    if (stream == null)
                    {
                        yield break;
                    }

                    XDocument document = XmlUtility.LoadSafe(stream, ignoreWhiteSpace: true);

                    var entries = document.Root.ElementsNoNamespace("entry").ToList();

                    if (entries.Count < bufferSize)
                    {
                        request.Debug(Messages.PackagesReceived, entries.Count);
                        lock (stopLock)
                        {
                            stopSending = true;
                        }
                    }

                    foreach (XElement entry in entries)
                    {
                        var package = new PackageBase();

                        PackageUtility.ReadEntryElement(ref package, entry);

                        if (firstPackage != null)
                        {
                            // check whether first package in the first request exists anywhere in the second request
                            if (string.Equals(firstPackage.GetFullName(), package.GetFullName(), StringComparison.OrdinalIgnoreCase) &&
                                string.Equals(firstPackage.Version, package.Version, StringComparison.OrdinalIgnoreCase))
                            {
                                lock (stopLock)
                                {
                                    stopSending = true;
                                }

                                break;
                            }
                        }

                        yield return(package);
                    }

                    // we only needs to check for the existence of the first package in the second request. don't need to do for subsequent request
                    if (firstPackage != null)
                    {
                        firstPackage = null;
                    }
                }

                // checks whether we should stop sending requests
                if (!stopSending && !request.IsCanceled())
                {
                    // Make sure nobody else is updating the startPoint
                    lock (stopLock)
                    {
                        // update the startPoint
                        startPoint += bufferSize;
                    }
                    // Make a new request with the new startPoint
                    var newQuery = string.Format(query, startPoint, bufferSize);

                    //Keep sending a request
                    tasks[index] = (Task.Factory.StartNew(searchQuery =>
                    {
                        var items = NuGetClient.DownloadDataToStream(searchQuery.ToStringSafe(), request);
                        return(items);
                    }, newQuery));
                }
                else
                {
                    if (request.IsCanceled())
                    {
                        request.Warning(Messages.RequestCanceled, "NuGetWebUtility", "SendRequest");
                        //stop sending request to the remote server
                        stopSending = true;
                    }

                    tasks.RemoveAt(index);
                }
            }

            // Change back to user specified security protocol
            System.Net.ServicePointManager.SecurityProtocol = securityProtocol;
        }