Converting HTTP Response Codes

In the previous example we created a small PowerShell function that checks web site availability, and as part of the test results, a HTTP response code was returned. Let’s check out how this numeric code can be easily converted into a meaningful text message.

Here is the function again that tests web sites:

function Test-Url
{
  param
  (
    [Parameter(Mandatory,ValueFromPipeline)]
    [string]
    $Url
  )
  
  Add-Type -AssemblyName System.Web
  
  $check = "https://isitdown.site/api/v3/"
  $encoded = [System.Web.HttpUtility]::UrlEncode($url)
  $callUrl = "$check$encoded"
  
  Invoke-RestMethod -Uri $callUrl |
    Select-Object -Property Host, IsItDown, Response_Code
}

And this would be a typical result:

 
PS C:> Test-Url -Url powershellmagazine.com

host                   isitdown response_code
----                   -------- -------------
powershellmagazine.com    False           200
 

In this example, the response code is “200” which happens to stand for “OK”. If you’d like to convert HTTP response codes to text, simply convert the data type to [System.Net.HttpStatusCode]. That’s all:

 
PS C:> 200 -as [System.Net.HttpStatusCode]
OK
 

Here is a version that incorporates this conversion for you:

function Test-Url
{
  param
  (
    [Parameter(Mandatory,ValueFromPipeline)]
    [string]
    $Url
  )
  
  Add-Type -AssemblyName System.Web
  
  $check = "https://isitdown.site/api/v3/"
  $encoded = [System.Web.HttpUtility]::UrlEncode($url)
  $callUrl = "$check$encoded"
  $response = @{
    Name = 'Response'
    Expression = { 
        '{0} ({1})' -f 
            ($_.Response_Code -as [System.Net.HttpStatusCode]), 
            $_.Response_Code 
    }
  }
  Invoke-RestMethod -Uri $callUrl | 
    Select-Object -Property Host, IsItDown, $response
} 

And this would be the result:

 
PS C:> Test-Url -Url powershellmagazine.com

host                   isitdown Response
----                   -------- --------
powershellmagazine.com    False OK (200)
 

Note how the calculated column “Response” now reports both the original numeric response code and the friendly text for it.


Twitter This Tip! ReTweet this Tip!

Test Web Site Availability

When a web site is unavailable, often the question is whether it’s you, or whether the web site is generally down for everyone else, too. PowerShell can ask a web service to check web site availability for you. Here is a simple wrapper function:

function Test-Url
{
  param
  (
    [Parameter(Mandatory,ValueFromPipeline)]
    [string]
    $Url
  )
  
  Add-Type -AssemblyName System.Web
  
  $check = "https://isitdown.site/api/v3/"
  $encoded = [System.Web.HttpUtility]::UrlEncode($url)
  $callUrl = "$check$encoded"
  
  Invoke-RestMethod -Uri $callUrl |
    Select-Object -Property Host, IsItDown, Response_Code
}

It calls a RESTful API and submits the URL to check via URL arguments. That’s why the URL to test needs to be URL-encoded. Next, the code calls Invoke-RestMethod and received the test result as an object.

 
PS C:> Test-Url -Url powershellmagazine.com

host                   isitdown response_code
----                   -------- -------------
powershellmagazine.com    False           200
 

Please note that the web service used in this example is free, and does not require registration or an API key. The downside is that the web service is throttled, so if you check a large number of URLs, it may respond with an exception stating that you submitted too many requests. When this happens, just wait a moment and try again.


psconf.eu – PowerShell Conference EU 2019 – June 4-7, Hannover Germany – visit www.psconf.eu There aren’t too many trainings around for experienced PowerShell scripters where you really still learn something new. But there’s one place you don’t want to miss: PowerShell Conference EU – with 40 renown international speakers including PowerShell team members and MVPs, plus 350 professional and creative PowerShell scripters. Registration is open at www.psconf.eu, and the full 3-track 4-days agenda becomes available soon. Once a year it’s just a smart move to come together, update know-how, learn about security and mitigations, and bring home fresh ideas and authoritative guidance. We’d sure love to see and hear from you!

Twitter This Tip! ReTweet this Tip!

Unit Conversion via Web Service

Accessing RESTful web services is trivial for PowerShell: simply send your input data to a public web service, and receive the results.

