Python 请求:多部分,其中一个部分为 json
Python Requests: Multipart with one part as json
Netflix 的精灵 API 将 JSON or multipart 与 application/json
中的一个部分 request
和 application/octet-stream
中任意数量的 attachment
部分相结合。
请求使一个简单的 JSON POST 非常简单:
requests.post(
url=self.host + self.endpoint,
json={
"version" : "1.0",
"user" : "genie",
"name" : "List * ... Directories bash job",
"description" : "Genie 3 Test Job",
"configs" : [ "/home/travis/build/Netflix/genie/genie-web/build/resources/test/com/netflix/genie/web/controllers/JobRestControllerIntegrationTests/job/config1" ],
"dependencies" : [ "/home/travis/build/Netflix/genie/genie-web/build/resources/test/com/netflix/genie/web/controllers/JobRestControllerIntegrationTests/job/dep1" ],
"setupFile" : "/home/travis/build/Netflix/genie/genie-web/build/resources/test/com/netflix/genie/web/controllers/JobRestControllerIntegrationTests/job/jobsetupfile",
"commandArgs" : "-c 'echo hello world'",
"clusterCriterias" : [ {
"tags" : [ "localhost" ]
} ],
"commandCriteria" : [ "bash" ],
},
)
命令有限,因此如果您要发送的命令(查询)很大,最好使用附件。
有了请求,请求多部分也不难:
requests.post(
url=self.host + self.endpoint,
json={
"version" : "1.0",
"user" : "genie",
"name" : "List * ... Directories bash job",
"description" : "Genie 3 Test Job",
"configs" : [ "/home/travis/build/Netflix/genie/genie-web/build/resources/test/com/netflix/genie/web/controllers/JobRestControllerIntegrationTests/job/config1" ],
"dependencies" : [ "/home/travis/build/Netflix/genie/genie-web/build/resources/test/com/netflix/genie/web/controllers/JobRestControllerIntegrationTests/job/dep1" ],
"setupFile" : "/home/travis/build/Netflix/genie/genie-web/build/resources/test/com/netflix/genie/web/controllers/JobRestControllerIntegrationTests/job/jobsetupfile",
"commandArgs" : "-c 'cat query.sql'",
"clusterCriterias" : [ {
"tags" : [ "localhost" ]
} ],
"commandCriteria" : [ "bash" ],
},
files={
"attachment": (
'query.sql',
'select count(1) from small_table;',
'application/octet-stream'
),
},
)
除非,如果 files
存在,它将忽略 json
,如果我将 json
更改为 data
,它将是一个表单。我可以将 JSON 字典移动到 files
字典中,但它似乎没有像 JSON 那样处理,现在我需要使用包对其进行编码?
我问是因为 requests
在参数和响应中处理 json object 我怀疑它也会在某个地方处理多部分表单,否则我会引入 json
只为 json.dumps(...)
此外:
- 似乎没有办法发送多个名为
attachment
的部分,如果您需要多个附加文件,api 会 allow/expect。 [在我的评论中,这可以通过将 files
更改为列表 name-to-file 对的列表来完成。
- 示例请求显示部分 headers 的名称未加引号,例如
Content-Disposition: form-data; name=request
和 Content-Disposition: form-data; name=attachment
,而请求包似乎生成 Content-Disposition: form-data; name="attachment"
。
“我可以将 JSON 字典移动到文件字典中,但它似乎没有像 JSON 那样处理”
- You can dump the dict to JSON files on disk.
tempfile.TemporaryFile
can of use. Dump, request, clean and repeat
“否则我将 json 引入只是为了 json.dumps(...)”
- It is okay to do this if you need to keep the dict around and the request built during run (ignore 1 for this use-case). However, remember to convert the dumps to io.BytesIO objects so that requests can compute the content-length header.
Also, remember to pass the content type for the files as "application/octet-stream" and not "plain/text"
“示例请求显示部分 headers 的名称未加引号”
I don't think that it should matter. RFC 2183 documents that parameter values of length < 78 but containing tspecials should be represented as quoted-string.
While the value for the name parameter doesn't include tspecials, this is more robust handling for short values IMO.
Netflix 的精灵 API 将 JSON or multipart 与 application/json
中的一个部分 request
和 application/octet-stream
中任意数量的 attachment
部分相结合。
请求使一个简单的 JSON POST 非常简单:
requests.post(
url=self.host + self.endpoint,
json={
"version" : "1.0",
"user" : "genie",
"name" : "List * ... Directories bash job",
"description" : "Genie 3 Test Job",
"configs" : [ "/home/travis/build/Netflix/genie/genie-web/build/resources/test/com/netflix/genie/web/controllers/JobRestControllerIntegrationTests/job/config1" ],
"dependencies" : [ "/home/travis/build/Netflix/genie/genie-web/build/resources/test/com/netflix/genie/web/controllers/JobRestControllerIntegrationTests/job/dep1" ],
"setupFile" : "/home/travis/build/Netflix/genie/genie-web/build/resources/test/com/netflix/genie/web/controllers/JobRestControllerIntegrationTests/job/jobsetupfile",
"commandArgs" : "-c 'echo hello world'",
"clusterCriterias" : [ {
"tags" : [ "localhost" ]
} ],
"commandCriteria" : [ "bash" ],
},
)
命令有限,因此如果您要发送的命令(查询)很大,最好使用附件。
有了请求,请求多部分也不难:
requests.post(
url=self.host + self.endpoint,
json={
"version" : "1.0",
"user" : "genie",
"name" : "List * ... Directories bash job",
"description" : "Genie 3 Test Job",
"configs" : [ "/home/travis/build/Netflix/genie/genie-web/build/resources/test/com/netflix/genie/web/controllers/JobRestControllerIntegrationTests/job/config1" ],
"dependencies" : [ "/home/travis/build/Netflix/genie/genie-web/build/resources/test/com/netflix/genie/web/controllers/JobRestControllerIntegrationTests/job/dep1" ],
"setupFile" : "/home/travis/build/Netflix/genie/genie-web/build/resources/test/com/netflix/genie/web/controllers/JobRestControllerIntegrationTests/job/jobsetupfile",
"commandArgs" : "-c 'cat query.sql'",
"clusterCriterias" : [ {
"tags" : [ "localhost" ]
} ],
"commandCriteria" : [ "bash" ],
},
files={
"attachment": (
'query.sql',
'select count(1) from small_table;',
'application/octet-stream'
),
},
)
除非,如果 files
存在,它将忽略 json
,如果我将 json
更改为 data
,它将是一个表单。我可以将 JSON 字典移动到 files
字典中,但它似乎没有像 JSON 那样处理,现在我需要使用包对其进行编码?
我问是因为 requests
在参数和响应中处理 json object 我怀疑它也会在某个地方处理多部分表单,否则我会引入 json
只为 json.dumps(...)
此外:
- 似乎没有办法发送多个名为
attachment
的部分,如果您需要多个附加文件,api 会 allow/expect。 [在我的评论中,这可以通过将files
更改为列表 name-to-file 对的列表来完成。 - 示例请求显示部分 headers 的名称未加引号,例如
Content-Disposition: form-data; name=request
和Content-Disposition: form-data; name=attachment
,而请求包似乎生成Content-Disposition: form-data; name="attachment"
。
“我可以将 JSON 字典移动到文件字典中,但它似乎没有像 JSON 那样处理”
- You can dump the dict to JSON files on disk.
tempfile.TemporaryFile
can of use. Dump, request, clean and repeat
“否则我将 json 引入只是为了 json.dumps(...)”
- It is okay to do this if you need to keep the dict around and the request built during run (ignore 1 for this use-case). However, remember to convert the dumps to io.BytesIO objects so that requests can compute the content-length header.
Also, remember to pass the content type for the files as "application/octet-stream" and not "plain/text"
“示例请求显示部分 headers 的名称未加引号”
I don't think that it should matter. RFC 2183 documents that parameter values of length < 78 but containing tspecials should be represented as quoted-string.
While the value for the name parameter doesn't include tspecials, this is more robust handling for short values IMO.