将curl命令转为ansible.builtin.uri模块上传Confluence附件失败排查
Confluence REST API上传附件:curl成功但Ansible uri模块报400错误
我使用curl调用Confluence REST API上传附件可正常执行,但切换为Ansible的ansible.builtin.uri模块时,返回400错误。
成功的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
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" }
问题原因与修复方案
核心问题
curl的-F参数会自动构造multipart/form-data格式的请求,包含file和comment两个表单字段;但当前Ansible任务仅将文件内容作为原始请求体发送,既不符合Confluence API要求的请求格式,也缺少comment参数,因此触发400错误。
修复后的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 body_format: form-multipart body: file: path: "{{ filepath }}" comment: "File attached via REST API" status_code: [200, 201] validate_certs: no
关键调整说明
- 用
body_format: form-multipart指定请求格式,模拟curl的-F参数行为,自动构造符合要求的multipart请求 - 通过
body定义表单字段:file字段通过path指定文件路径,comment字段对应curl中的注释内容 - 添加
status_code: [200, 201],覆盖Confluence API上传成功可能返回的200或201状态码,避免因状态码不匹配报错
内容的提问来源于stack exchange,提问作者jeremywat
相关产品推荐
相关产品推荐