Here are three PowerShell functions designed to each do a numeric conversion:

function Convert-InchToCentimeter
{
  param
  (
    [Parameter(Mandatory)]
    [Double]
    $Inch
  )
  [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
  $url = 'https://ucum.nlm.nih.gov/ucum-service/v1/ucumtransform/{0}/from/%5Bin_i%5D/to/cm' -f $Inch
  $result = Invoke-RestMethod -Uri $url -UseBasicParsing 
  $result.UCUMWebServiceResponse.Response
}


function Convert-FootToMicrometer
{
  param
  (
    [Parameter(Mandatory)]
    [Double]
    $Foot
  )
  [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
  $url = 'https://ucum.nlm.nih.gov/ucum-service/v1/ucumtransform/{0}/from/%5Bft_i%5D/to/um' -f $Foot
  $result = Invoke-RestMethod -Uri $url -UseBasicParsing 
  $result.UCUMWebServiceResponse.Response
}


function Convert-GramToOunce
{
  param
  (
    [Parameter(Mandatory)]
    [Double]
    $Gram
  )
  [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
  $url = 'https://ucum.nlm.nih.gov/ucum-service/v1/ucumtransform/{0}/from/g/to/%5Boz_ap%5D' -f $Gram
  $result = Invoke-RestMethod -Uri $url -UseBasicParsing 
  $result.UCUMWebServiceResponse.Response
}

Provided you have Internet access, then doing conversions is as simple as a function call:

 
PS C:> Convert-GramToOunce -Gram 230

SourceQuantity SourceUnit TargetUnit ResultQuantity
-------------- ---------- ---------- --------------
230.0          g          [oz_ap]    7.3946717   
 

The important points to keep in mind are:

  • You need to allow Tls12 to enable HTTPS connections (see code)
  • You need to follow the rules set forth by the web service, i.e. when it requires whole numbers, you cannot submit decimals

There are plenty more conversions available at https://ucum.nlm.nih.gov/ucum-service.html#conversion, so you can use the functions provided as a template to create more conversion functions.


Twitter This Tip! ReTweet this Tip!

Validating Active Directory Credentials

PowerShell can validate AD username and passwords against the Active Directory:

Add-Type -AssemblyName System.DirectoryServices.AccountManagement
$account = New-Object System.DirectoryServices.AccountManagement.PrincipalContext([DirectoryServices.AccountManagement.ContextType]::Domain, $env:userdomain)

$account.ValidateCredentials('user12', 'topSecret')

Note that this approach is for diagnostic purposes only. It accepts a plain text password.


Twitter This Tip! ReTweet this Tip!

Numbering Output (Part 1)

If you’d like to add an incrementing number to your output, here is a simple way:

Get-Process |
  Select-Object -Property '#', ProcessName, CPU -First 10 |
  ForEach-Object -begin { $i = 0} -process {
    $i++
    $_.'#' = $i
    $_
  } -end {}

Select-Object adds a new property called “#”, and ForEach-Object adds an auto-incrementing number to it. The result looks similar to this:

 
 # ProcessName               CPU
 - -----------               ---
 1 AdobeCollabSync       65,5625
 2 AdobeCollabSync           0,5
 3 AGMService            
...
 

Twitter This Tip! ReTweet this Tip!

Accepting Masked Passwords

If you ever write PowerShell functions that need to accept sensitive input such as passwords, make sure you allow users to submit SecureString input. If you accept passwords via clear text, there is a substantial risk that others may see the password while being entered, or (even worse) that the password is logged and later can be found in dump files.

Here is a simple framework that illustrates how you can achieve safe input:

function Enter-Secret
{
    param
    (
        [Parameter(Mandatory)]
        [SecureString]
        $SafeInput
    )

    $PlainText = [Management.Automation.PSCredential]::
    new('x',$SafeInput).GetNetworkCredential().Password

    "User entered $PlainText"

}

When the user runs Enter-Secret, the password can be entered in a masked way. Internally, the function converts the secure string into plain text. This way, the secret password is never visible and will never be logged.

The conversion from SecureString to String is performed by creating a temporary credential object. Credential objects have a built-in method (GetNetworkCredential()) to convert a SecureString to a String.


Twitter This Tip! ReTweet this Tip!