Private/Join-SatUri.ps1
|
function Join-SatUri { <# .SYNOPSIS Joins a base URI with an endpoint path. .DESCRIPTION Safely combines a base URI with an endpoint path using the .NET Uri class. Handles trailing and leading slashes automatically. .PARAMETER BaseUri The base URI (default: https://api.srrdb.com/v1) .PARAMETER Endpoint The endpoint path to append (e.g., /details/ReleaseName) .PARAMETER QueryString Optional query string to append to the URI (without leading ?). IMPORTANT: Query string values must be URL-encoded before passing to this function. Use [System.Uri]::EscapeDataString() to encode parameter values. .EXAMPLE Join-SatUri -Endpoint "/details/Some.Release.Name" Returns: https://api.srrdb.com/v1/details/Some.Release.Name .EXAMPLE Join-SatUri -Endpoint "/search/harry/potter" Returns: https://api.srrdb.com/v1/search/harry/potter #> [CmdletBinding()] [OutputType([string])] param( [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string] $BaseUri = 'https://api.srrdb.com/v1', [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string] $Endpoint, [Parameter(Mandatory = $false)] [ValidateScript({ # Validate that QueryString doesn't contain unencoded special characters that could indicate injection if ($_ -match '[<>\"''\x00-\x1F]') { throw "QueryString contains invalid characters. Ensure values are properly URL-encoded using [System.Uri]::EscapeDataString()" } $true })] [string] $QueryString ) try { # Validate that BaseUri is a valid URI $null = [Uri]::new($BaseUri) # Ensure base URI ends with / for proper path joining $normalizedBase = $BaseUri.TrimEnd('/') # Ensure endpoint starts with / for consistency $normalizedEndpoint = if ($Endpoint.StartsWith('/')) { $Endpoint } else { "/$Endpoint" } $uri = "$normalizedBase$normalizedEndpoint" if ($QueryString) { $uri += "?$QueryString" } return $uri } catch { throw "Failed to join URI: $($_.Exception.Message)" } } |