Hi.
As far as I can tell, AutoCompleteResource.IdStartsWith (v3 API) incorrectly passes the query parameter includePrerelease=true, but it should be passing prerelease=true (according to the API docs here).
NuGet product used: NuGet client library (specifically, NuGet.Protocol.Core.Types.AutoCompleteResource).
NuGet version: NuGet.Protocol (v4.8.0.0).
Below is a small console app that reproduces the issue and demonstrates that, if the URL uses the correct prerelease=true query parameter, correct results are returned.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
using NuGet.Common;
using NuGet.Configuration;
using NuGet.Protocol;
using NuGet.Protocol.Core.Types;
namespace NuGetSuggestions
{
static class Program
{
static async Task Main()
{
PackageSource packageSource = new PackageSource("https://api.nuget.org/v3/index.json");
var providers = new List<Lazy<INuGetResourceProvider>>();
providers.AddRange(
Repository.Provider.GetCoreV3()
);
SourceRepository sourceRepository = new SourceRepository(packageSource, providers);
AutoCompleteResource autoCompleteResource = await sourceRepository.GetResourceAsync<AutoCompleteResource>(CancellationToken.None);
IEnumerable<string> packageIds = await autoCompleteResource.IdStartsWith("SixLabors", includePrerelease: true, log: NullLogger.Instance, CancellationToken.None);
Console.WriteLine("Without fix, got {0} package Ids.", packageIds.Count()); // Shows 0 package Ids
// Patch the HttpClient handler chain, inserting our fix.
FieldInfo clientField = autoCompleteResource.GetType().GetField("_client", BindingFlags.Instance | BindingFlags.NonPublic);
HttpSource httpSource = (HttpSource)clientField.GetValue(autoCompleteResource);
FieldInfo httpClientField = httpSource.GetType().GetField("_httpClient", BindingFlags.Instance | BindingFlags.NonPublic);
HttpClient httpClient = (HttpClient)httpClientField.GetValue(httpSource);
FieldInfo handlerField = typeof(HttpMessageInvoker).GetField("_handler", BindingFlags.Instance | BindingFlags.NonPublic);
HttpMessageHandler innerHandler = (HttpMessageHandler)handlerField.GetValue(httpClient);
PrereleaseFixHandler prereleaseFixHandler = new PrereleaseFixHandler(innerHandler);
httpClient = new HttpClient(prereleaseFixHandler);
httpClientField.SetValue(httpSource, httpClient);
packageIds = await autoCompleteResource.IdStartsWith("SixLabors", includePrerelease: true, log: NullLogger.Instance, CancellationToken.None);
Console.WriteLine("With fix, got {0} package Ids.", packageIds.Count()); // Shows 7 package Ids
}
class PrereleaseFixHandler : DelegatingHandler
{
public PrereleaseFixHandler(HttpMessageHandler innerHandler)
: base(innerHandler)
{
}
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage requestMessage, CancellationToken cancellationToken)
{
Console.WriteLine("Original request URI: {0}", requestMessage.RequestUri);
// Fix incorrectly-named "includePrerelease" query parameter (should be "prerelease").
requestMessage.RequestUri = new Uri(requestMessage.RequestUri.AbsoluteUri.Replace("&includePrerelease=", "&prerelease="));
Console.WriteLine("Modified request URI: {0}", requestMessage.RequestUri);
HttpResponseMessage responseMessage = await base.SendAsync(requestMessage, cancellationToken);
return responseMessage;
}
}
}
}
The code responsible seems to be here:
@ryuyu
I think you might have some context about the protocol.
Has this always been the case?
Was the client implementation always wrong?
I'm happy to submit a PR if it turns out this needs fixing, by the way :)
I synced up with @joelverhagen
The v2 protocol used includePrerelease https://github.com/NuGet/NuGetGallery/blob/7bcc3973abd94302c3f61df992113dd3d31693e9/src/NuGetGallery/Controllers/ApiController.cs#L890, but the v3 uses only prerelease.
So only that needs changing.
For reference, the v3 implementation is here:
https://github.com/NuGet/NuGet.Services.Metadata/blob/37b26ada86a09ce26f02c218bf4322ac1f9e6482/src/NuGet.Services.BasicSearch/ServiceEndpoints.cs#L96
Should I open a PR for this, then? Happy to have a go.
@tintoy
Thanks, I have assigned it to @heng-liu as she is familiarizing herself with the codebase.
I imagine she'll have a PR soon :)