/// <summary> /// Creates a list of path segments for the specified URI query. /// </summary> /// <param name="queryUri">The absolute URI of the request.</param> /// <param name="serviceBaseUri">The service base URI for the request.</param> /// <returns>The <see cref="QueryToken"/> representing the query path.</returns> private QueryToken CreatePathSegments(Uri queryUri, Uri serviceBaseUri) { Debug.Assert(queryUri != null, "queryUri != null"); Debug.Assert(serviceBaseUri != null, "serviceBaseUri != null"); //// This method is a no-metadata, lexical only copy of RequestUriProcessor.CreateSegments List <string> uriSegments = this.EnumerateSegments(queryUri, serviceBaseUri); Debug.Assert(uriSegments.Count <= this.maxDepth, "uriSegments.Count <= this.maxDepth"); // The segment before the one being processed SegmentQueryToken parentNode = null; foreach (string uriSegment in uriSegments) { Debug.Assert(uriSegment != null, "uriSegment != null"); string segmentIdentifier; bool hasKeyValues = ExtractSegmentIdentifier(uriSegment, out segmentIdentifier); string keyValuesString = hasKeyValues ? uriSegment.Substring(segmentIdentifier.Length) : null; KeywordKind?keyword = QueryTokenUtils.ParseKeywordKind(segmentIdentifier); parentNode = keyword == null ? new SegmentQueryToken( segmentIdentifier, parentNode, hasKeyValues ? ParseKeyValues(keyValuesString) : null) : new KeywordSegmentQueryToken(keyword.Value, parentNode); } return(parentNode); }
/// <summary> /// Parses the <paramref name="queryUri"/> and returns a new instance of <see cref="SyntacticTree"/> /// describing the query specified by the uri. /// </summary> /// <param name="queryUri">The absolute URI which holds the query to parse. This must be a path relative to the <paramref name="serviceBaseUri"/>.</param> /// <param name="serviceBaseUri">The base URI of the service.</param> /// <param name="maxDepth">The maximum depth of any single query part. Security setting to guard against DoS attacks causing stack overflows and such.</param> /// <returns>A new instance of <see cref="SyntacticTree"/> which represents the query specified in the <paramref name="queryUri"/>.</returns> public static SyntacticTree ParseUri(Uri queryUri, Uri serviceBaseUri, int maxDepth) { ExceptionUtils.CheckArgumentNotNull(queryUri, "queryUri"); if (!queryUri.IsAbsoluteUri) { throw new ArgumentException(Strings.SyntacticTree_UriMustBeAbsolute(queryUri), "queryUri"); } ExceptionUtils.CheckArgumentNotNull(serviceBaseUri, "serviceBaseUri"); if (!serviceBaseUri.IsAbsoluteUri) { throw new ArgumentException(Strings.SyntacticTree_UriMustBeAbsolute(serviceBaseUri), "serviceBaseUri"); } if (maxDepth <= 0) { throw new ArgumentException(Strings.SyntacticTree_MaxDepthInvalid, "maxDepth"); } UriPathParser pathParser = new UriPathParser(maxDepth); var path = pathParser.ParsePathIntoSegments(queryUri, serviceBaseUri); List <CustomQueryOptionToken> queryOptions = UriUtils.ParseQueryOptions(queryUri); QueryToken filter = null; string filterQuery = queryOptions.GetQueryOptionValueAndRemove(UriQueryConstants.FilterQueryOption); if (filterQuery != null) { UriQueryExpressionParser expressionParser = new UriQueryExpressionParser(maxDepth); filter = expressionParser.ParseFilter(filterQuery); } IEnumerable <OrderByToken> orderByTokens = null; string orderByQuery = queryOptions.GetQueryOptionValueAndRemove(UriQueryConstants.OrderByQueryOption); if (orderByQuery != null) { UriQueryExpressionParser expressionParser = new UriQueryExpressionParser(maxDepth); orderByTokens = expressionParser.ParseOrderBy(orderByQuery); } SelectToken select = null; string selectQuery = queryOptions.GetQueryOptionValueAndRemove(UriQueryConstants.SelectQueryOption); if (selectQuery != null) { ISelectExpandTermParser selectParser = SelectExpandTermParserFactory.Create(selectQuery); select = selectParser.ParseSelect(); } ExpandToken expand = null; string expandQuery = queryOptions.GetQueryOptionValueAndRemove(UriQueryConstants.ExpandQueryOption); if (expandQuery != null) { ISelectExpandTermParser expandParser = SelectExpandTermParserFactory.Create(expandQuery); expand = expandParser.ParseExpand(); } int? skip = null; string skipQuery = queryOptions.GetQueryOptionValueAndRemove(UriQueryConstants.SkipQueryOption); if (skipQuery != null) { int skipValue; if (!UriPrimitiveTypeParser.TryUriStringToNonNegativeInteger(skipQuery, out skipValue)) { throw new ODataException(Strings.SyntacticTree_InvalidSkipQueryOptionValue(skipQuery)); } skip = skipValue; } int? top = null; string topQuery = queryOptions.GetQueryOptionValueAndRemove(UriQueryConstants.TopQueryOption); if (topQuery != null) { int topValue; if (!UriPrimitiveTypeParser.TryUriStringToNonNegativeInteger(topQuery, out topValue)) { throw new ODataException(Strings.SyntacticTree_InvalidTopQueryOptionValue(topQuery)); } top = topValue; } string inlineCountQuery = queryOptions.GetQueryOptionValueAndRemove(UriQueryConstants.InlineCountQueryOption); InlineCountKind?inlineCount = QueryTokenUtils.ParseInlineCountKind(inlineCountQuery); string format = queryOptions.GetQueryOptionValueAndRemove(UriQueryConstants.FormatQueryOption); return(new SyntacticTree( path, filter, orderByTokens, select, expand, skip, top, inlineCount, format, queryOptions.Count == 0 ? null : new ReadOnlyCollection <CustomQueryOptionToken>(queryOptions))); }