Skip to content

[core-http] Support overriding xml parser char key via options#12065

Merged
jeremymeng merged 5 commits into
Azure:masterfrom
jeremymeng:passing-xmlcharkey
Nov 4, 2020
Merged

[core-http] Support overriding xml parser char key via options#12065
jeremymeng merged 5 commits into
Azure:masterfrom
jeremymeng:passing-xmlcharkey

Conversation

@jeremymeng
Copy link
Copy Markdown
Member

@jeremymeng jeremymeng commented Oct 27, 2020

Currently our xml parser uses hard-coded _ as key to access parsed
xml element content. This causes issue like storage customer getting
errors listing blobs when they use _ as Blob metadata key.

This PR adds support to allow customizing the xml parser char key via
options. Currently xmlCharKey option is supported, with room for
other options (e.g., attr key for accessing parsed xml attributes).

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel it is useful to export the default value, since we now support overriding it.

@jeremymeng
Copy link
Copy Markdown
Member Author

What storage need to do after this change:
image

Currently our xml parser uses hard-coded `_` as key to access parsed
xml element content. This causes issue like storage customer getting
errors listing blobs when they use `_` as Blob metadata key.

This PR add support to allow customizing the xml parser char key via
options. Currently `xmlCharKey` option is supported, with room for
other xml parser options (e.g., attr key for accessing parsed xml
attributes).
Comment thread sdk/core/core-http/src/serializer.ts Outdated
Copy link
Copy Markdown
Member

@joheredi joheredi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

Copy link
Copy Markdown
Member

@xirzec xirzec left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I really like the approach here; my comments are all code style/cleanup ones.

Can we also apply this change to core-xml and friends?

(deserializationContentTypes && deserializationContentTypes.json) || defaultJsonContentTypes;
this.xmlContentTypes =
(deserializationContentTypes && deserializationContentTypes.xml) || defaultXmlContentTypes;
this.xmlCharKey = parsingOptions?.xmlCharKey || XML_CHARKEY;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

might as well be consistently fancy, right? ;)

Suggested change
this.xmlCharKey = parsingOptions?.xmlCharKey || XML_CHARKEY;
this.xmlCharKey = parsingOptions?.xmlCharKey ?? XML_CHARKEY;

