public async Task <IHttpActionResult> Get( ODataQueryOptions <V2FeedPackage> options, [FromUri] string semVerLevel = null) { // Setup the search var packages = GetAll() .Where(p => p.PackageStatusKey == PackageStatus.Available) .Where(SemVerLevelKey.IsPackageCompliantWithSemVerLevelPredicate(semVerLevel)) .WithoutSortOnColumn(Version) .WithoutSortOnColumn(Id, ShouldIgnoreOrderById(options)) .InterceptWith(new NormalizeVersionInterceptor()); var semVerLevelKey = SemVerLevelKey.ForSemVerLevel(semVerLevel); bool?customQuery = null; // Try the search service try { var searchService = _searchServiceFactory.GetService(); HijackableQueryParameters hijackableQueryParameters = null; if (searchService is ExternalSearchService && SearchHijacker.IsHijackable(options, out hijackableQueryParameters)) { var searchAdaptorResult = await SearchAdaptor.FindByIdAndVersionCore( searchService, GetTraditionalHttpContext().Request, packages, hijackableQueryParameters.Id, hijackableQueryParameters.Version, semVerLevel : semVerLevel); // If intercepted, create a paged queryresult if (searchAdaptorResult.ResultsAreProvidedBySearchService) { customQuery = false; // Packages provided by search service packages = searchAdaptorResult.Packages; // Add explicit Take() needed to limit search hijack result set size if $top is specified var totalHits = packages.LongCount(); var pagedQueryable = packages .Take(options.Top != null ? Math.Min(options.Top.Value, MaxPageSize) : MaxPageSize) .ToV2FeedPackageQuery( GetSiteRoot(), _configurationService.Features.FriendlyLicenses, semVerLevelKey); return(TrackedQueryResult( options, pagedQueryable, MaxPageSize, totalHits, (o, s, resultCount) => SearchAdaptor.GetNextLink(Request.RequestUri, resultCount, null, o, s, semVerLevelKey), customQuery)); } else { customQuery = true; } } else { customQuery = true; } } catch (Exception ex) { // Swallowing Exception intentionally. If *anything* goes wrong in search, just fall back to the database. // We don't want to break package restores. We do want to know if this happens, so here goes: QuietLog.LogHandledException(ex); } // Reject only when try to reach database. if (!ODataQueryVerifier.AreODataOptionsAllowed(options, ODataQueryVerifier.V2Packages, _configurationService.Current.IsODataFilterEnabled, nameof(Get))) { return(BadRequest(ODataQueryVerifier.GetValidationFailedMessage(options))); } var queryable = packages.ToV2FeedPackageQuery( GetSiteRoot(), _configurationService.Features.FriendlyLicenses, semVerLevelKey); return(TrackedQueryResult(options, queryable, MaxPageSize, customQuery)); }
private async Task <IHttpActionResult> GetCore( ODataQueryOptions <V2FeedPackage> options, string id, string version, string semVerLevel, bool return404NotFoundWhenNoResults) { var packages = GetAll() .Include(p => p.PackageRegistration) .Where(p => p.PackageStatusKey == PackageStatus.Available && p.PackageRegistration.Id.Equals(id, StringComparison.OrdinalIgnoreCase)) .Where(SemVerLevelKey.IsPackageCompliantWithSemVerLevelPredicate(semVerLevel)); if (!string.IsNullOrEmpty(version)) { NuGetVersion nugetVersion; if (NuGetVersion.TryParse(version, out nugetVersion)) { // Our APIs expect to receive normalized version strings. // We need to compare normalized versions or we can never retrieve SemVer2 package versions. var normalizedString = nugetVersion.ToNormalizedString(); packages = packages.Where(p => p.NormalizedVersion == normalizedString); } } var semVerLevelKey = SemVerLevelKey.ForSemVerLevel(semVerLevel); bool?customQuery = null; // try the search service try { var searchService = _searchServiceFactory.GetService(); var searchAdaptorResult = await SearchAdaptor.FindByIdAndVersionCore( searchService, GetTraditionalHttpContext().Request, packages, id, version, semVerLevel : semVerLevel); // If intercepted, create a paged queryresult if (searchAdaptorResult.ResultsAreProvidedBySearchService) { customQuery = false; // Packages provided by search service packages = searchAdaptorResult.Packages; // Add explicit Take() needed to limit search hijack result set size if $top is specified var totalHits = packages.LongCount(); if (totalHits == 0 && return404NotFoundWhenNoResults) { _telemetryService.TrackODataCustomQuery(customQuery); return(NotFound()); } var pagedQueryable = packages .Take(options.Top != null ? Math.Min(options.Top.Value, MaxPageSize) : MaxPageSize) .ToV2FeedPackageQuery( GetSiteRoot(), _configurationService.Features.FriendlyLicenses, semVerLevelKey); return(TrackedQueryResult( options, pagedQueryable, MaxPageSize, totalHits, (o, s, resultCount) => SearchAdaptor.GetNextLink(Request.RequestUri, resultCount, new { id }, o, s, semVerLevelKey), customQuery)); } else { customQuery = true; } } catch (Exception ex) { // Swallowing Exception intentionally. If *anything* goes wrong in search, just fall back to the database. // We don't want to break package restores. We do want to know if this happens, so here goes: QuietLog.LogHandledException(ex); } if (return404NotFoundWhenNoResults && !packages.Any()) { _telemetryService.TrackODataCustomQuery(customQuery); return(NotFound()); } var queryable = packages.ToV2FeedPackageQuery( GetSiteRoot(), _configurationService.Features.FriendlyLicenses, semVerLevelKey); return(TrackedQueryResult(options, queryable, MaxPageSize, customQuery)); }
private async Task <IHttpActionResult> GetCore(ODataQueryOptions <V1FeedPackage> options, string id, string version, bool return404NotFoundWhenNoResults) { var packages = _packagesRepository.GetAll() .Include(p => p.PackageRegistration) .Where(p => p.PackageRegistration.Id.Equals(id, StringComparison.OrdinalIgnoreCase) && !p.IsPrerelease && p.PackageStatusKey == PackageStatus.Available) .Where(SemVerLevelKey.IsUnknownPredicate()); if (!string.IsNullOrEmpty(version)) { packages = packages.Where(p => p.Version == version); } bool?customQuery = null; // try the search service try { var searchAdaptorResult = await SearchAdaptor.FindByIdAndVersionCore( _searchService, GetTraditionalHttpContext().Request, packages, id, version, semVerLevel : null); // If intercepted, create a paged queryresult if (searchAdaptorResult.ResultsAreProvidedBySearchService) { customQuery = false; // Packages provided by search service packages = searchAdaptorResult.Packages; // Add explicit Take() needed to limit search hijack result set size if $top is specified var totalHits = packages.LongCount(); if (return404NotFoundWhenNoResults && totalHits == 0) { _telemetryService.TrackODataCustomQuery(customQuery); return(NotFound()); } var pagedQueryable = packages .Take(options.Top != null ? Math.Min(options.Top.Value, MaxPageSize) : MaxPageSize) .ToV1FeedPackageQuery(GetSiteRoot()); return(TrackedQueryResult( options, pagedQueryable, MaxPageSize, totalHits, (o, s, resultCount) => SearchAdaptor.GetNextLink(Request.RequestUri, resultCount, new { id }, o, s), customQuery)); } else { customQuery = true; } } catch (Exception ex) { // Swallowing Exception intentionally. If *anything* goes wrong in search, just fall back to the database. // We don't want to break package restores. We do want to know if this happens, so here goes: QuietLog.LogHandledException(ex); } if (return404NotFoundWhenNoResults && !packages.Any()) { _telemetryService.TrackODataCustomQuery(customQuery); return(NotFound()); } var queryable = packages.ToV1FeedPackageQuery(GetSiteRoot()); return(TrackedQueryResult(options, queryable, MaxPageSize, customQuery)); }
private async Task <IHttpActionResult> GetCoreAsync( ODataQueryOptions <V2FeedPackage> options, string id, string version, string semVerLevel, bool allowHijack, bool return404NotFoundWhenNoResults, bool isNonHijackEnabled) { var packages = GetAll() .Include(p => p.PackageRegistration) .Where(p => p.PackageStatusKey == PackageStatus.Available && p.PackageRegistration.Id.Equals(id, StringComparison.OrdinalIgnoreCase)) .Where(SemVerLevelKey.IsPackageCompliantWithSemVerLevelPredicate(semVerLevel)); if (!string.IsNullOrEmpty(version)) { NuGetVersion nugetVersion; if (NuGetVersion.TryParse(version, out nugetVersion)) { // Our APIs expect to receive normalized version strings. // We need to compare normalized versions or we can never retrieve SemVer2 package versions. var normalizedString = nugetVersion.ToNormalizedString(); packages = packages.Where(p => p.NormalizedVersion == normalizedString); } } var semVerLevelKey = SemVerLevelKey.ForSemVerLevel(semVerLevel); bool?customQuery = null; if (allowHijack) { // try the search service try { var searchService = _searchServiceFactory.GetService(); var searchAdaptorResult = await SearchAdaptor.FindByIdAndVersionCore( searchService, GetTraditionalHttpContext().Request, packages, id, version, semVerLevel : semVerLevel); // If intercepted, create a paged queryresult if (searchAdaptorResult.ResultsAreProvidedBySearchService) { customQuery = false; // Packages provided by search service packages = searchAdaptorResult.Packages; // Add explicit Take() needed to limit search hijack result set size if $top is specified var totalHits = packages.LongCount(); if (totalHits == 0 && return404NotFoundWhenNoResults) { _telemetryService.TrackODataCustomQuery(customQuery); return(NotFound()); } var pagedQueryable = packages .Take(options.Top != null ? Math.Min(options.Top.Value, MaxPageSize) : MaxPageSize) .ToV2FeedPackageQuery( GetSiteRoot(), _configurationService.Features.FriendlyLicenses, semVerLevelKey); return(TrackedQueryResult( options, pagedQueryable, MaxPageSize, totalHits, (o, s, resultCount) => SearchAdaptor.GetNextLink(Request.RequestUri, resultCount, new { id }, o, s, semVerLevelKey), customQuery)); } else { customQuery = true; } } catch (Exception ex) { // Swallowing Exception intentionally. If *anything* goes wrong in search, just fall back to the database. // We don't want to break package restores. We do want to know if this happens, so here goes: QuietLog.LogHandledException(ex); } } // When non-hijacked queries are disabled, allow only one non-hijacked pattern: query for a specific ID and // version without any fancy OData options. This enables some monitoring and testing and is known to produce // a very fast SQL query based on an optimized index. var isSimpleLookup = !string.IsNullOrWhiteSpace(id) && !string.IsNullOrWhiteSpace(version) && options.RawValues.Expand == null && options.RawValues.Filter == null && options.RawValues.Format == null && options.RawValues.InlineCount == null && options.RawValues.OrderBy == null && options.RawValues.Select == null && options.RawValues.Skip == null && options.RawValues.SkipToken == null && options.RawValues.Top == null; if (!allowHijack || !isNonHijackEnabled) { if (!isSimpleLookup) { return(DeprecatedRequest(Strings.ODataParametersDisabled)); } customQuery = true; } if (return404NotFoundWhenNoResults && !packages.Any()) { _telemetryService.TrackODataCustomQuery(customQuery); return(NotFound()); } var queryable = packages.ToV2FeedPackageQuery( GetSiteRoot(), _configurationService.Features.FriendlyLicenses, semVerLevelKey); return(TrackedQueryResult(options, queryable, MaxPageSize, customQuery)); }
private async Task <IHttpActionResult> GetCore(ODataQueryOptions <V2FeedPackage> options, string curatedFeedName, string id, string version, bool return404NotFoundWhenNoResults) { var curatedFeed = _entities.CuratedFeeds.FirstOrDefault(cf => cf.Name == curatedFeedName); if (curatedFeed == null) { return(NotFound()); } var packages = _curatedFeedService.GetPackages(curatedFeedName) .Where(p => p.PackageRegistration.Id.Equals(id, StringComparison.OrdinalIgnoreCase)); if (!string.IsNullOrEmpty(version)) { packages = packages.Where(p => p.Version == version); } // try the search service try { var searchAdaptorResult = await SearchAdaptor.FindByIdAndVersionCore( _searchService, GetTraditionalHttpContext().Request, packages, id, version, curatedFeed : curatedFeed); // If intercepted, create a paged queryresult if (searchAdaptorResult.ResultsAreProvidedBySearchService) { // Packages provided by search service packages = searchAdaptorResult.Packages; // Add explicit Take() needed to limit search hijack result set size if $top is specified var totalHits = packages.LongCount(); if (return404NotFoundWhenNoResults && totalHits == 0) { return(NotFound()); } var pagedQueryable = packages .Take(options.Top != null ? Math.Min(options.Top.Value, MaxPageSize) : MaxPageSize) .ToV2FeedPackageQuery(GetSiteRoot(), _configurationService.Features.FriendlyLicenses); return(QueryResult(options, pagedQueryable, MaxPageSize, totalHits, (o, s, resultCount) => SearchAdaptor.GetNextLink(Request.RequestUri, resultCount, new { id }, o, s))); } } catch (Exception ex) { // Swallowing Exception intentionally. If *anything* goes wrong in search, just fall back to the database. // We don't want to break package restores. We do want to know if this happens, so here goes: QuietLog.LogHandledException(ex); } if (return404NotFoundWhenNoResults && !packages.Any()) { return(NotFound()); } var queryable = packages.ToV2FeedPackageQuery(GetSiteRoot(), _configurationService.Features.FriendlyLicenses); return(QueryResult(options, queryable, MaxPageSize)); }