2

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 script@query.js

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?

bob0the0mighty
  • 782
  • 11
  • 28
  • 2
    This should be as simple as `Invoke-RestMethod -Uri ... -Headers .. -Method Post -Body @{ "script" = Get-Content query.js }`. Per the curl docs, `--data-urlencode name@file` posts the content of `file` as the `name` parameter. – Jeroen Mostert Sep 23 '19 at 13:21
  • gc query.js by itself did not work, but gc query.js | out-string did. I'm not sure why, as both Get-Content and Out-String should return string objects. – bob0the0mighty Sep 23 '19 at 13:55
  • 1
    No, `Get-Content` returns a pipeline of objects. I would expect `Invoke-RestMethod` to handle that correctly, but apparently not. Oh well. `Get-Content -Raw` should work better in that case (piping the whole thing back to `Out-String` is more overhead). – Jeroen Mostert Sep 23 '19 at 14:05
  • Yeah, I just read through the help files and saw this. I have a bad habit of using Get-Member to get information about objects, and gm returns TypeName: System.String for gc query.js and gc query.js | Out-String – bob0the0mighty Sep 23 '19 at 14:06

1 Answers1

0

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

bob0the0mighty
  • 782
  • 11
  • 28