Search code examples
powershellgoogle-apiodata

How to send a BatchRequest to google API with PowerShell


I am working with the Google API to automate tasks for distribution groups. I understand how to send individual requests, but I want to be able to send BatchRequests, and this seems to be a challenge as the format is not consistent like for example all JSON so i can convert the body once and make my request. I am reading through the documentation from Google and I cant figure out how to achieve that with Powershell. https://developers.google.com/admin-sdk/directory/v1/guides/batch

I see there is already a .NET library for that, but I struggle to understand how to use it. https://googleapis.dev/dotnet/Google.Apis/latest/api/Google.Apis.Requests.BatchRequest.html

I cant understand how I can do nested HTTP request inside a HTTP request with PowerShell. I have no idea how I can even write it, so here is a draft that I am thinking over, and I will be editing throughout this post.

$batchUrl = 'https://www.googleapis.com/batch/admin/directory_v1'

$header = @{
    "Content-type"  = "multipart/mixed; boundary=batch_test"
    "Authorization" = "Bearer <token>"
}

$psBody = [ordered] @{
    method = "POST /admin/directory/v1/groups/[email protected]/members"
    "content-type" = "application/json"
    email = "[email protected]"
    role = "MEMBER"
}

$JSONbody = $psBody | ConvertTo-Json

Invoke-RestMethod -Uri $batchUrl -Method POST -Headers $header -Body $JSONbody

I really want to understand that OData structure, any documentation/guide reference are welcome.


Solution

  • I figured it out, the format needed was literally what Google posted, therefore I just had to adjust the body to what I want. The example bellow is just Prove of Concept and would need some functions to automate the population from an Array.

    $URL = 'https://www.googleapis.com/batch/admin/directory_v1'
    
    $boundary = [System.Guid]::NewGuid().ToString();
    $LF = "`r`n";
    
    $header = @{
        "Content-type"  = "multipart/mixed; boundary=$boundary"
        "Authorization" = "Bearer <token>"
    }
    
    $request1 = [pscustomobject][ordered]@{
        email = "[email protected]"
        role  = "MEMBER"
    } | ConvertTo-Json
    
    $request2 = [pscustomobject][ordered]@{
        email = "[email protected]"
        role  = "MEMBER"
    } | ConvertTo-Json
    
    $nestedBody = (
        "--$boundary",
        "Content-Type: application/http$LF",
        "POST /admin/directory/v1/groups/[email protected]/members",
        "Content-Type: application/json$LF",
        "$($request1)$LF",
        "--$boundary--",
        "Content-Type: application/http$LF",
        "POST /admin/directory/v1/groups/[email protected]/members",
        "Content-Type: application/json$LF",
        "$($request2)$LF",
        "--$boundary--"
    ) -join $LF
    
    $sendRequest = @{
        Uri         = $URL
        header      =  $header
        Method      = "Post"
        Body        = $nestedBody
    }
    
    Invoke-RestMethod @sendRequest
    

    The way I got to that conclusions was by installing the Fiddler Proxy and see how my request look like in practice, check screenshot bellow.

    enter image description here