1

I'm trying to send a HTML request via cURL in PowerShell. The code in question:

$command = 'curl -d @request.txt -o testoutput.xml -X "POST" -H @header.txt -u "username:password" "URL"'
Invoke-Expression $command

The HTML Body (-d) and Header (-H) need to be read from files, hence the @ before the filenames.

In order for this to work, I need to escape the @ so PowerShell doesn't interpret it as a splat operator - and that's my problem, nothing I've tried so far worked:

  • putting it in single quotes
  • here document (@" "@)
  • here string (@' '@)
  • using string templates with placeholders ("{0}request.txt" -f "@")
  • Unicode escape ("`u{0040}request.txt")

How do I escape the @ correctly? Or am I on the wrong path entirely? (I'm new to PowerShell sorry)

Kape
  • 13
  • 3
  • 1
    Use `--%`: `curl --% -d @request.txt -o testoutput.xml -X "POST" -H @header.txt -u "username:password" "URL"` - this will prevent the PowerShell parser from trying to evaluate anything following it – Mathias R. Jessen Jul 21 '21 at 14:07

1 Answers1

2

Invoke-Expression (iex) should generally be avoided; definitely don't use it to invoke an external program or PowerShell script.

Therefore:

  • invoke curl directly
  • and quote PowerShell metacharacters such as @ (see this answer for the full list) - either individually, with ` (e.g., `@), or by enclosing the entire argument in quotes ('...' or "...", as appropriate).
curl -d `@request.txt -o testoutput.xml -X "POST" -H @header.txt -u "username:password" "URL"

As for what you tried:

The primary concern about Invoke-Expression use is one of security: unwanted execution of (additional) commands potentially injected into the string passed to it.

In terms of functionality, Invoke-Expression is not only not needed for regular calls to external programs, it can create quoting headaches.

However, given that you're passing a '...' string to Invoke-Expression, quoting the @ as `@ would have worked, as shown in this simple example:

# OK, but generally do NOT do this.
Invoke-Expression 'Write-Output `@'

Had you used a "..." string, the ` would have been "eaten" by the up-front parsing of such an expandable string, based on the escaping rules explained in the conceptual about_Quoting_Rules help topic:

# BREAKS, because the ` is stripped before Invoke-Expression sees it.
Invoke-Expression "Write-Output `@"
mklement0
  • 382,024
  • 64
  • 607
  • 775