URL Encode/Decode
Encode Query String with [System.Web.HttpUtility]::UrlEncode()
Section titled “Encode Query String with [System.Web.HttpUtility]::UrlEncode()”$scheme = 'https'$url_format = '{0}://example.vertigion.com/foos?{1}'$qs_data = @{ 'foo1'='bar1'; 'foo2'= 'complex;/?:@&=+$, bar''"'; 'complex;/?:@&=+$, foo''"'='bar2';}
[System.Collections.ArrayList] $qs_array = @()foreach ($qs in $qs_data.GetEnumerator()) { $qs_key = [System.Web.HttpUtility]::UrlEncode($qs.Name) $qs_value = [System.Web.HttpUtility]::UrlEncode($qs.Value) $qs_array.Add("${qs_key}=${qs_value}") | Out-Null}
$url = $url_format -f @([uri]::"UriScheme${scheme}", ($qs_array -join '&'))With [System.Web.HttpUtility]::UrlEncode(), you will notice that spaces are turned into plus signs (+) instead of %20:
[https://example.vertigion.com/foos](https://example.vertigion.com/foos)? foo2=complex%3b%2f%3f%3a%40%26%3d%2b%24%2c+bar%27%22& complex%3b%2f%3f%3a%40%26%3d%2b%24%2c+foo%27%22=bar2&foo1=bar1
Quick Start: Encoding
Section titled “Quick Start: Encoding”$url1 = [uri]::EscapeDataString("http://test.com?test=my value")# url1: http%3A%2F%2Ftest.com%3Ftest%3Dmy%20value
$url2 = [uri]::EscapeUriString("http://test.com?test=my value")# url2: http://test.com?test=my%20value
# HttpUtility requires at least .NET 1.1 to be installed.$url3 = [System.Web.HttpUtility]::UrlEncode("http://test.com?test=my value")# url3: http%3a%2f%2ftest.com%3ftest%3dmy+valueNote: More info on HTTPUtility.
Quick Start: Decoding
Section titled “Quick Start: Decoding”Note: these examples use the variables created in the Quick Start: Encoding section above.
# url1: http%3A%2F%2Ftest.com%3Ftest%3Dmy%20value[uri]::UnescapeDataString($url1)# Returns: http://test.com?test=my value
# url2: http://test.com?test=my%20value[uri]::UnescapeDataString($url2)# Returns: http://test.com?test=my value
# url3: http%3a%2f%2ftest.com%3ftest%3dmy+value[uri]::UnescapeDataString($url3)# Returns: http://test.com?test=my+value
# Note: There is no `[uri]::UnescapeUriString()`;# which makes sense since the `[uri]::UnescapeDataString()`# function handles everything it would handle plus more.
# HttpUtility requires at least .NET 1.1 to be installed.# url1: http%3A%2F%2Ftest.com%3Ftest%3Dmy%20value[System.Web.HttpUtility]::UrlDecode($url1)# Returns: http://test.com?test=my value
# HttpUtility requires at least .NET 1.1 to be installed.# url2: http://test.com?test=my%20value[System.Web.HttpUtility]::UrlDecode($url2)# Returns: http://test.com?test=my value
# HttpUtility requires at least .NET 1.1 to be installed.# url3: http%3a%2f%2ftest.com%3ftest%3dmy+value[System.Web.HttpUtility]::UrlDecode($url3)# Returns: http://test.com?test=my valueNote: More info on HTTPUtility.
Encode Query String with [uri]::EscapeDataString()
Section titled “Encode Query String with [uri]::EscapeDataString()”$scheme = 'https'$url_format = '{0}://example.vertigion.com/foos?{1}'$qs_data = @{ 'foo1'='bar1'; 'foo2'= 'complex;/?:@&=+$, bar''"'; 'complex;/?:@&=+$, foo''"'='bar2';}
[System.Collections.ArrayList] $qs_array = @()foreach ($qs in $qs_data.GetEnumerator()) { $qs_key = [uri]::EscapeDataString($qs.Name) $qs_value = [uri]::EscapeDataString($qs.Value) $qs_array.Add("${qs_key}=${qs_value}") | Out-Null}
$url = $url_format -f @([uri]::"UriScheme${scheme}", ($qs_array -join '&'))With [uri]::EscapeDataString(), you will notice that the apostrophe (') was not encoded:
[https://example.vertigion.com/foos](https://example.vertigion.com/foos)? foo2=complex%3B%2F%3F%3A%40%26%3D%2B%24%2C%20bar'%22& complex%3B%2F%3F%3A%40%26%3D%2B%24%2C%20foo'%22=bar2&foo1=bar1
Decode URL with [uri]::UnescapeDataString()
Section titled “Decode URL with [uri]::UnescapeDataString()”Encoded with [uri]::EscapeDataString()
First, we’ll decode the URL and Query String encoded with [uri]::EscapeDataString() in the above example:
[https://example.vertigion.com/foos](https://example.vertigion.com/foos)? foo2=complex%3B%2F%3F%3A%40%26%3D%2B%24%2C%20bar'%22& complex%3B%2F%3F%3A%40%26%3D%2B%24%2C%20foo'%22=bar2&foo1=bar1
$url = 'https://example.vertigion.com/foos?foo2=complex%3B%2F%3F%3A%40%26%3D%2B%24%2C%20bar''%22&complex%3B%2F%3F%3A%40%26%3D%2B%24%2C%20foo''%22=bar2&foo1=bar1'$url_parts_regex = '^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?' # See Remarks
if ($url -match $url_parts_regex) { $url_parts = @{ 'Scheme' = $Matches[2]; 'Server' = $Matches[4]; 'Path' = $Matches[5]; 'QueryString' = $Matches[7]; 'QueryStringParts' = @{} }
foreach ($qs in $query_string.Split('&')) { $qs_key, $qs_value = $qs.Split('=') $url_parts.QueryStringParts.Add( [uri]::UnescapeDataString($qs_key), [uri]::UnescapeDataString($qs_value) ) | Out-Null }} else { Throw [System.Management.Automation.ParameterBindingException] "Invalid URL Supplied"}This gives you back [hashtable]$url_parts; which equals (Note: the spaces in the complex parts are spaces):
PS > $url_parts
Name Value---- -----Scheme httpsPath /foosServer example.vertigion.comQueryString foo2=complex%3B%2F%3F%3A%40%26%3D%2B%24%2C%20bar'%22&complex%3B%2F%3F%3A%40%26%3D%2B%24%2C%20foo'%22=bar2&foo1=bar1QueryStringParts {foo2, complex;/?:@&=+$, foo'", foo1}
PS > $url_parts.QueryStringParts
Name Value---- -----foo2 complex;/?:@&=+$, bar'"complex;/?:@&=+$, foo'" bar2foo1 bar1Encoded with [System.Web.HttpUtility]::UrlEncode()
Now, we’ll decode the URL and Query String encoded with [System.Web.HttpUtility]::UrlEncode() in the above example:
[https://example.vertigion.com/foos](https://example.vertigion.com/foos)? foo2=complex%3b%2f%3f%3a%40%26%3d%2b%24%2c+bar%27%22& complex%3b%2f%3f%3a%40%26%3d%2b%24%2c+foo%27%22=bar2&foo1=bar1
$url = 'https://example.vertigion.com/foos?foo2=complex%3b%2f%3f%3a%40%26%3d%2b%24%2c+bar%27%22&complex%3b%2f%3f%3a%40%26%3d%2b%24%2c+foo%27%22=bar2&foo1=bar1'$url_parts_regex = '^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?' # See Remarks
if ($url -match $url_parts_regex) { $url_parts = @{ 'Scheme' = $Matches[2]; 'Server' = $Matches[4]; 'Path' = $Matches[5]; 'QueryString' = $Matches[7]; 'QueryStringParts' = @{} }
foreach ($qs in $query_string.Split('&')) { $qs_key, $qs_value = $qs.Split('=') $url_parts.QueryStringParts.Add( [uri]::UnescapeDataString($qs_key), [uri]::UnescapeDataString($qs_value) ) | Out-Null }} else { Throw [System.Management.Automation.ParameterBindingException] "Invalid URL Supplied"}This gives you back [hashtable]$url_parts, which equals (Note: the spaces in the complex parts are plus signs (+) in the first part and spaces in the second part):
PS > $url_parts
Name Value---- -----Scheme httpsPath /foosServer example.vertigion.comQueryString foo2=complex%3b%2f%3f%3a%40%26%3d%2b%24%2c+bar%27%22&complex%3b%2f%3f%3a%40%26%3d%2b%24%2c+foo%27%22=bar2&foo1=bar1QueryStringParts {foo2, complex;/?:@&=+$, foo'", foo1}
PS > $url_parts.QueryStringParts
Name Value---- -----foo2 complex;/?:@&=+$, bar'"complex;/?:@&=+$, foo'" bar2foo1 bar1Decode URL with [System.Web.HttpUtility]::UrlDecode()
Section titled “Decode URL with [System.Web.HttpUtility]::UrlDecode()”Encoded with [uri]::EscapeDataString()
First, we’ll decode the URL and Query String encoded with [uri]::EscapeDataString() in the above example:
[https://example.vertigion.com/foos](https://example.vertigion.com/foos)? foo2=complex%3B%2F%3F%3A%40%26%3D%2B%24%2C%20bar'%22& complex%3B%2F%3F%3A%40%26%3D%2B%24%2C%20foo'%22=bar2&foo1=bar1
$url = 'https://example.vertigion.com/foos?foo2=complex%3B%2F%3F%3A%40%26%3D%2B%24%2C%20bar''%22&complex%3B%2F%3F%3A%40%26%3D%2B%24%2C%20foo''%22=bar2&foo1=bar1'$url_parts_regex = '^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?' # See Remarks
if ($url -match $url_parts_regex) { $url_parts = @{ 'Scheme' = $Matches[2]; 'Server' = $Matches[4]; 'Path' = $Matches[5]; 'QueryString' = $Matches[7]; 'QueryStringParts' = @{} }
foreach ($qs in $query_string.Split('&')) { $qs_key, $qs_value = $qs.Split('=') $url_parts.QueryStringParts.Add( [System.Web.HttpUtility]::UrlDecode($qs_key), [System.Web.HttpUtility]::UrlDecode($qs_value) ) | Out-Null }} else { Throw [System.Management.Automation.ParameterBindingException] "Invalid URL Supplied"}This gives you back [hashtable]$url_parts; which equals (Note: the spaces in the complex parts are spaces):
PS > $url_parts
Name Value---- -----Scheme httpsPath /foosServer example.vertigion.comQueryString foo2=complex%3B%2F%3F%3A%40%26%3D%2B%24%2C%20bar'%22&complex%3B%2F%3F%3A%40%26%3D%2B%24%2C%20foo'%22=bar2&foo1=bar1QueryStringParts {foo2, complex;/?:@&=+$, foo'", foo1}
PS > $url_parts.QueryStringParts
Name Value---- -----foo2 complex;/?:@&=+$, bar'"complex;/?:@&=+$, foo'" bar2foo1 bar1Encoded with [System.Web.HttpUtility]::UrlEncode()
Now, we’ll decode the URL and Query String encoded with [System.Web.HttpUtility]::UrlEncode() in the above example:
[https://example.vertigion.com/foos](https://example.vertigion.com/foos)? foo2=complex%3b%2f%3f%3a%40%26%3d%2b%24%2c+bar%27%22& complex%3b%2f%3f%3a%40%26%3d%2b%24%2c+foo%27%22=bar2&foo1=bar1
$url = 'https://example.vertigion.com/foos?foo2=complex%3b%2f%3f%3a%40%26%3d%2b%24%2c+bar%27%22&complex%3b%2f%3f%3a%40%26%3d%2b%24%2c+foo%27%22=bar2&foo1=bar1'$url_parts_regex = '^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?' # See Remarks
if ($url -match $url_parts_regex) { $url_parts = @{ 'Scheme' = $Matches[2]; 'Server' = $Matches[4]; 'Path' = $Matches[5]; 'QueryString' = $Matches[7]; 'QueryStringParts' = @{} }
foreach ($qs in $query_string.Split('&')) { $qs_key, $qs_value = $qs.Split('=') $url_parts.QueryStringParts.Add( [System.Web.HttpUtility]::UrlDecode($qs_key), [System.Web.HttpUtility]::UrlDecode($qs_value) ) | Out-Null }} else { Throw [System.Management.Automation.ParameterBindingException] "Invalid URL Supplied"}This gives you back [hashtable]$url_parts; which equals (Note: the spaces in the complex parts are spaces):
PS > $url_parts
Name Value---- -----Scheme httpsPath /foosServer example.vertigion.comQueryString foo2=complex%3b%2f%3f%3a%40%26%3d%2b%24%2c+bar%27%22&complex%3b%2f%3f%3a%40%26%3d%2b%24%2c+foo%27%22=bar2&foo1=bar1QueryStringParts {foo2, complex;/?:@&=+$, foo'", foo1}
PS > $url_parts.QueryStringParts
Name Value---- -----foo2 complex;/?:@&=+$, bar'"complex;/?:@&=+$, foo'" bar2foo1 bar1Remarks
Section titled “Remarks”The regular expression used in the Decode URL examples was taken from RFC 2396, Appendix B: Parsing a URI Reference with a Regular Expression; for posterity, here’s a quote:
The following line is the regular expression for breaking-down a URI reference into its components.
^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))? 12 3 4 5 6 7 8 9The numbers in the second line above are only to assist readability; they indicate the reference points for each subexpression (i.e., each paired parenthesis). We refer to the value matched for subexpression as $. For example, matching the above expression to
http://www.ics.uci.edu/pub/ietf/uri/#Relatedresults in the following subexpression matches:
$1 = http:$2 = http$3 = //www.ics.uci.edu$4 = www.ics.uci.edu$5 = /pub/ietf/uri/$6 = <undefined>$7 = <undefined>$8 = #Related$9 = Related