Skip to content

Commit

Permalink
Initial support for proxied search query #9
Browse files Browse the repository at this point in the history
  • Loading branch information
tomzo committed Feb 13, 2019
1 parent 3c9d061 commit b02062c
Show file tree
Hide file tree
Showing 11 changed files with 120 additions and 8 deletions.
1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,6 @@ Not implemented:
* Does not work with older paket versions
* Cache package metadata and invalidates when upstream changes are detected using [NuGet.CatalogReader](https://github.com/emgarten/NuGet.CatalogReader). *This will be ported from older liget < 1.0.0.*
* V2 search, filter and alike queries. *This is not planned.*
* search and autocomplete endpoints for cached packages. Basically, you need to query nuget.org to *search* for public packages.

# Usage

Expand Down
5 changes: 5 additions & 0 deletions src/LiGet/Cache/CacheService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -148,5 +148,10 @@ public Task<IPackageSearchMetadata> FindAsync(PackageIdentity identity)
//TODO: possibly cache and stream from in-memory cache
return _sourceRepository.GetMetadataAsync(identity, CancellationToken.None);
}

public Task<IEnumerable<IPackageSearchMetadata>> SearchAsync(string searchTerm, SearchFilter filter, int skip, int take, CancellationToken ct)
{
return _sourceRepository.SearchAsync(searchTerm, filter, skip, take, ct);
}
}
}
5 changes: 5 additions & 0 deletions src/LiGet/Cache/FakeCacheService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -57,5 +57,10 @@ public Task CacheAsync(
{
return Task.CompletedTask;
}

public Task<IEnumerable<IPackageSearchMetadata>> SearchAsync(string searchTerm, SearchFilter filter, int skip, int take, CancellationToken ct)
{
throw new System.NotImplementedException();
}
}
}
2 changes: 2 additions & 0 deletions src/LiGet/Cache/ICacheService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,5 +30,7 @@ public interface ICacheService
Task<Stream> GetNuspecStreamAsync(PackageIdentity identity);
Task<Stream> GetReadmeStreamAsync(PackageIdentity identity);
Task<IPackageSearchMetadata> FindAsync(PackageIdentity identity);

Task<IEnumerable<IPackageSearchMetadata>> SearchAsync(string searchTerm, SearchFilter filter, int skip, int take, CancellationToken ct);
}
}
1 change: 1 addition & 0 deletions src/LiGet/CarterModules/CacheIndexModule.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ await res.AsJson(new
Version = "3.0.0",
Resources =
ServiceWithAliases("PackagePublish", req.PackagePublish(prefix), "2.0.0") // api.nuget.org returns this too.
.Concat(ServiceWithAliases("SearchQueryService", req.PackageSearch(prefix), "", "3.0.0-beta", "3.0.0-rc")) // each version is an alias of others
.Concat(ServiceWithAliases("RegistrationsBaseUrl", req.RegistrationsBase(prefix), "", "3.0.0-rc", "3.0.0-beta"))
.Concat(ServiceWithAliases("PackageBaseAddress", req.PackageBase(prefix), "3.0.0"))
.ToList()
Expand Down
36 changes: 36 additions & 0 deletions src/LiGet/CarterModules/CacheSearchModule.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
using System.Linq;
using System.Threading;
using Carter;
using Carter.ModelBinding;
using Carter.Request;
using Carter.Response;
using LiGet.Cache;
using LiGet.Configuration;
using LiGet.WebModels;
using NuGet.Protocol.Core.Types;

namespace LiGet.CarterModules
{
public class CacheSearchModule : CarterModule
{
const string prefix = "api/cache";

public CacheSearchModule(ICacheService cacheService) {
this.Get("/api/cache/v3/search", async (req, res, routeData) => {
var query = req.Query.As<string>("q");
int? skip = req.Query.As<int?>("skip");
int? take = req.Query.As<int?>("take");
bool? prerelease = req.Query.As<bool?>("prerelease");
string semVerLevel = req.Query.As<string>("semVerLevel");
query = query ?? string.Empty;
var results = await cacheService.SearchAsync(query, new SearchFilter(prerelease ?? false), skip ?? 0, take ?? 0, CancellationToken.None);
await res.AsJson(new
{
TotalHits = results.Count(),
Data = results.Select(r => new SearchResultModel(r, r.GetVersionsAsync().Result, req, prefix))
});
});
}
}
}
3 changes: 2 additions & 1 deletion src/LiGet/ISourceRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ public interface ISourceRepository
Task<IEnumerable<IPackageSearchMetadata>> GetMetadataAsync(string packageId, bool includePrerelease, bool includeUnlisted, CancellationToken ct);
Task<IEnumerable<NuGetVersion>> GetAllVersionsAsync(string id, CancellationToken ct);
Task<Uri> GetPackageUriAsync(string id, string version, CancellationToken cancellationToken);
Task<IPackageSearchMetadata> GetMetadataAsync(PackageIdentity identity, CancellationToken none);
Task<IPackageSearchMetadata> GetMetadataAsync(PackageIdentity identity, CancellationToken ct);
Task<IEnumerable<IPackageSearchMetadata>> SearchAsync(string searchTerm, SearchFilter filter, int skip, int take, CancellationToken ct);
}
}
8 changes: 8 additions & 0 deletions src/LiGet/NuGetClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ private class NuRepository : ISourceRepository
private RegistrationResourceV3 _regResource;
private PackageMetadataResourceV3 _metadataSearch;
private RemoteV3FindPackageByIdResource _versionSearch;
private PackageSearchResourceV3 _search;
private NuGetLoggerAdapter<NuGetClient> _loggerAdapter;

public NuRepository(List<Lazy<INuGetResourceProvider>> providers, Uri repositoryUrl, Microsoft.Extensions.Logging.ILogger<NuGetClient> logger)
Expand All @@ -55,6 +56,8 @@ public NuRepository(List<Lazy<INuGetResourceProvider>> providers, Uri repository
ReportAbuseResourceV3 reportAbuseResource = _sourceRepository.GetResource<ReportAbuseResourceV3>();
_metadataSearch = new PackageMetadataResourceV3(httpSource.HttpSource, _regResource, reportAbuseResource);
_versionSearch = new RemoteV3FindPackageByIdResource(_sourceRepository, httpSource.HttpSource);
RawSearchResourceV3 rawSearchResource = _sourceRepository.GetResource<RawSearchResourceV3>();
_search = new PackageSearchResourceV3(rawSearchResource, _metadataSearch);
this._loggerAdapter = new NuGetLoggerAdapter<NuGetClient>(logger);
}

Expand Down Expand Up @@ -100,6 +103,11 @@ public Task<IPackageSearchMetadata> GetMetadataAsync(PackageIdentity identity, C
{
return _metadataSearch.GetMetadataAsync(identity, _cacheContext, _loggerAdapter, ct);
}

public Task<IEnumerable<IPackageSearchMetadata>> SearchAsync(string searchTerm, SearchFilter filter, int skip, int take, CancellationToken ct)
{
return _search.SearchAsync(searchTerm, filter, skip, take, _loggerAdapter, ct);
}
}
}
}
33 changes: 33 additions & 0 deletions src/LiGet/Services/ISearchService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using LiGet.Entities;
using NuGet.Protocol.Core.Types;
using NuGet.Versioning;

namespace LiGet.Services
Expand All @@ -17,6 +18,31 @@ public interface ISearchService

