public async Task <IHttpActionResult> Get(ODataQueryOptions <V2FeedPackage> options) { // Setup the search var packages = _packagesRepository.GetAll() .Where(p => !p.Deleted && p.SemVerLevelKey == SemVerLevelKey.Unknown) .WithoutSortOnColumn(Version) .WithoutSortOnColumn(Id, ShouldIgnoreOrderById <V2FeedPackage>(options)) .InterceptWith(new NormalizeVersionInterceptor()); // Try the search service try { 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, curatedFeed : null); // 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(); 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, null, 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); } //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); return(QueryResult(options, queryable, MaxPageSize)); }
public void IsHijackableReturnsFalseIfFilterContainsSubstringOf(string uri) { // Arrange var requestUri = new Uri(uri); // Act HijackableQueryParameters hijackableQueryParameters = null; var result = SearchHijacker.IsHijackable(GetODataQueryOptionsForTest(requestUri), out hijackableQueryParameters); // Assert Assert.False(result); }
public async Task <IHttpActionResult> Get( ODataQueryOptions <V2FeedPackage> options, [FromUri] string semVerLevel = null) { bool result = TryShouldIgnoreOrderById(options, out var shouldIgnoreOrderById); if (!result) { return(BadRequest("Invalid OrderBy parameter")); } // Setup the search var packages = GetAll() .Where(p => p.PackageStatusKey == PackageStatus.Available) .Where(SemVerLevelKey.IsPackageCompliantWithSemVerLevelPredicate(semVerLevel)) .WithoutSortOnColumn(Version) .WithoutSortOnColumn(Id, shouldIgnoreOrderById) .InterceptWith(new NormalizeVersionInterceptor()); var semVerLevelKey = SemVerLevelKey.ForSemVerLevel(semVerLevel); bool?customQuery = null; var isNonHijackEnabled = _featureFlagService.IsODataV2GetAllNonHijackedEnabled(); // 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 (ODataException ex) when(isNonHijackEnabled && ex.InnerException != null && ex.InnerException is FormatException) { // Sometimes users make invalid requests. It's not exceptional behavior, don't trace. } catch (Exception ex) when(isNonHijackEnabled) { // 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 (!isNonHijackEnabled) { return(BadRequest(Strings.ODataParametersDisabled)); } // 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)); }