miserable
miserable

Reputation: 727

Curl in PowerShell with custom cookie file

The following curl command works fine in cmd:

curl -L -c ./cookie -b ./cookie -X POST -H "Accept: application/json" -s -d "{\"accountId\":\"123456789\",\"partition\":\"abc\",\"duration\":1234}" https://testabc.com

When I try to run the same from PowerShell, I get the -c is ambiguous error. I tried replacing -c with SessionVariable, but then I start getting the following error:

Invoke-WebRequest : Missing an argument for parameter 'SessionVariable'. Specify a parameter of type 'System.String' and try again.

Upvotes: 0

Views: 1757

Answers (1)

phuclv
phuclv

Reputation: 41784

You have several solutions to execute the correct curl binary:

  • Run curl.exe instead of curl. This is similar to why where works in cmd but in PowerShell you must run where.exe because where is an alias to Where-Object
  • Remove the curl alias by running Remove-Alias curl. You can put this in the profile to remove it by default
  • Install PowerShell Core and use it instead

That's because in the past curl was an alias of Invoke-WebRequest along with wget

PS C:\> Get-Alias -Definition Invoke-WebRequest

CommandType     Name                                               Version    Source
-----------     ----                                               -------    ------
Alias           curl -> Invoke-WebRequest
Alias           iwr -> Invoke-WebRequest
Alias           wget -> Invoke-WebRequest

When MS added tar.exe and curl.exe to Windows 10 that causes some confusion since now running curl will invoke the alias instead of the executable (that's easy to understand since an alias will have higher priority just like in bash). In PowerShell core (i.e. version 6.0+) those aliases have been removed. See remove curl and wget aliases

PS C:\> Get-Alias -Definition Invoke-WebRequest

CommandType     Name                                               Version    Source
-----------     ----                                               -------    ------
Alias           iwr -> Invoke-WebRequest

Update:

You must also modify your quotes because PowerShell has different quoting rules which is more similar to bash and is more standardized and much better than the messy one in cmd:

curl -L -c ./cookie -b ./cookie -X POST -H "Accept: application/json" -s -d '{"accountId":"123456789","partition":"abc","duration":1234}' https://testabc.com

Update 2:

I tried capturing the command line passed to curl.exe with sysmon and in cmd it's like this

"C:\WINDOWS\system32\curl.exe" -L -c ./cookie -b ./cookie -X POST -H "Accept: application/json" -s -d "{\"accountId\":\"123456789\",\"partition\":\"abc\",\"duration\":1234}" https://testabc.com

while in PowerShell it's like this

"C:\WINDOWS\system32\curl.exe" -L -c ./cookie -b ./cookie -X POST -H "Accept: application/json" -s -d {"accountId":"123456789","partition":"abc","duration":1234} https://testabc.com

Notice the difference in the json string. So it seems that curl.exe splits arguments itself and expects the raw \ escape characters in the parameters to tokenize the arguments properly. To do that you can wrap the whole json string into 'single quotes' like this

curl -L -c ./cookie -b ./cookie -X POST -H "Accept: application/json" -s -d '"{\"accountId\":\"123456789\",\"partition\":\"abc\",\"duration\":1234}"' https://testabc.com

or just pass verbatim arguments by adding the stop-parsing symbol --% after curl.exe to force PowerShell to not use its parsing rules and pass the whole string to the executable

curl.exe --% -L -c ./cookie -b ./cookie -X POST -H "Accept: application/json" -s -d "{\"accountId\":\"123456789\",\"partition\":\"abc\",\"duration\":1234}" https://testabc.com

Upvotes: 1

Related Questions