Skip to content

[core-http] de-serialize before checking internalError#12150

Merged
jeremymeng merged 4 commits into
Azure:masterfrom
jeremymeng:corehttp-deserialize-error-response-before-checking-innererror
Nov 3, 2020
Merged

[core-http] de-serialize before checking internalError#12150
jeremymeng merged 4 commits into
Azure:masterfrom
jeremymeng:corehttp-deserialize-error-response-before-checking-innererror

Conversation

@jeremymeng
Copy link
Copy Markdown
Member

Currently we check parsedBody.error or parsedBody for code and
message to use in the RestError to be thrown. However, we do this
on the raw object from parsing XML.

In the example added to the test, without this fix, the parsedBody
from xml parsing is

{ Code: "ContainerAlreadyExists", Message: "The specified container already exists." }

but we are accessing the properties with lowercase code and message.

We should check on the object after de-serializing when we have error
object properly mapped already.

Currently we check `parsedBody.error` or `parsedBody` for `code` and
`message` to use in the `RestError` to be thrown. However, we do this
on the raw object from parsing XML.

In the example added to the test, without this fix, the `parsedBody`
from xml parsing is
```js
{ Code: "ContainerAlreadyExists", Message: "The specified container already exists." }
```
but we are accessing the properties with lowercase `code` and `message`.

We should check on the object after de-serializing when we have error
object properly mapped already.
Copy link
Copy Markdown
Contributor

@HarshaNalluru HarshaNalluru left a comment

Choose a reason for hiding this comment

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

Nice one!

// If error response has a body, try to extract error code & message from it
// Then try to deserialize it using default body mapper
// If error response has a body, try to deserialize it using default body mapper.
// Then try to extract error code & message from it
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Changelog?

@ljian3377
Copy link
Copy Markdown
Member

ljian3377 commented Oct 30, 2020

Well done. One remaining issue here is the err.code is still undefined. Reproduce with this case.
https://github.com/jeremymeng/azure-sdk-for-js/blob/5563bb80173184f84e3b8760f263f543b91ac125/sdk/storage/storage-blob/test/blockblobclient.spec.ts#L389

Looks like we are missing the mapping for Code. Do you know how to change this in the generated code?
https://github.com/jeremymeng/azure-sdk-for-js/blob/5563bb80173184f84e3b8760f263f543b91ac125/sdk/storage/storage-blob/src/generated/src/models/mappers.ts#L104

export const StorageError: coreHttp.CompositeMapper = {
  serializedName: "StorageError",
  type: {
    name: "Composite",
    className: "StorageError",
    modelProperties: {
      message: {
        xmlName: "Message",
        serializedName: "Message",
        type: {
          name: "String"
        }
      }
    }
  }
};

export const DataLakeStorageErrorError: coreHttp.CompositeMapper = {
  serializedName: "DataLakeStorageError_error",
  type: {
    name: "Composite",
    className: "DataLakeStorageErrorError",
    modelProperties: {
      code: {
        xmlName: "Code",
        serializedName: "Code",
        type: {
          name: "String"
        }
      },
      message: {
        xmlName: "Message",
        serializedName: "Message",
        type: {
          name: "String"
        }
      }
    }
  }
};

Need to fix this for all four packages. And I wonder what the DataLakeStorageErrorError in Blob and StorageErrorError in DataLake are for.

@jeremymeng
Copy link
Copy Markdown
Member Author

One remaining issue here is the err.code

@ljian3377 yes, Storage side needs a swagger transformation to add the Code property.

Also note that this changes the Storage error message even though it's a bug fix. We might want to bump minor version of Storage packages.

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.

Looks good! Would you mind porting this fix to @azure/core-client?

@jeremymeng
Copy link
Copy Markdown
Member Author

Would you mind porting this fix to @azure/core-client?

Done porting. Was waiting for feedback first before porting.

@ljian3377
Copy link
Copy Markdown
Member

One remaining issue here is the err.code

@ljian3377 yes, Storage side needs a swagger transformation to add the Code property.

Also note that this changes the Storage error message even though it's a bug fix. We might want to bump minor version of Storage packages.

@jeremymeng FYI, we are going to release the GA version of the previous beta in the November release, which bumped up the minor version.

@ljian3377
Copy link
Copy Markdown
Member

When will this be merged?

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.

The deserialization logic is very complex, so I'm not sure if my comments all make sense. 😅

@@ -247,14 +243,26 @@ function handleErrorResponse(
}
}
if (error.response) {
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.

while reading this code, I'm not sure why this if is here, since error.response === parsedResponse and since we're already inside if (parsedResponse.parsedBody) presumably parsedResponse must be true.

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 if check was added in last change by @sarangan12? I will remove

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.

Checking on error.response removed.

Comment on lines +260 to +261
if (defaultBodyMapper) {
if (error.response) {
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't we combine these?

      if (defaultBodyMapper && error.response) {

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.

Checking on error.response removed.

deserializedError = operationSpec.serializer.deserialize(
defaultBodyMapper,
valueToDeserialize,
"error.response.parsedBody"
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.

This is trying to deserialize valueToDeserialize.error.response.parsedBody ? Is there a reason we don't pass that property in as the valueToDeserialize instead?

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 was trying to keep the current code/logic. It deserializes and assigns to error.response.parsedBody I was a little surprised that the code

          const errorResponse: FullOperationResponse = error.response;
          errorResponse.parsedBody = operationSpec.serializer.deserialize(

also updates error.response.parsedBody

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.

There is some extra handling of sequence type I think that's why valueToDeserialize is introduced.

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 const is also introduced in last PR. @sarangan12 do you remember the reason why this change?

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 guess it's to cast error.response back to FullOperationResponse so we can assign the parsedBody property. I updated this PR to remove the if check on error.response, and do as FulloperationResponse cast.

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.

I feel like this could be cleaned up more, but I am too scared to suggest any specific changes this close to release, so I think I'm good with it.

- Cast `error.response` back to `FullOperationResponse` so we could
assign it's `parsedBody` property
Copy link
Copy Markdown
Contributor

@sadasant sadasant left a comment

Choose a reason for hiding this comment

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

Looks good!

@jeremymeng jeremymeng merged commit ba864c0 into Azure:master Nov 3, 2020
@jeremymeng jeremymeng deleted the corehttp-deserialize-error-response-before-checking-innererror branch November 3, 2020 20:05
openapi-sdkautomation Bot pushed a commit to AzureSDKAutomation/azure-sdk-for-js that referenced this pull request Dec 29, 2020
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.

7 participants