PS C:\Users\user> Split-Path "http://localhost:9200/index" -Parent
http:\\localhost:9200
In above example, I am trying to extract everything before the /index. I thought Split-Path would do the job but it changes the forward slashes in http:// to back slashes.
"http://localhost:9200/index" -replace ([Uri]"http://localhost:9200/index").AbsolutePath
I've worked out the above alternative which works but Split-Path just seems cleaner. Just wondering why it does that with the forward slashes?
Split-Path
works with provider paths only. Instead, use the .NET class Uri
that is specifically made for parsing URIs.
Using the method Uri.GetLeftPart()
, a partial URI can be extracted from the URI. This is much easier than building it "manually" by concatenating the URI components.
$uri = [uri] 'http://localhost:9200/index'
$uri.GetLeftPart('Authority')
# or as a one-liner:
([uri] 'http://localhost:9200/index').GetLeftPart('Authority')
Output:
http://localhost:9200
By passing other values from the UriPartial enum, different parts of the URI can be returned:
$uri = [uri] 'http://localhost:9200/index?param=value#anchor'
foreach( $part in 'Scheme','Authority','Path','Query' ) {
[pscustomobject]@{
Part = $part
URI = $uri.GetLeftPart( $part )
}
}
Output:
Part URI
---- ---
Scheme http://
Authority http://localhost:9200
Path http://localhost:9200/index
Query http://localhost:9200/index?param=value
As noted by this related C# answer, there is one catch with Uri.GetLeftPart()
:
If the port is the default port for the scheme, it will strip it out. E. g., the URI http://localhost:80/index
gets turned into http://localhost/index
, because port 80 is the default for the HTTP scheme.
If this is a problem, then you may use the UriBuilder
class to manually build the new URI from the parts of the original URI, while avoiding direct string manipulation:
Function Get-UriBase( [Parameter(Mandatory, ValueFromPipeline)] [Uri] $Uri ) {
process {
$uriBase = [UriBuilder]::new( $uri.Scheme, $uri.Host, $uri.Port ).ToString()
# Output $uriBase if original URI starts with this part
if( $uri.OriginalString.StartsWith( $uriBase ) ) {
return $uriBase
}
# Otherwise original URI didn't contain a port, so use GetLeftPart() which omits it
$uri.GetLeftPart('Authority')
}
}
foreach( $uri in 'http://localhost:80/index', 'http://localhost:1234/index', 'http://localhost/index' ) {
# For output in table format
[PSCustomObject]@{ URI = $uri; URI_Base = Get-UriBase $uri }
}
Output:
URI URI_Base
--- --------
http://localhost:80/index http://localhost:80/
http://localhost:1234/index http://localhost:1234/
http://localhost/index http://localhost