英文:
Converting 'curl' command to 'ansible.builtin.uri' module?
问题
我有一个文件附件,我正试图通过REST API上传到Confluence。我可以通过使用curl
复制他们的示例来做到这一点,但是在使用Ansible时失败了,我无法弄清楚原因。
这是curl
命令:
curl -u <username>:<password> -X POST -H "X-Atlassian-Token: nocheck" -F "file=@<filepath>" -F "comment=File attached via REST API" https://myconfluenceserver.com/rest/api/content/<page ID>/child/attachment
当然,< >
中的值已被替换为真实值。此命令成功执行。
这是Ansible
任务:
ansible.builtin.uri:
user: "{{ osa_credentials.username }}"
password: "{{ osa_credentials.password }}"
url: "{{ url }}"
method: POST
headers:
X-Atlassian-Token: nocheck
force_basic_auth: yes
src: "{{ filepath }}"
validate_certs: no
当我运行curl
命令时,它正常工作,但使用Ansible时会抛出错误 400
。以下是完整的错误文本:
fatal: [localhost]: FAILED! => {
"changed": false,
"connection": "close",
"content_language": "en",
"content_length": "435",
"content_type": "text/html;charset=utf-8",
"date": "Thu, 29 Jun 2023 06:34:10 GMT",
"elapsed": 1,
"invocation": {
"module_args": {
"attributes": null,
"body": null,
"body_format": "raw",
"ca_path": null,
"ciphers": null,
"client_cert": null,
"client_key": null,
"creates": null,
"decompress": true,
"dest": null,
"follow_redirects": "safe",
"force": false,
"force_basic_auth": true,
"group": null,
"headers": {
"Content-Length": 543818,
"X-Atlassian-Token": "nocheck"
},
"http_agent": "ansible-httpget",
"method": "POST",
"mode": null,
"owner": null,
"password": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER",
"remote_src": false,
"removes": null,
"return_content": false,
"selevel": null,
"serole": null,
"setype": null,
"seuser": null,
"src": "<filepath>",
"status_code": [
200
],
"timeout": 30,
"unix_socket": null,
"unredirected_headers": [],
"unsafe_writes": true,
"url": "https://myconfluenceserver.com/rest/api/content/<page ID>/child/attachment",
"url_password": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER",
"url_username": "<username>",
"use_gssapi": false,
"use_netrc": true,
"use_proxy": true,
"user": "<username>",
"validate_certs": false
}
},
"msg": "Status code was 400 and not [200]: HTTP Error 400: ",
"redirected": false,
"server": "Apache",
"status": 400,
"url": "https://myconfluenceserver.com/rest/api/content/<page ID>/child/attachment"
}
我漏掉了什么?
英文:
I have a file attachment I'm trying to upload to Confluence via the REST API. I can do it by replicating their example with curl
, but it's failing when using Ansible and I can't figure out why.
Here's the curl
command:
curl -u <username>:<password> -X POST -H "X-Atlassian-Token: nocheck" -F "file=@<filepath>" -F "comment=File attached via REST API" https://myconfluenceserver.com/rest/api/content/<page ID>/child/attachment
Of course the values in <>
are replaced with real values. This command is successful.
Here's the Ansible
task:
ansible.builtin.uri:
user: "{{ osa_credentials.username }}"
password: "{{ osa_credentials.password }}"
url: "{{ url }}"
method: POST
headers:
X-Atlassian-Token: nocheck
force_basic_auth: yes
src: "{{ filepath }}"
validate_certs: no
When I run the curl
command it works, but with Ansible it throws error 400
. Here is the full error text:
fatal: [localhost]: FAILED! => {
"changed": false,
"connection": "close",
"content_language": "en",
"content_length": "435",
"content_type": "text/html;charset=utf-8",
"date": "Thu, 29 Jun 2023 06:34:10 GMT",
"elapsed": 1,
"invocation": {
"module_args": {
"attributes": null,
"body": null,
"body_format": "raw",
"ca_path": null,
"ciphers": null,
"client_cert": null,
"client_key": null,
"creates": null,
"decompress": true,
"dest": null,
"follow_redirects": "safe",
"force": false,
"force_basic_auth": true,
"group": null,
"headers": {
"Content-Length": 543818,
"X-Atlassian-Token": "nocheck"
},
"http_agent": "ansible-httpget",
"method": "POST",
"mode": null,
"owner": null,
"password": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER",
"remote_src": false,
"removes": null,
"return_content": false,
"selevel": null,
"serole": null,
"setype": null,
"seuser": null,
"src": "<filepath>",
"status_code": [
200
],
"timeout": 30,
"unix_socket": null,
"unredirected_headers": [],
"unsafe_writes": true,
"url": "https://myconfluenceserver.com/rest/api/content/<page ID>/child/attachment",
"url_password": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER",
"url_username": "<username>",
"use_gssapi": false,
"use_netrc": true,
"use_proxy": true,
"user": "<username>",
"validate_certs": false
}
},
"msg": "Status code was 400 and not [200]: HTTP Error 400: ",
"redirected": false,
"server": "Apache",
"status": 400,
"url": "https://myconfluenceserver.com/rest/api/content/<page ID>/child/attachment"
}
What am I missing?
答案1
得分: 2
以下是您要翻译的内容:
Confluence REST API attachment - What content type to use? How to resolve HTTP Response Code 415?
根据Ansible uri
模块与 multipart/mixed
?以及以下的最小示例
---
- hosts: localhost
become: false
gather_facts: false
vars:
CONFLUENCE_USER: "user"
CONFLUENCE_PASSWORD: "test"
PAGE_ID: "123456789"
tasks:
- name: Test REST API - Confluence Attach File
ansible.builtin.uri:
user: "{{ CONFLUENCE_USER }}"
password: "{{ CONFLUENCE_PASSWORD }}"
url: "https://confluence.example.com/rest/api/content/{{ PAGE_ID }}/child/attachment"
validate_certs: yes
method: POST
headers:
X-Atlassian-Token: nocheck
force_basic_auth: yes
body_format: form-multipart
body:
file:
content: "{{ lookup('file','test.file') }}"
filename: test.file
register: result
- debug:
var: result.json.results
对Confluence的测试运行将成功地上传文件并输出如下:
TASK [debug] *********
ok: [localhost] =>
result.json.results:
- _expandable:
ancestors: ''
body: ''
children: /rest/api/content/987654321/child
descendants: /rest/api/content/987654321/descendant
history: /rest/api/content/987654321/history
operations: ''
restrictions: /rest/api/content/987654321/restriction/byOperation
space: /rest/api/space/~user
_links:
download: /download/attachments/123456789/test.file?version=1&modificationDate=1688109306468&api=v2
self: https://confluence.example.com/rest/api/content/987654321
webui: /display/~user/StackOverflow?preview=%2F123456789%2F987654321%2Ftest.file
...
status: current
title: test.file
type: attachment
...
那么应该使用什么正确的body格式,或者正确的完成这个任务的方法是什么?
使用以下内容:
body_format: form-multipart
body:
file:
content: "{{ lookup('file','test.file') }}"
filename: test.file
如man curl
中所述:
-F, --form <name=content>
(HTTP SMTP IMAP) 对于HTTP协议系列,这让
curl
模拟用户按下提交按钮后填写的表单。这使curl
按照RFC 2388的定义,使用Content-Type
multipart/form-data
来POST
数据。
文档
-
uri
模块 – 与Web服务交互 - 参数:body_format
使用
form-multipart
时,无法覆盖Content-Type
头form-multipart
在v2.10版本中添加。
英文:
> Confluence REST API attachment - What content type to use? How to resolve HTTP Response Code 415?
According Ansible uri
module with multipart/mixed
? and the following minimal example
---
- hosts: localhost
become: false
gather_facts: false
vars:
CONFLUENCE_USER: "user"
CONFLUENCE_PASSWORD: "test"
PAGE_ID: "123456789"
tasks:
- name: Test REST API - Confluence Attach File
ansible.builtin.uri:
user: "{{ CONFLUENCE_USER }}"
password: "{{ CONFLUENCE_PASSWORD }}"
url: "https://confluence.example.com/rest/api/content/{{ PAGE_ID }}/child/attachment"
validate_certs: yes
method: POST
headers:
X-Atlassian-Token: nocheck
force_basic_auth: yes
body_format: form-multipart
body:
file:
content: "{{ lookup('file','test.file') }}"
filename: test.file
register: result
- debug:
var: result.json.results
a test run against Confluence will successful result into a file upload and output of
TASK [debug] *********
ok: [localhost] =>
result.json.results:
- _expandable:
ancestors: ''
body: ''
children: /rest/api/content/987654321/child
descendants: /rest/api/content/987654321/descendant
history: /rest/api/content/987654321/history
operations: ''
restrictions: /rest/api/content/987654321/restriction/byOperation
space: /rest/api/space/~user
_links:
download: /download/attachments/123456789/test.file?version=1&modificationDate=1688109306468&api=v2
self: https://confluence.example.com/rest/api/content/987654321
webui: /display/~user/StackOverflow?preview=%2F123456789%2F987654321%2Ftest.file
...
status: current
title: test.file
type: attachment
...
> So what's the right body format to use, or what's the right way to accomplish this?
Using
body_format: form-multipart
body:
file:
content: "{{ lookup('file','test.file') }}"
filename: test.file
and as stated in man curl
> -F, --form <name=content>
>
> (HTTP SMTP IMAP) For HTTP protocol family, this lets curl
emulate a filled-in form in which a user has pressed the submit button. This causes curl
to POST
data using the Content-Type
multipart/form-data
according to RFC 2388
Documentation
-
uri
module – Interacts with webservices - Parameters:body_format
> The
Content-Type
header cannot be overridden when usingform-multipart
>
>form-multipart
was added in v2.10.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论