public class SearchResult
{
public SearchResult()
{
}

public SearchResult(IPackageSearchMetadata result, IEnumerable<VersionInfo> versions)
{
this.Id = result.Identity.Id;
this.Version = result.Identity.Version;
this.Description = result.Description;
this.Authors = result.Authors;
this.IconUrl = result.IconUrl?.AbsoluteUri;
this.LicenseUrl = result.LicenseUrl?.AbsoluteUri;
this.ProjectUrl = result.ProjectUrl?.AbsoluteUri;
this.Summary = result.Summary;
if(result.Tags != null)
this.Tags = result.Tags.Split(',');
this.Title = result.Title;
this.TotalDownloads = result.DownloadCount ?? 0;
var list = new List<SearchResultVersion>();
foreach(var v in versions) {
list.Add(new SearchResultVersion(v));
}
this.Versions = list;
}

public string Id { get; set; }

public NuGetVersion Version { get; set; }
Expand All @@ -36,6 +62,13 @@ public class SearchResult

public class SearchResultVersion
{

public SearchResultVersion(VersionInfo v)
{
this.Version = v.Version;
this.Downloads = v.DownloadCount ?? 0;
}

public SearchResultVersion(NuGetVersion version, long downloads)
{
Version = version ?? throw new ArgumentNullException(nameof(version));
Expand Down
13 changes: 13 additions & 0 deletions src/LiGet/WebModels/SearchResultModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using LiGet.Services;
using LiGet.Extensions;
using Microsoft.AspNetCore.Http;
using NuGet.Protocol.Core.Types;

namespace LiGet.WebModels
{
Expand All @@ -27,6 +28,18 @@ public SearchResultModel(SearchResult result, HttpRequest url, string prefix)
Versions = versions.ToList().AsReadOnly();
}

public SearchResultModel(IPackageSearchMetadata result, IEnumerable<VersionInfo> versions, HttpRequest url, string prefix)
{
_result = new SearchResult(result, versions);
_url = url ?? throw new ArgumentNullException(nameof(url));
this._prefix = prefix;
Versions = _result.Versions.Select(
v => new SearchResultVersionModel(
url.PackageRegistration(_result.Id, v.Version.ToNormalizedString()),
v.Version.ToNormalizedString(),
v.Downloads)).ToList();
}

public string Id => _result.Id;
public string Version => _result.Version.ToNormalizedString();
public string Description => _result.Description;
Expand Down
21 changes: 15 additions & 6 deletions tests/LiGet.Tests/NuGetClientIntegrationTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,6 @@ public class NuGetClientIntegrationTest : IDisposable
new object[] { CacheIndex },
new object[] { CompatCacheIndex },
};
public static IEnumerable<object[]> V3CasesExcludingCache = new[] {
new object[] { MainIndex },
new object[] { CompatIndex },
};
public static IEnumerable<object[]> V2Cases = new[] {
new object[] { V2Index },
new object[] { CompatV2Index }
Expand Down Expand Up @@ -141,7 +137,7 @@ public async Task V2IndexResourceReturnsODataServiceDocument(string indexEndpoin
}

[Theory]
[MemberData(nameof(V3CasesExcludingCache))]
[MemberData(nameof(V3Cases))]
public async Task IndexIncludesAtLeastOneSearchQueryEntry(string indexEndpoint)
{
InitializeClient(indexEndpoint);
Expand All @@ -168,7 +164,7 @@ public async Task IndexIncludesAtLeastOnePackageBaseAddressEntry(string indexEnd
}

[Theory]
[MemberData(nameof(V3CasesExcludingCache))]
[MemberData(nameof(V3Cases))]
public async Task IndexIncludesAtLeastOneSearchAutocompleteServiceEntry(string indexEndpoint)
{
InitializeClient(indexEndpoint);
Expand Down Expand Up @@ -335,6 +331,19 @@ await packageResource.Push(TestResources.GetNupkgBagetTest1(),
Assert.Equal(new PackageIdentity("liget-test1", NuGetVersion.Parse("1.0.0")), one.Identity);
}

[Fact]
[Trait("Category", "integration")] // because it queries nuget.org
public async Task CacheSearchPackage()
{
InitializeClient(CacheIndex);
var packageResource = await _sourceRepository.GetResourceAsync<PackageUpdateResource>();
PackageSearchResourceV3 search = GetSearch();
var found = await search.SearchAsync("log4net", new SearchFilter(true), 0, 10, logger, CancellationToken.None);
Assert.NotEmpty(found);
var one = found.First();
Assert.Equal("log4net", one.Identity.Id);
}

private PackageSearchResourceV3 GetSearch()
{
PackageMetadataResourceV3 packageMetadataRes = GetPackageMetadataResource();
Expand Down

0 comments on commit b02062c

Please sign in to comment.