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)); }
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"); } }
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"); } }
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))); }
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)); }
/// <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; }