Search code examples
powershellcurlinvoke-webrequest

Translating Curl request to Invoke-WebRequest with --data-urlencode parameter


I'm trying to request data from Mixpanel via there API.

Mixpanel JQL Getting Started

I can run a modified version of their basic example script and receive data.

# sends the JQL code in `query.js` to the api
# to a project with sample data for this tutorial
curl https://mixpanel.com/api/2.0/jql \
    -u API_SECRET:PASSWORD \
    --data-urlencode [email protected]

query.js above is the query payload, which contains a JS function that is run on Mixpanel servers. The request returns JSON data.

I have been unable to translate this to Invoke-WebRequest. Below is my attempt.

$urlEncodedString = gc query.js | Out-String | % {[System.Web.HttpUtility]::UrlEncode($_)}
$user = 'SECRET'; 
$pass = 'PASSWORD';  
$pair = "$($user):$($pass)";  
$encodedCreds = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes($pair));
$basicAuthValue = "Basic $encodedCreds";
$Headers = @{ Authorization = $basicAuthValue };

Invoke-WebRequest -Uri ("https://mixpanel.com/api/2.0/jql") -Headers $Headers -Method Post -Body "Script@$urlEncodedString

Returns a 400 from the server. If I use verbose, the payload size is shown as -1 byte.

The authentication is correct, but I'm sure I''m not placing the "script@$urlEncodedString" correctly.

I've tried building the body as a dictionary according to this answer, but no success either. I get the same error and message in verbose mode.

How do I translate the --data-urlencode portion to Invoke-WebRequest?


Solution

  • Building off the comment Jeroen Mostert, this ended up working:

    $query = gc query.js | Out-String 
    $user = 'SECRET'; 
    $pass = 'PASSWORD';  
    $pair = "$($user):$($pass)";  
    $encodedCreds = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes($pair));
    $basicAuthValue = "Basic $encodedCreds";
    $Headers = @{ Authorization = $basicAuthValue };
    
    Invoke-WebRequest -Uri ("https://mixpanel.com/api/2.0/jql") -Headers $Headers -Method Post -Body @{"script" = $query}
    

    Oddly enough, gc query.js was not sufficient to get a valid response from Mixpanel.

    Edit: Out-String returns a single string by default, where Get-Content returns a List of strings per line by default. This is why including Out-String resulted in a successful request.

    Get-Content --raw also results in success