constructor(
nextPolicy: RequestPolicy,
deserializationContentTypes: DeserializationContentTypes | undefined,
parsingOptions: { xmlCharKey?: string } | undefined,
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rather than putting a literal { xmlCharKey?: string } everywhere, can we write this down as a type? It'll make it much easier to add additional parsingOptions later if needed.


constructor(
nextPolicy: RequestPolicy,
deserializationContentTypes: DeserializationContentTypes | undefined,
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is there a reason these are all | undefined instead of making the parameters themselves optional with ??

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The last parameter is non-optional. I could move both parameters to be after request policy options

xmlContentTypes: string[],
operationResponse: HttpOperationResponse
operationResponse: HttpOperationResponse,
opts?: { includeRoot?: boolean; xmlCharKey?: string }
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

again I wonder if this should be an interface

Comment thread sdk/core/core-http/src/serializer.ts Outdated
responseBody = responseBody["_"];
if (
responseBody[XML_ATTRKEY] != undefined &&
responseBody[options?.xmlCharKey ?? XML_CHARKEY] != undefined
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

feels like we should assign the result of options?.xmlCharKey ?? XML_CHARKEY instead of calculating it twice. Why not just assign the final char key at the top of the method?

Comment thread sdk/core/core-http/src/serializer.ts Outdated
objectName: string,
isXml: boolean
isXml: boolean,
options?: { xmlCharKey?: string }
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

feels like this private method shouldn't have xmlCharKey be optional, since the caller already knows the final value

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

RIGHT! Making it required for private methods reveals some places where I missed passing the options

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh, you meant requiring xmlCharKey. I made options required.

After I replaced { xmlCharKey?: string } with an interface, I would need some type mapping to make this property required, and assert it when calling I think.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Made internal options Required<> as @xirzec suggested. I also rename the interface name to more generic SerializerOptions.

Comment thread sdk/core/core-http/src/serializer.ts Outdated
propertyMapper: Mapper,
serializedValue: any,
isXml: boolean,
options?: { xmlCharKey?: string }
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same thought, why make this optional everywhere? We should make it optional where it comes in from a public interface, but required everywhere else so we don't have default logic sprinkled everywhere.

Comment thread sdk/core/core-http/src/serviceClient.ts Outdated
urlParameterValue,
getPathStringFromParameter(urlParameter)
getPathStringFromParameter(urlParameter),
{ xmlCharKey: operationArguments.options?.parsingOptions?.xmlCharKey }
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we create this object once earlier in the method and pass it by reference in each place?

Comment thread sdk/core/core-http/src/serviceClient.ts Outdated
parameterMapper
);
serializer.serialize(parameterMapper, value, parameterPathString);
serializer.serialize(parameterMapper, value, parameterPathString, {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same thing, let's shorthand the last argument

- introduce XmlOptions interface

- Make xml options required for private methods

- Remove duplicate by introducing locals
@jeremymeng
Copy link
Copy Markdown
Member Author

Can we also apply this change to core-xml and friends?

Sure, I may do it in another PR as I am trying to ship core-http tomorrow.

Copy link
Copy Markdown
Member

@xirzec xirzec left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM.

I'm fine shipping this for this release, but if you wanted it to bake longer for the next release I wouldn't be opposed.


- Explicitly set `manual` redirect handling for node fetch. And fixing redirectPipeline [PR 11863](https://github.com/Azure/azure-sdk-for-js/pull/11863)
- Add support for multiple error response codes.[PR 11841](https://github.com/Azure/azure-sdk-for-js/)
- Add support for multiple error response codes. [PR 11841](https://github.com/Azure/azure-sdk-for-js/)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these notes should be in a newer section right or we need to fix the release date for 1.2.0 above, right?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The date will be fixed in #12258

mergeAttrs: false,
explicitRoot: true,
validator: null,
validator: undefined,
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if we're setting these to undefined, should we instead omit the keys entirely? Or would that do something different?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is unrelated to the fix, but I added the type xml2js.OptionsV2 and undefined are correct according to the type definitions. I believe this is a copy of all the supported xml2js settings so I will keep them listed here even we don't use any of them directly.

@jeremymeng
Copy link
Copy Markdown
Member Author

/azp run js - storage-blob - tests

@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines successfully started running 1 pipeline(s).

@jeremymeng
Copy link
Copy Markdown
Member Author

/azp run js - servicebus - tests

@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines successfully started running 1 pipeline(s).

@jeremymeng
Copy link
Copy Markdown
Member Author

/azp run js - storage-file-share - tests

@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines successfully started running 1 pipeline(s).

@jeremymeng
Copy link
Copy Markdown
Member Author

/azp run js - storage-queue - tests

@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines successfully started running 1 pipeline(s).

@jeremymeng
Copy link
Copy Markdown
Member Author

/azp run js - storage-file-datalake - tests

@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines successfully started running 1 pipeline(s).

@jeremymeng
Copy link
Copy Markdown
Member Author

Service Bus and Storage live tests are passing. I will merge this so we will have nightly test results of other libraries tomorrow for more confidence.

@jeremymeng jeremymeng merged commit d5c67cb into Azure:master Nov 4, 2020
@jeremymeng jeremymeng deleted the passing-xmlcharkey branch November 4, 2020 23:58
@HarshaNalluru
Copy link
Copy Markdown
Contributor

Service Bus and Storage live tests are passing. I will merge this so we will have nightly test results of other libraries tomorrow for more confidence.

FYI: I believe service-bus is unaffected by these changes since it isn't using the serializers from core-http. This would change once service-bus starts using the swagger and codegen instead of handwritten ATOM API.

@jeremymeng
Copy link
Copy Markdown
Member Author

atomXmlHelper uses parseXML and stringifyXML, which are touched in this PR

@HarshaNalluru
Copy link
Copy Markdown
Contributor

Oh, thanks!

jeremymeng added a commit to jeremymeng/azure-sdk-for-js that referenced this pull request Nov 19, 2020
…har key

Currently our xml parser uses hard-coded `_` as key to access parsed
xml element content. This causes issue like storage customer getting
errors listing blobs when they use `_` as Blob metadata key.

This PR adds support to allow customizing the xml parser char key via
options. Currently `xmlCharKey` option is supported, with room for
other xml parser options (e.g., attr key for accessing parsed xml
attributes).

- Introduced `XmlOptions` which is the same as `SerializerOptions`
currently but gives better separation of concerns.

- Fix two missing cases of replacement of "$" with XML_ATTRKEY in
core-http. We don't support customizing this yet so functionality
remains unchanged.

- Fixed typos

- Remove run time dependency on core-xml by duplicating XML_ATTRKEY, XML_CHARKEY, and XmlOptions in core-client.

- Address CR feedback: nest XmlOptions in SerializerOptions
jeremymeng added a commit that referenced this pull request Nov 20, 2020
…ey (#12418)

Currently our xml parser uses hard-coded `_` as key to access parsed
xml element content. This causes issue like storage customer getting
errors listing blobs when they use `_` as Blob metadata key.

This PR adds support to allow customizing the xml parser char key via
options. Currently `xmlCharKey` option is supported, with room for
other xml parser options (e.g., attr key for accessing parsed xml
attributes).

- Introduced `XmlOptions` which is the same as `SerializerOptions`
currently but gives better separation of concerns.

- Fix two missing cases of replacement of "$" with XML_ATTRKEY in
core-http. We don't support customizing this yet so functionality
remains unchanged.

- Remove run time dependency on core-xml by duplicating XML_ATTRKEY, XML_CHARKEY, and XmlOptions in core-client.

- Address CR feedback: nest XmlOptions in SerializerOptions
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants