Skip to content

Commit 87c886d

Browse files
authored
Fix error decoding of string body (Azure#31265)
1 parent c6be14f commit 87c886d

File tree

5 files changed

+102
-9
lines changed

5 files changed

+102
-9
lines changed

.vscode/cspell.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -504,6 +504,12 @@
504504
"specifed"
505505
]
506506
},
507+
{
508+
"filename": "sdk/tables/azure-data-tables/CHANGELOG.md",
509+
"words": [
510+
"kldtz"
511+
]
512+
},
507513
{
508514
"filename": "sdk/tables/test-resources.json",
509515
"words": [

sdk/tables/azure-data-tables/CHANGELOG.md

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,13 @@
11
# Release History
22

3-
## 12.4.4 (Unreleased)
3+
## 12.4.4 (2023-09-12)
44

55
### Features Added
66
* Enabled to specify resource type `container` in account SAS access.
77

8-
### Breaking Changes
9-
108
### Bugs Fixed
119
* Fixed a bug when submitting transactions with an empty operation list. ([#31471](https://github.com/Azure/azure-sdk-for-python/issues/31471))
10+
* Fixed a bug when decoding response body in string type. Thanks @kldtz for the contribution! ([#31265](https://github.com/Azure/azure-sdk-for-python/pull/31265))
1211

1312
### Other Changes
1413
* Bumped minimum dependency on `azure-core` to `>=1.27.1`. ([#28918](https://github.com/Azure/azure-sdk-for-python/issues/28918))

sdk/tables/azure-data-tables/azure/data/tables/_error.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,13 +139,17 @@ def _decode_error(response, error_message=None, error_type=None, **kwargs): # p
139139
additional_data[info.tag] = info.text
140140
else:
141141
if error_body:
142+
# Attempt to parse from XML element
142143
for info in error_body.iter():
143144
if info.tag.lower().find("code") != -1:
144145
error_code = info.text
145146
elif info.tag.lower().find("message") != -1:
146147
error_message = info.text
147148
else:
148149
additional_data[info.tag] = info.text
150+
except AttributeError:
151+
# Response body wasn't XML, give up trying to parse
152+
error_message = str(error_body)
149153
except DecodeError:
150154
pass
151155

sdk/tables/azure-data-tables/tests/test_table_batch.py

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,14 @@
88
from datetime import datetime, timedelta
99
import os
1010
import pytest
11-
11+
from functools import partial
12+
from requests import Response
1213
from devtools_testutils import AzureRecordedTestCase, recorded_by_proxy, set_custom_default_matcher
1314

1415
from azure.core import MatchConditions
16+
from azure.core.pipeline import PipelineRequest, PipelineResponse
1517
from azure.core.pipeline.policies import HTTPPolicy
18+
from azure.core.pipeline.transport._requests_basic import RequestsTransportResponse
1619
from azure.core.credentials import AzureNamedKeyCredential, AzureSasCredential
1720
from azure.core.exceptions import ResourceNotFoundError, ClientAuthenticationError, HttpResponseError
1821
from azure.data.tables import (
@@ -30,6 +33,7 @@
3033
TableClient,
3134
)
3235
from azure.data.tables._constants import DEFAULT_STORAGE_ENDPOINT_SUFFIX
36+
from azure.identity import DefaultAzureCredential
3337
from _shared.testcase import TableTestCase
3438
from preparers import tables_decorator
3539

@@ -1243,3 +1247,41 @@ def test_batch_url_for_cosmos_emulator(self):
12431247
assert table.scheme == "http"
12441248
with pytest.raises(RequestCorrect):
12451249
table.submit_transaction(self.batch)
1250+
1251+
def test_decode_string_body(self):
1252+
def patch_run(request: PipelineRequest, **kwargs) -> PipelineResponse:
1253+
response = Response()
1254+
response.status_code = 405
1255+
response._content = b"<!DOCTYPE html><html><head><title>UnsupportedHttpVerb</title></head><body><h1>The resource doesn't support specified Http Verb.</h1><p><ul><li>HttpStatusCode: 405</li><li>ErrorCode: UnsupportedHttpVerb</li><li>RequestId : 98adf858-a01e-0071-2580-bfe811000000</li><li>TimeStamp : 2023-07-26T05:19:26.9825582Z</li></ul></p></body></html>"
1256+
response.url = "https://<storage>.z6.web.core.windows.net/$batch"
1257+
response.headers = {"x-ms-error-code": "UnsupportedHttpVerb", "content-type": "text/html"}
1258+
return PipelineResponse(
1259+
http_request=None,
1260+
http_response=RequestsTransportResponse(
1261+
requests_response=response,
1262+
request=None,
1263+
),
1264+
context=None,
1265+
)
1266+
1267+
with TableClient(
1268+
endpoint="https://<storage>.z6.web.core.windows.net/",
1269+
credential=DefaultAzureCredential(),
1270+
table_name="syncenabled",
1271+
) as client:
1272+
client._client._client._pipeline.run = partial(patch_run)
1273+
with pytest.raises(HttpResponseError) as ex:
1274+
client.submit_transaction(
1275+
[
1276+
(
1277+
"upsert",
1278+
{
1279+
"PartitionKey": "test-partition",
1280+
"RowKey": "test-key",
1281+
"name": "test-name",
1282+
},
1283+
)
1284+
]
1285+
)
1286+
assert ex.value.status_code == 405
1287+
assert ex.value.error_code == "UnsupportedHttpVerb"

sdk/tables/azure-data-tables/tests/test_table_batch_async.py

Lines changed: 47 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,18 @@
55
# Licensed under the MIT License. See License.txt in the project root for
66
# license information.
77
# --------------------------------------------------------------------------
8-
9-
import pytest
10-
118
from datetime import datetime, timedelta
129
import os
13-
10+
import pytest
11+
from functools import partial
12+
from requests import Response
1413
from devtools_testutils import AzureRecordedTestCase, set_custom_default_matcher
1514
from devtools_testutils.aio import recorded_by_proxy_async
1615

1716
from azure.core import MatchConditions
17+
from azure.core.pipeline import PipelineRequest, PipelineResponse
1818
from azure.core.pipeline.policies import AsyncHTTPPolicy
19+
from azure.core.pipeline.transport._requests_asyncio import AsyncioRequestsTransportResponse
1920
from azure.core.credentials import AzureSasCredential, AzureNamedKeyCredential
2021
from azure.core.exceptions import ResourceNotFoundError, ClientAuthenticationError, HttpResponseError
2122
from azure.data.tables.aio import TableServiceClient, TableClient
@@ -32,7 +33,7 @@
3233
TableErrorCode,
3334
)
3435
from azure.data.tables._constants import DEFAULT_STORAGE_ENDPOINT_SUFFIX
35-
36+
from azure.identity.aio import DefaultAzureCredential
3637
from _shared.asynctestcase import AsyncTableTestCase
3738
from async_preparers import tables_decorator_async
3839

@@ -1178,3 +1179,44 @@ async def test_batch_url_for_cosmos_emulator(self):
11781179
assert table.scheme == "http"
11791180
with pytest.raises(RequestCorrect):
11801181
await table.submit_transaction(self.batch)
1182+
1183+
@pytest.mark.asyncio
1184+
async def test_decode_string_body(self):
1185+
async def patch_run(request: PipelineRequest, **kwargs) -> PipelineResponse:
1186+
response = Response()
1187+
response.status_code = 405
1188+
response._content = b"<!DOCTYPE html><html><head><title>UnsupportedHttpVerb</title></head><body><h1>The resource doesn't support specified Http Verb.</h1><p><ul><li>HttpStatusCode: 405</li><li>ErrorCode: UnsupportedHttpVerb</li><li>RequestId : 98adf858-a01e-0071-2580-bfe811000000</li><li>TimeStamp : 2023-07-26T05:19:26.9825582Z</li></ul></p></body></html>"
1189+
response.url = "https://<storage>.z6.web.core.windows.net/$batch"
1190+
response.headers = {"x-ms-error-code": "UnsupportedHttpVerb", "content-type": "text/html"}
1191+
return PipelineResponse(
1192+
http_request=None,
1193+
http_response=AsyncioRequestsTransportResponse(
1194+
requests_response=response,
1195+
request=None,
1196+
),
1197+
context=None,
1198+
)
1199+
1200+
client = TableClient(
1201+
endpoint=self.account_url(self.tables_storage_account_name, "table"),
1202+
credential=DefaultAzureCredential(
1203+
name=self.tables_storage_account_name, key=self.tables_primary_storage_account_key
1204+
),
1205+
table_name="syncenabled",
1206+
)
1207+
client._client._client._pipeline.run = partial(patch_run)
1208+
with pytest.raises(HttpResponseError) as ex:
1209+
await client.submit_transaction(
1210+
[
1211+
(
1212+
"upsert",
1213+
{
1214+
"PartitionKey": "test-partition",
1215+
"RowKey": "test-key",
1216+
"name": "test-name",
1217+
},
1218+
)
1219+
]
1220+
)
1221+
assert ex.value.status_code == 405
1222+
assert ex.value.error_code == "UnsupportedHttpVerb"

0 commit comments

Comments
 (0)