How to prevent cURL joining multiple `--data` values by &-symbol?

1

I'm using cURL to put some data onto a Redmine server. I want to use multiple --data-xxx options to build a valid XML request body. The command is like this:

curl -H "Content-Type: application/xml" \
  -H "X-Redmine-API-Key: $TOKEN" \
  -d "<?xml version=\"1.0\"?><wiki_page><text>" \
  --data-binary "@$FILE" \
  -d "</text></wiki_page>" \
  -X PUT http://some.redmine.site.com/projects/someproj/wiki/test.xml

However, as --data option documented:

If any of these options is used more than once on the same command line, the data pieces specified will be merged together with a separating &-symbol. Thus, using -d name=daniel -d skill=lousy would generate a post chunk that looks like name=daniel&skill=lousy.

I can understand the designer of cURL make it this way to help build a URL with query string. But in this situation, these added &-symbols will make my request XML body malformed. I can prepend "nbsp;" to the value to workaround this when it's after --data. But when it comes to the usage mixed with a file (--data-binary "@$FILE"), there are no way to work this out.

fwonce

Posted 2016-10-10T09:09:36.183

Reputation: 55

Sadly, I've read the manpage carefully and I can tell there is no option to change or suppress the interconnecting character. The only way I can think of is to complete concatenating the string before do curl. – fwonce – 2016-10-10T09:26:39.137

I think this question belongs to StackOverflow.

– Don't Root here plz... – 2016-10-10T09:32:51.730

Answers

2

Just pass everything as a single --data value, then. There are several ways you could do it:

  • For short files, 'include' the file's raw contents in the command:

    curl … -d "<?xml…?><wiki_page><text>$(cat "$FILE")</text></wiki_page>"
    
  • For longer files, create a temporary file containing the required data:

    temp=$(mktemp /tmp/redmineXXXXXXXX.xml)
    {
        echo "<?xml…>"
        echo "<wiki_page><text>"
        cat "$FILE"
        echo "</text></wiki_page>"
    } > "$temp"
    curl … -d "@$temp"
    rm -f "$temp"
    

user1686

Posted 2016-10-10T09:09:36.183

Reputation: 283 655

Thanks @grawity. Yep, there are several ways to do it indeed and I'll take one of them. Last words: whether cURL should provide an option to let users change this? Besides the case I brought up above, matrix-parameter URI also engages semicolon as the separator rather than the ampersand.

– fwonce – 2016-10-11T02:23:59.393

No, it shouldn't, because -d is not for building URIs – it's for building POST data. Specifically, it generates application/x-www-form-urlencoded formatted POST data, which always uses & as the separator. While this format is based on URI query strings, it is not the same thing. – user1686 – 2016-10-11T12:37:33.803