Functions/Invoke-BMRestMethod.ps1


function Invoke-BMRestMethod
{
    <#
    .SYNOPSIS
    Invokes a BuildMaster REST method.
 
    .DESCRIPTION
    The `Invoke-BMRestMethod` invokes a BuildMaster REST API method. You pass the path to the endpoint (everything after `/api/`) via the `Name` parameter, the HTTP method to use via the `Method` parameter, and the parameters to pass in the body of the request via the `Parameter` parameter. This function converts the `Parameter` hashtable to a URL-encoded query string and sends it in the body of the request. You can send the parameters as JSON by adding the `AsJson` parameter. You can pass your own custom body to the `Body` parameter. If you do, make sure you set an appropriate content type for the request with the `ContentType` parameter.
 
    You also need to pass an object that represents the BuildMaster instance and API key to use when connecting via the `Session` parameter. Use the `New-BMSession` function to create a session object.
 
    When using the `WhatIf` parameter, only web requests that use the `Get` HTTP method are made.
    #>

    [CmdletBinding(SupportsShouldProcess=$true,DefaultParameterSetName='NoBody')]
    param(
        [Parameter(Mandatory=$true)]
        [object]
        # A session object that represents the BuildMaster instance to use. Use the `New-BMSession` function to create session objects.
        $Session,

        [Parameter(Mandatory=$true)]
        [string]
        # The name of the API to use. The should be everything after `/api/` in the method's URI.
        $Name,

        [Microsoft.PowerShell.Commands.WebRequestMethod]
        # The HTTP/web method to use. The default is `GET`.
        $Method = [Microsoft.PowerShell.Commands.WebRequestMethod]::Get,

        [Parameter(Mandatory=$true,ParameterSetName='BodyFromHashtable')]
        [hashtable]
        # That parameters to pass to the method. These are converted to JSON and sent to the API in the body of the request.
        $Parameter,

        [Parameter(ParameterSetName='BodyFromHashtable')]
        [Switch]
        # Send the request as JSON. Otherwise, the data is sent as name/value pairs.
        $AsJson,

        [Parameter(Mandatory=$true,ParameterSetName='CustomBody')]
        [string]
        # The body to send.
        $Body,

        [string]
        # The content type of the web request.
        #
        # By default,
        #
        # * if passing a value to the `Parameter` parameter, the content type is set to `application/x-www-form-urlencoded`
        # * if passing a value to the `Parameter` parameter and you're using the `AsJson` switch, the content type is set to `application/json`.
        #
        # Otherwise, the content type is not set. If you're passing your own body to the `Body` parameter, you may have to set the appropriate content type for BuildMaster to respond.
        $ContentType
    )

    Set-StrictMode -Version 'Latest'
    Use-CallerPreference -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState

    $uri = '{0}api/{1}' -f $Session.Uri,$Name
    
    $debugBody = ''
    $webRequestParam = @{ }
    if( $Body )
    {
        $webRequestParam['Body'] = $Body
    }
    elseif( $Parameter )
    {
        if( $AsJson )
        {
            $Body = $Parameter | ConvertTo-Json -Depth 100
            $debugBody = $Body -replace '("API_Key": +")[^"]+','$1********'
            if( -not $ContentType )
            {
                $ContentType = 'application/json; charset=utf-8'
            }
        }
        else
        {
            $keyValues = $Parameter.Keys | ForEach-Object { '{0}={1}' -f [Web.HttpUtility]::UrlEncode($_),[Web.HttpUtility]::UrlEncode($Parameter[$_]) }
            $Body = $keyValues -join '&'
            if( -not $ContentType )
            {
                $ContentType = 'application/x-www-form-urlencoded; charset=utf-8'
            }
            $debugBody = $Parameter.Keys | ForEach-Object {
                $value = $Parameter[$_]
                if( $_ -eq 'API_Key' )
                {
                    $value = '********'
                }
                ' {0}={1}' -f $_,$value }
        }
        $webRequestParam['Body'] = $Body
    }

    if( $ContentType )
    {
        $webRequestParam['ContentType'] = $ContentType
    }

    $headers = @{
                    'X-ApiKey' = $Session.ApiKey;
                }

    #$DebugPreference = 'Continue'
    Write-Debug -Message ('{0} {1}' -f $Method.ToString().ToUpperInvariant(),($uri -replace '\b(API_Key=)([^&]+)','$1********'))
    if( $ContentType )
    {
        Write-Debug -Message (' Content-Type: {0}' -f $ContentType)
    }
    foreach( $headerName in $headers.Keys )
    {
        $value = $headers[$headerName]
        if( $headerName -eq 'X-ApiKey' )
        {
            $value = '*' * 8
        }

        Write-Debug -Message (' {0}: {1}' -f $headerName,$value)
    }
    
    $debugBody | Write-Debug

    try
    {
        if( $Method -eq [Microsoft.PowerShell.Commands.WebRequestMethod]::Get -or $PSCmdlet.ShouldProcess($Uri,$Method) )
        {
            Invoke-RestMethod -Method $Method -Uri $uri @webRequestParam -Headers $headers | 
                ForEach-Object { $_ } 
        }
    }
    catch [Net.WebException]
    {
        Write-Error -ErrorRecord $_
    }
}