Azure 作业提交失败,出现 400 抱怨 Etag
Azure Job submission fails with 400 complaining about Etag
序言
我正在尝试使用 Azure REST API、使用 Python 2 和 requests
包为 Azure IoT 中心创建一个“ScheduleUpdateTwin”作业。
分析
响应请求
我将从 requests
日志行开始(隐藏中心名称):
DEBUG:urllib3.connectionpool:https://<myhubname>.azure-devices.net:443 "PUT /jobs/v2/j1505904104?api-version=2017-06-30 HTTP/1.1" 400 441
的确,req.status_code
是 400
。
req.content
是(稍微修改跟踪 ID):
{"Message":"ErrorCode:ArgumentInvalid;Error: BadRequest {\"Message\":\"ErrorCode:ArgumentInvalid;Missing or invalid etag for job type ScheduleUpdateTwin. ScheduleUpdateTwin job type is a force update, which only accepts \'*\' as the Etag.\",\"ExceptionMessage\":\"Tracking ID:xxxxxxxxxx8844a48f81e29359ba0279-TimeStamp:09/20/2017 10:41:45\"}","ExceptionMessage":"Tracking ID:xxxxxxxxxxe14888a51434047aef23d0-G:5-TimeStamp:09/20/2017 10:41:46"}
回应headers
{'Content-Length': '441',
'Content-Type': 'application/json; charset=utf-8',
'Date': 'Wed, 20 Sep 2017 11:10:12 GMT',
'Server': 'Microsoft-HTTPAPI/2.0',
'iothub-errorcode': 'ArgumentInvalid'}
请求headers
我的请求(发送到 Azure API 端点)的 headers 是(同样,破坏私有数据):
{'Accept': '*/*',
'Accept-Encoding': 'gzip, deflate',
'Authorization': 'SharedAccessSignature '
'sr=<myhubname>.azure-devices.net%2Fjobs&skn=<skn>&sig=<sig>&se=<se>',
'Connection': 'keep-alive',
'Content-Length': '227',
'Content-Type': 'application/json',
'If-Match': '*',
'User-Agent': 'python-requests/2.18.1'}
请求body
这里是(pretty-printed 在这里发帖,所以 Content-Length 显然会有所不同)请求 body:
{
"maxExecutionTimeInSeconds": 3600,
"updateTwin": {
"properties": {
"desired": {
"version": "5.0.0"
}
},
"tags": {
"owner": "tzot"
}
},
"jobId": "j1505904104",
"type": "scheduleUpdateTwin",
"queryCondition": "deviceId = 'test_rpi_01'"
}
If-None-Match 而不是 If-Match
当然,documentation提示应该提供If-None-Match
,因为这是一个PUT
。所以我改变了我的代码并发送了一个 If-None-Match: *
;响应又是 400
。
其他 REST API 调用工作正常
请注意,其他 REST API 调用,如 devices/{device_id}
在没有设置 Etag 的情况下可以很好地用于 GET
、PUT
和 DELETE
操作; twins/{device_id}
(GET
、PATCH
)和twins/{device_id}/methods
(POST
)也是如此。
API版本
我使用的API
版本是:api-version=2017-06-30
结语
如何通过 REST API 调用向 Azure IoT 提交作业?
更新
在请求中添加"etag": "*" JSON
经过Rita Han的建议,我在请求body中添加了"etag": "*"
键,变成了(注:new jobId):
{
"jobId": "j1505986505",
"maxExecutionTimeInSeconds": 3600,
"etag": "*",
"updateTwin": {
"properties": {
"desired": {
"version": "5.0.0"
}
},
"tags": {
"owner": "tzot"
}
},
"type": "scheduleUpdateTwin",
"queryCondition": "deviceId = 'test_rpi_01'"
}
结果相同:HTTP 400状态码,响应内容相同。在 HTTP 请求 headers 中尝试使用 If-Match: *
,然后使用 If-None-Match: *
,然后使用 If-None-Match: blabla
,希望现有的 ETag 不会与“blabla”匹配。都无济于事。响应是一样的。
解决方案
内容应在 updateTwin
值内包含一个 etag
属性。
如错误信息指出:
Missing or invalid etag for job type ScheduleUpdateTwin.
ScheduleUpdateTwin job type is a force update, which only accepts
\'*\' as the Etag.
您可以这样修改您的请求正文:
{
"maxExecutionTimeInSeconds": 3600,
"updateTwin": {
"properties": {
"desired": {
"version": "5.0.0"
}
},
"etag":"*",
},
"jobId": "j1505904104",
"type": "scheduleUpdateTwin",
"queryCondition": "deviceId = 'test_rpi_01'"
}
更新:
添加python测试结果:
序言
我正在尝试使用 Azure REST API、使用 Python 2 和 requests
包为 Azure IoT 中心创建一个“ScheduleUpdateTwin”作业。
分析
响应请求
我将从 requests
日志行开始(隐藏中心名称):
DEBUG:urllib3.connectionpool:https://<myhubname>.azure-devices.net:443 "PUT /jobs/v2/j1505904104?api-version=2017-06-30 HTTP/1.1" 400 441
的确,req.status_code
是 400
。
req.content
是(稍微修改跟踪 ID):
{"Message":"ErrorCode:ArgumentInvalid;Error: BadRequest {\"Message\":\"ErrorCode:ArgumentInvalid;Missing or invalid etag for job type ScheduleUpdateTwin. ScheduleUpdateTwin job type is a force update, which only accepts \'*\' as the Etag.\",\"ExceptionMessage\":\"Tracking ID:xxxxxxxxxx8844a48f81e29359ba0279-TimeStamp:09/20/2017 10:41:45\"}","ExceptionMessage":"Tracking ID:xxxxxxxxxxe14888a51434047aef23d0-G:5-TimeStamp:09/20/2017 10:41:46"}
回应headers
{'Content-Length': '441',
'Content-Type': 'application/json; charset=utf-8',
'Date': 'Wed, 20 Sep 2017 11:10:12 GMT',
'Server': 'Microsoft-HTTPAPI/2.0',
'iothub-errorcode': 'ArgumentInvalid'}
请求headers
我的请求(发送到 Azure API 端点)的 headers 是(同样,破坏私有数据):
{'Accept': '*/*',
'Accept-Encoding': 'gzip, deflate',
'Authorization': 'SharedAccessSignature '
'sr=<myhubname>.azure-devices.net%2Fjobs&skn=<skn>&sig=<sig>&se=<se>',
'Connection': 'keep-alive',
'Content-Length': '227',
'Content-Type': 'application/json',
'If-Match': '*',
'User-Agent': 'python-requests/2.18.1'}
请求body
这里是(pretty-printed 在这里发帖,所以 Content-Length 显然会有所不同)请求 body:
{
"maxExecutionTimeInSeconds": 3600,
"updateTwin": {
"properties": {
"desired": {
"version": "5.0.0"
}
},
"tags": {
"owner": "tzot"
}
},
"jobId": "j1505904104",
"type": "scheduleUpdateTwin",
"queryCondition": "deviceId = 'test_rpi_01'"
}
If-None-Match 而不是 If-Match
当然,documentation提示应该提供If-None-Match
,因为这是一个PUT
。所以我改变了我的代码并发送了一个 If-None-Match: *
;响应又是 400
。
其他 REST API 调用工作正常
请注意,其他 REST API 调用,如 devices/{device_id}
在没有设置 Etag 的情况下可以很好地用于 GET
、PUT
和 DELETE
操作; twins/{device_id}
(GET
、PATCH
)和twins/{device_id}/methods
(POST
)也是如此。
API版本
我使用的API
版本是:api-version=2017-06-30
结语
如何通过 REST API 调用向 Azure IoT 提交作业?
更新
在请求中添加"etag": "*" JSON
经过Rita Han的建议,我在请求body中添加了"etag": "*"
键,变成了(注:new jobId):
{
"jobId": "j1505986505",
"maxExecutionTimeInSeconds": 3600,
"etag": "*",
"updateTwin": {
"properties": {
"desired": {
"version": "5.0.0"
}
},
"tags": {
"owner": "tzot"
}
},
"type": "scheduleUpdateTwin",
"queryCondition": "deviceId = 'test_rpi_01'"
}
结果相同:HTTP 400状态码,响应内容相同。在 HTTP 请求 headers 中尝试使用 If-Match: *
,然后使用 If-None-Match: *
,然后使用 If-None-Match: blabla
,希望现有的 ETag 不会与“blabla”匹配。都无济于事。响应是一样的。
解决方案
内容应在 updateTwin
值内包含一个 etag
属性。
如错误信息指出:
Missing or invalid etag for job type ScheduleUpdateTwin. ScheduleUpdateTwin job type is a force update, which only accepts \'*\' as the Etag.
您可以这样修改您的请求正文:
{
"maxExecutionTimeInSeconds": 3600,
"updateTwin": {
"properties": {
"desired": {
"version": "5.0.0"
}
},
"etag":"*",
},
"jobId": "j1505904104",
"type": "scheduleUpdateTwin",
"queryCondition": "deviceId = 'test_rpi_01'"
}
更新:
添加python测试结果: