Function return type?

Hi all,

I am currently reading ‘Learn Powershell Scripting In a Month of Lunches’ and trying to drill in the idea of cmdlets performing one thing and one thing only which then can be chained together to form a complete tool.

I am working with the REST API from Teamwork.com and had the idea of creating some Powershell cmdlets that were wrappers around working with the API. For my first cmdlet I want to write something like - ‘Invoke-TWAuthentication’ which can be used to authenticate a user to Teamwork when making REST API calls.

I am currently testing this in a function to make sure I can get it to work but the function keeps returning a System.String type instead of a IDictionary which is required by the parameter ‘Headers’ in the Invoke-RestMethod cmdlet.

Here is the small snippet I am working with, the idea being I can use it in the ‘-Headers’ value so like this:

Invoke-RestMethod -Uri <Uri> -Method Get -Headers Invoke-TWAuthentication
function Invoke-TWAuthentication()
{
$bytes = [System.Text.Encoding]::ASCII.GetBytes('MyAPIKey')
$base64 = [System.Convert]::ToBase64String($bytes)
$basicAuthValue = "Basic $base64"
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 -bor [Net.SecurityProtocolType]::Tls11 -bor [Net.SecurityProtocolType]::Tls
$headers = @{ Authorization = $basicAuthValue }
}

You aren’t returning anything in your function; you’re just storing the data in a variable that stays in the function scope. To return the value, you need to drop the final value to output:

https://gist.github.com/vexx32/1e5b1fa68510beda6002883bf401fdde

And the reason it appears to be returning a string is that command calls can’t be made directly as a parameter argument; you need to place the command call in parentheses, otherwise it is simply interpreted as a regular string instead of calling your function.

Invoke-RestMethod -Uri -Method Get -Headers (Invoke-TWAuthentication)

I would also recommend renaming your function here. It doesn’t `Invoke` anything, really; it just retrieves the API key value for the header. I would be inclined to recommend a name something along the lines of `Get-TWApiAuthHeader` or something along those lines that you’d prefer.

In the interest of having one cmdlet do one task, as well, I’d recommend moving the TLS setter outside it as well; that would generally fall pretty clearly under the category of “invisible side effects” that you’ll generally want to avoid. :slight_smile:

Thanks so much for your response. That has really helped. So I guess it is not worth putting that in a cmdlet, a function will do?

There’s no harm to making it a cmdlet, I suppose, but you won’t gain a whole lot over a more straightforward advanced function in this case, in my opinion. :slight_smile: