New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Parsing encoded character with special meaning in ODataJsonLightContextUriParser #965

Closed
OfirArviv opened this Issue Oct 1, 2017 · 4 comments

Comments

Projects
None yet
2 participants
@OfirArviv

OfirArviv commented Oct 1, 2017

When receiving an OData response with 'odata.context' uri that contain encoded special characters with special meaning in uri parsing, for example %23 which is the encoding for '#', the OData client throws the following exception The context URL '[context url ]' is invalid.' This occur due to parsing the URI with 'UriFormat.Unescaped' param.

Assemblies affected

OData .Net lib 6.16.0 (and also 7.X by looking at the source code).

Reproduce steps

An example for a request that fails:

  1. Making the following OData GET request using a generated OData client :
    a. GET /api/v1.0/me/notes/classnotebooks/[guid]/students?$expand=members HTTP/1.1
  2. Receiving a valid response with one of the inner complex fields having a metadata property as following:
    a. "members@odata.context":"https://www.onenote.com/api/v1.0/$metadata#me/notes/classnotebooks('[guid]')/students('i%3A0%23.f%7Cmembership%7Cexample%40example.org')/members"

Expected result

The OData response is parsed normally.

Actual result

The following exception is thrown 'The context URL 'https://www.onenote.com/api/v1.0/$metadata#me/notes/classnotebooks('[guid]')/students('i%3A0%23.f%7Cmembership%7Cexample%40example.org')/members' is invalid.'

Additional detail

This is the main flow that cause this:

1. Processing the response is taking place in the OData client.
2. A new ODataJsonLightContextUriParser class is created with the context URI as it's input.
3. The class method TokenizeContextUri() is called.
4. The fragment of the context URI is parsed in the following line of codes:
	1. Uri contextUriFromPayload = this.parseResult.ContextUri; 
	2.  this.parseResult.Fragment = contextUriFromPayload.GetComponents(UriComponents.Fragment, UriFormat.Unescaped);
	* This is the root - using UriFormat.Unescaped instead of UriFormat.SafeUnescaped or UriFormat.UriEscaped*
5. Which results in parser.parseResult.Fragment = "me/notes/classnotebooks('[guid]')/students('i:0#.f|membership|example@example.org')/members"
6. A chain of methods continues until we get to the method ParseContextUriFragment() of the ODataJsonLightContextUriParser class is executed with the fragment variable as one of its parameters.
7. Which results in the following lines of code being exectued:
	1. var rawSegments = pathParser.ParsePathIntoSegments(pathUri, this.ServiceRoot); in  ODataUriParser class.
8. This results in the segments being 
	1. "me"
	2. "notes"
	3. "classnotebooks('[guid]')"
	4. "students('i:0"
9. The last segment is wrongly cut due to the special meaning of the '#' symbol!
10. After more lines of code the following method is executed ExtractSegmentIdentifierAndParenthesisExpression(string segmentText, ….) of the ODataPathParser class.
11. Because the parenthesis are illegal a "Microsoft.OData.Core.ODataException: 'Bad Request - Error in query syntax."  is thrown.
12. The ODataException is caught in the ParseContextUriFragment() method. The following exception is thrown all the way up the fails the OData call: Microsoft.OData.Core.ODataException: 'The context URL 'https://www.onenote.com/api/v1.0/$metadata#me/notes/classnotebooks('[giid]')/students('i%3A0%23.f%7Cmembership%7Cexample%40example.org')/members' is invalid.'

@biaol-odata biaol-odata added the P4 label Oct 2, 2017

@biaol-odata

This comment has been minimized.

Member

biaol-odata commented Oct 2, 2017

@OfirArviv: Thanks for the detailed message.
This looks like a bug related to the decoding of special characters in fragment. And I think your proposed fix of using UriFormat.SafeUnescaped is a right one. Can you please create a PR with additional test case? Thanks for your contribution to OData.

@biaol-odata

This comment has been minimized.

Member

biaol-odata commented Oct 3, 2017

@mikepizzo Can you please add any comments you might have? Thanks.

@OfirArviv

This comment has been minimized.

OfirArviv commented Oct 6, 2017

I will. As this is a bug, can I create a PR to the maintenance branch as well?

@biaol-odata

This comment has been minimized.

Member

biaol-odata commented Oct 6, 2017

@OfirArviv Eventually we need to. But for now, you can try to complete this on master branch first. Thanks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment