DOBON.NET

URLを解析する

URL(URI)を解析して、サーバー名、ポート番号、スキーム名、絶対パス、クエリ情報、フラグメント、ユーザー名、パスワードなどの情報を取得することは、その文字列を自分で解析することでも可能ですが、.NET FrameworkではUriクラスを使うと非常に簡単です。

早速ですが、以下に

http://user:pass@www.dobon.net:80/vb/bbs.cgi?id=a%20b&n=1#top

というURLを解析する例を示します。

VB.NET
コードを隠すコードを選択
'解析するURL(このURLは実在しません) 
Dim url As String = "http://user:pass@www.dobon.net:80/vb/bbs.cgi?id=a%20b&n=1#top"

'Uriオブジェクトを作成 
Dim u As New Uri(url)

'絶対パス 
Console.WriteLine(u.AbsolutePath)
'結果: /vb/bbs.cgi 

'絶対URI 
Console.WriteLine(u.AbsoluteUri)
'結果: http://user:pass@www.dobon.net/vb/bbs.cgi?id=a%20b&n=1#top 

'サーバーのDNS(Domain Name System)ホスト名またはIPアドレスと、ポート番号 
Console.WriteLine(u.Authority)
'結果: www.dobon.net 

'DNSの解決に安全に使用できるエスケープ解除されたホスト名 
Console.WriteLine(u.DnsSafeHost)
'結果: www.dobon.net 

'エスケープフラグメント 
Console.WriteLine(u.Fragment)
'結果: #top 

'サーバーのDNSホスト名またはIPアドレス 
Console.WriteLine(u.Host)
'結果: www.dobon.net 

'ホスト名の型 
Select Case u.HostNameType
    Case UriHostNameType.Basic
        Console.WriteLine("ホストは設定されましたが、型を決定できません。")
        Exit Select
    Case UriHostNameType.Dns
        Console.WriteLine("ホスト名は、ドメイン名システム形式のホスト名です。")
        Exit Select
    Case UriHostNameType.IPv4
        Console.WriteLine("ホスト名は、IP Version 4 形式のホストアドレスです。")
        Exit Select
    Case UriHostNameType.IPv6
        Console.WriteLine("ホスト名は、IP Version 6 形式のホスト アドレスです。")
        Exit Select
    Case UriHostNameType.Unknown
        Console.WriteLine("ホスト名の型が指定されていません。")
        Exit Select
End Select
'結果: ホスト名は、ドメイン名システム形式のホスト名です。 

'絶対インスタンスであるかどうか 
Console.WriteLine(u.IsAbsoluteUri)
'結果: True 

'ポート値がこのスキームの既定のポート値かどうか 
Console.WriteLine(u.IsDefaultPort)
'結果: True 

'ファイルURIかどうか 
Console.WriteLine(u.IsFile)
'結果: False 

'ローカルホストを参照するかどうか 
Console.WriteLine(u.IsLoopback)
'結果: False 

'UNCパスかどうか 
Console.WriteLine(u.IsUnc)
'結果: False 

'Uriコンストラクタに渡された元のURI文字列 
Console.WriteLine(u.OriginalString)
'結果: http://user:pass@www.dobon.net:80/vb/bbs.cgi?id=a%20b&n=1#top 

'ローカルオペレーティングシステムでのファイル名表現 
Console.WriteLine(u.LocalPath)
'結果: /vb/bbs.cgi 

'AbsolutePathプロパティとQueryプロパティを疑問符(?)で区切った形式 
Console.WriteLine(u.PathAndQuery)
'結果: /vb/bbs.cgi?id=a%20b&n=1 

'ポート番号 
Console.WriteLine(u.Port)
'結果: 80 

'クエリ情報 
Console.WriteLine(u.Query)
'結果: ?id=a%20b&n=1 

'スキーム名 
Console.WriteLine(u.Scheme)
'結果: http 

'セグメント 
For Each s As String In u.Segments
    Console.WriteLine(vbTab & s)
Next
'結果: 
' / 
' vb/ 
' bbs.cgi 

'Uriインスタンスの作成前に、URI文字列がエスケープされているか 
Console.WriteLine(u.UserEscaped)
'結果: False 

'ユーザー名、パスワードなどのユーザー固有の情報 
Console.WriteLine(u.UserInfo)
'結果: user:pass 

'左端からスキームまで 
Console.WriteLine(u.GetLeftPart(UriPartial.Scheme))
'結果: http:// 

'左端から権限まで 
Console.WriteLine(u.GetLeftPart(UriPartial.Authority))
'結果: http://user:pass@www.dobon.net 

'左端からパスまで 
Console.WriteLine(u.GetLeftPart(UriPartial.Path))
'結果: http://user:pass@www.dobon.net/vb/bbs.cgi 

'左端からクエリまで 
Console.WriteLine(u.GetLeftPart(UriPartial.Query))
'結果: http://user:pass@www.dobon.net/vb/bbs.cgi?id=a%20b&n=1 

'エスケープ解除された正規形式のURI 
Console.WriteLine(u.ToString())
'結果: http://user:pass@www.dobon.net/vb/bbs.cgi?id=a b&n=1#top
C#
コードを隠すコードを選択
//解析するURL(このURLは実在しません)
string url = "http://user:pass@www.dobon.net:80/vb/bbs.cgi?id=a%20b&n=1#top";

//Uriオブジェクトを作成
Uri u = new Uri(url);

//絶対パス 
Console.WriteLine(u.AbsolutePath);
//結果: /vb/bbs.cgi

//絶対URI
Console.WriteLine(u.AbsoluteUri);
//結果: http://user:pass@www.dobon.net/vb/bbs.cgi?id=a%20b&n=1#top

//サーバーのDNS(Domain Name System)ホスト名またはIPアドレスと、ポート番号
Console.WriteLine(u.Authority);
//結果: www.dobon.net

//DNSの解決に安全に使用できるエスケープ解除されたホスト名
Console.WriteLine(u.DnsSafeHost);
//結果: www.dobon.net

//エスケープフラグメント
Console.WriteLine(u.Fragment);
//結果: #top

//サーバーのDNSホスト名またはIPアドレス
Console.WriteLine(u.Host);
//結果: www.dobon.net

//ホスト名の型
switch (u.HostNameType)
{
    case UriHostNameType.Basic:
        Console.WriteLine(
            "ホストは設定されましたが、型を決定できません。");
        break;
    case UriHostNameType.Dns:
        Console.WriteLine(
            "ホスト名は、ドメイン名システム形式のホスト名です。");
        break;
    case UriHostNameType.IPv4:
        Console.WriteLine(
            "ホスト名は、IP Version 4 形式のホストアドレスです。");
        break;
    case UriHostNameType.IPv6:
        Console.WriteLine(
            "ホスト名は、IP Version 6 形式のホスト アドレスです。");
        break;
    case UriHostNameType.Unknown:
        Console.WriteLine("ホスト名の型が指定されていません。");
        break;
}
//結果: ホスト名は、ドメイン名システム形式のホスト名です。

//絶対インスタンスであるかどうか
Console.WriteLine(u.IsAbsoluteUri);
//結果: True

//ポート値がこのスキームの既定のポート値かどうか
Console.WriteLine(u.IsDefaultPort);
//結果: True

//ファイルURIかどうか
Console.WriteLine(u.IsFile);
//結果: False

//ローカルホストを参照するかどうか
Console.WriteLine(u.IsLoopback);
//結果: False

//UNCパスかどうか
Console.WriteLine(u.IsUnc);
//結果: False

//Uriコンストラクタに渡された元のURI文字列
Console.WriteLine(u.OriginalString);
//結果: http://user:pass@www.dobon.net:80/vb/bbs.cgi?id=a%20b&n=1#top

//ローカルオペレーティングシステムでのファイル名表現
Console.WriteLine(u.LocalPath);
//結果: /vb/bbs.cgi

//AbsolutePathプロパティとQueryプロパティを疑問符(?)で区切った形式
Console.WriteLine(u.PathAndQuery);
//結果: /vb/bbs.cgi?id=a%20b&n=1

//ポート番号
Console.WriteLine(u.Port);
//結果: 80

//クエリ情報
Console.WriteLine(u.Query);
//結果: ?id=a%20b&n=1

//スキーム名
Console.WriteLine(u.Scheme);
//結果: http

//セグメント
foreach (string s in u.Segments)
    Console.WriteLine("\t" + s);
//結果: 
//    /
//    vb/
//    bbs.cgi

//Uriインスタンスの作成前に、URI文字列がエスケープされているか
Console.WriteLine(u.UserEscaped);
//結果: False

//ユーザー名、パスワードなどのユーザー固有の情報
Console.WriteLine(u.UserInfo);
//結果: user:pass

//左端からスキームまで
Console.WriteLine(u.GetLeftPart(UriPartial.Scheme));
//結果: http://

//左端から権限まで
Console.WriteLine(u.GetLeftPart(UriPartial.Authority));
//結果: http://user:pass@www.dobon.net

//左端からパスまで
Console.WriteLine(u.GetLeftPart(UriPartial.Path));
//結果: http://user:pass@www.dobon.net/vb/bbs.cgi

//左端からクエリまで
Console.WriteLine(u.GetLeftPart(UriPartial.Query));
//結果: http://user:pass@www.dobon.net/vb/bbs.cgi?id=a%20b&n=1

//エスケープ解除された正規形式のURI 
Console.WriteLine(u.ToString());
//結果: http://user:pass@www.dobon.net/vb/bbs.cgi?id=a b&n=1#top

Uriクラスのプロパティのまとめ

上記の例のように、"http://user:pass@www.dobon.net:80/vb/bbs.cgi?id=a%20b&n=1#top"を指定して作成したUriオブジェクトのプロパティやメソッドが返す値を表にまとめると、以下のようになります。

プロパティまたはメソッド説明
AbsolutePath絶対パス/vb/bbs.cgi
AbsoluteUri絶対URIhttp://user:pass@www.dobon.net/vb/bbs.cgi?id=a%20b&n=1#top
AuthorityサーバーのDNS(Domain Name System)ホスト名またはIPアドレスと、ポート番号。ポート番号はスキームの既定でない場合のみ付加される(例えば、"www.dobon.net:8080")。予約文字はエスケープされる。www.dobon.net
DnsSafeHostDNSの解決に安全に使用できるエスケープ解除されたホスト名。IPv6アドレスの場合、角かっこ([])が削除され、さらにScopeIdプロパティが設定されている時はスコープが付加される。(.NET Framework 2.0で追加)www.dobon.net
Fragmentエスケープフラグメント#top
HostサーバーのDNSホスト名またはIPアドレス。Authorityと違い、ポート番号を含まない。www.dobon.net
HostNameTypeホスト名の型。Dnsは、ドメイン名システム形式。IPv4は、IP Version 4 形式。IPv6は、IP Version 6 形式。Basicは、ホストは設定されたが、型を決定できない。Unknownは、型が指定されていない。UriHostNameType.Dns
IsAbsoluteUri絶対インスタンスとして解析できるか(.NET Framework 2.0で追加)True
IsDefaultPortポート値がこのスキームの既定のポート値かどうか。例えば、スキームが"http"ならばポート値が80の場合にTrue。True
IsFileファイルURIかどうか。SchemeプロパティがUri.UriSchemeFileフィールド("file")と等しい場合にTrue。False
IsLoopbackローカルホストを参照するかどうか。"127.0.0.1"、"loopback"、または"localhost"のいずれかか、ホスト情報が指定されていない場合("file:///C:Dir/file.txt"など)にTrue。False
IsUncUNCパスかどうか。"\\server\folder"などのようなパスか、スキームが"file://"でホスト構成要素を指定している場合にTrue。False
LocalPathローカルオペレーティングシステムでのファイル名表現。エスケープが解除される。パスがWindowsファイルパスとして認識される場合は、"/"が"\"に置換される。/vb/bbs.cgi
OriginalStringUriコンストラクタに渡された元のURI文字列(.NET Framework 2.0で追加)http://user:pass@www.dobon.net:80/vb/bbs.cgi?id=a%20b&n=1#top
PathAndQueryAbsolutePathプロパティとQueryプロパティを疑問符(?)で区切った形式/vb/bbs.cgi?id=a%20b&n=1
Portポート番号。URI内にポートが指定されていない場合は、プロトコルの既定値。既定のポート番号がない場合は、-1。80
Queryクエリ情報?id=a%20b&n=1
Schemeスキーム名http
SegmentsURIを構成するパスセグメント。文字列の配列を返す。/
vb/
bbs.cgi
UserEscapedUriインスタンスの作成前に、URI文字列がエスケープされているか(コンストラクタのdontEscapeパラメーターがTrueに設定されていたか)。False
UserInfoユーザー名、パスワードなどのユーザー固有の情報user:pass
GetLeftPart(UriPartial.Scheme)左端からスキームまでhttp://
GetLeftPart(UriPartial.Authority)左端から権限までhttp://user:pass@www.dobon.net
GetLeftPart(UriPartial.Path)左端からパスまでhttp://user:pass@www.dobon.net/vb/bbs.cgi
GetLeftPart(UriPartial.Query)左端からクエリまで(.NET Framework 2.0で追加)http://user:pass@www.dobon.net/vb/bbs.cgi?id=a%20b&n=1
ToString()エスケープ解除された正規形式のURIhttp://user:pass@www.dobon.net/vb/bbs.cgi?id=a b&n=1#top

Uriコンストラクタで行われるURLエンコードとデコードについて

Uriクラスは、与えられたURLを正規形式で格納するために、URLにASCII文字以外の文字が含まれている場合は、その文字をコンストラクタでURLエンコード(エスケープ)します。

より正確に言うと、ASCII文字以外の文字ではなく、.NET Framework 4.5以降ではRFC3986およびRFC3987の非予約文字と予約文字以外の文字、それ以前ではRFC2396の非予約文字と予約文字以外の文字をURLエンコードしているようです。URLエンコードについて詳しくは、「URLエンコード、URLデコードを行う」をご覧ください。

補足:必ず非予約文字と予約文字以外の文字がエンコードされる訳ではなく、スキームや、文字のある場所などによってエンコードする文字が変わるようです。

例えば次のようなコードによって、どのようにURLエンコードが行われているかを確認することができます。なおここで紹介している結果は、.NET Framework 4.5でのものです。

VB.NET
コードを隠すコードを選択
Dim url As String = "http://www.dobon.net/あ/%26.cgi" & _
    "?id=!()_-*.aA0 ?$%&|@\/#[]{}<>+=^~""'`;:,"

'Uriオブジェクトを作成
Dim u As New Uri(url)

Console.WriteLine(u.AbsolutePath)
' /%E3%81%82/%26.cgi

Console.WriteLine(u.Query)
' ?id=!()_-*.aA0%20?$%25&%7C@%5C/

Console.WriteLine(u.Fragment)
' #[]%7B%7D%3C%3E+=%5E~%22'%60;:,
C#
コードを隠すコードを選択
string url = "http://www.dobon.net/あ/%26.cgi" +
    "?id=!()_-*.aA0 ?$%&|@\\/#[]{}<>+=^~\"'`;:,";

//Uriオブジェクトを作成
Uri u = new Uri(url);

Console.WriteLine(u.AbsolutePath);
// /%E3%81%82/%26.cgi

Console.WriteLine(u.Query);
// ?id=!()_-*.aA0%20?$%25&%7C@%5C/

Console.WriteLine(u.Fragment);
// #[]%7B%7D%3C%3E+=%5E~%22'%60;:,

またUriクラスは、与えられたURLに「%xx」形式の16進数値が含まれている時、その一部をコンストラクタでデコードしているようです。私が試したところでは、半角英数字と「!()_-*.[]~':」(.NET Framework 4.0では、半角英数字と「!()_-*.~':」)(つまり、非予約文字すべてと、予約文字の一部)の「%xx」表現が含まれている時、これらがデコードされました。

VB.NET
コードを隠すコードを選択
Dim url As String = "http://www.dobon.net/a.cgi" & _
    "?%21%28%29%5F%2D%2A%2E%61%41%30%5B%5D%7E%27%3A"

'Uriオブジェクトを作成
Dim u As New Uri(url)

Console.WriteLine(u.Query)
' ?!()_-*.aA0[]~':
C#
コードを隠すコードを選択
string url = "http://www.dobon.net/a.cgi" +
    "?%21%28%29%5F%2D%2A%2E%61%41%30%5B%5D%7E%27%3A";

//Uriオブジェクトを作成
Uri u = new Uri(url);

Console.WriteLine(u.Query);
// ?!()_-*.aA0[]~':

AbsoluteUriプロパティ、OriginalStringプロパティ、ToStringメソッドの違い

MSDNの「Uri.OriginalString プロパティ」と「Uri.ToString メソッド」の説明を総合すると、ToStringメソッドは、#、?、%以外のすべての文字のエスケープを解除し、AbsoluteUriプロパティは一切エスケープ解除をしないと解釈できます。しかし、ToStringメソッドについては、実際は少し違うようです。

実際に試してみると、ToStringメソッドは「?#$%&@\/+=;,」の「%xx」表現である「%3F%23%24%25%26%40%5C%2F%2B%3D%3B%2C」をデコードしませんでした。また、「+」をスペースに変換しませんでした。

VB.NET
コードを隠すコードを選択
Dim url As String = "http://www.dobon.net/bbs.cgi?" & _
    "%3F%23%24%25%26%40%5C%2F%2B%3D%3B%2C%E3%81%82+"

'Uriオブジェクトを作成
Dim u As New Uri(url)

Console.WriteLine(u.AbsoluteUri)
'http://www.dobon.net/bbs.cgi?%3F%23%24%25%26%40%5C%2F%2B%3D%3B%2C%E3%81%82+

Console.WriteLine(u.ToString())
'http://www.dobon.net/bbs.cgi?%3F%23%24%25%26%40%5C%2F%2B%3D%3B%2Cあ+
C#
コードを隠すコードを選択
string url = "http://www.dobon.net/bbs.cgi?" +
    "%3F%23%24%25%26%40%5C%2F%2B%3D%3B%2C%E3%81%82+";

//Uriオブジェクトを作成
Uri u = new Uri(url);

Console.WriteLine(u.AbsoluteUri);
//http://www.dobon.net/bbs.cgi?%3F%23%24%25%26%40%5C%2F%2B%3D%3B%2C%E3%81%82+

Console.WriteLine(u.ToString());
//http://www.dobon.net/bbs.cgi?%3F%23%24%25%26%40%5C%2F%2B%3D%3B%2Cあ+

.NET Framework 2.0から追加されたOriginalStringプロパティは、基本的には、Uriオブジェクトを作成するときに指定された文字列をそのまま返します。

UriコンストラクタではURLエンコードとデコードが行われると説明しましたが、それ以外にも、ポート番号がスキームの既定のポート番号と同じならば削除するなどの変換が行われます。しかしOriginalStringプロパティは、そのような変換が行われる前の文字列を返します。

以下の例でその違いをご確認ください。

VB.NET
コードを隠すコードを選択
Dim url As String = "http://www.dobon.net:80/あ/%41.cgi" & _
    "?id=!()_-*.aA0 ?$%&|@\/#[]{}<>+=^~""'`;:,"

'Uriオブジェクトを作成
Dim u As New Uri(url)

Console.WriteLine(u.AbsoluteUri)
'http://www.dobon.net/%E3%81%82/A.cgi?id=!()_-*.aA0%20?$%25&%7C@%5C/#[]
'%7B%7D%3C%3E+=%5E~%22'%60;:,

Console.WriteLine(u.ToString())
'http://www.dobon.net/あ/A.cgi?id=!()_-*.aA0 ?$%25&|@\/#[]{}<>+=^~"'`;:,

Console.WriteLine(u.OriginalString)
'http://www.dobon.net:80/あ/%41.cgi?id=!()_-*.aA0 ?$%&|@\/#[]{}<>+=^~"'`;:,
C#
コードを隠すコードを選択
string url = "http://www.dobon.net:80/あ/%41.cgi" +
    "?id=!()_-*.aA0 ?$%&|@\\/#[]{}<>+=^~\"'`;:,";

//Uriオブジェクトを作成
Uri u = new Uri(url);

Console.WriteLine(u.AbsoluteUri);
//http://www.dobon.net/%E3%81%82/A.cgi?id=!()_-*.aA0%20?$%25&%7C@%5C/#[]
//%7B%7D%3C%3E+=%5E~%22'%60;:,

Console.WriteLine(u.ToString());
//http://www.dobon.net/あ/A.cgi?id=!()_-*.aA0 ?$%25&|@\/#[]{}<>+=^~"'`;:,

Console.WriteLine(u.OriginalString);
//http://www.dobon.net:80/あ/%41.cgi?id=!()_-*.aA0 ?$%&|@\/#[]{}<>+=^~"'`;:,

HostとDnsSafeHostプロパティの違い

HostとDnsSafeHostプロパティについては、「ホスト名(ドメイン名)をPunycodeに変換(エンコード、デコード)する」をご覧ください。

Uri.GetComponentsメソッドを使用する方法

今まで紹介してきたUriクラスのプロパティで取得できる情報のほとんどをUri.GetComponentsメソッドを使って取得することもできます。このメソッドは、.NET Framework 2.0以降で使用できます。

GetComponentsメソッドを使うと、例えばスキームとホスト名とパスを連結した文字列を取得するというように、複数の部分を一度に取得することができます。どの部分を取得するかは、UriComponents列挙体値のビット組み合わせで指定します。

またGetComponentsメソッドでは、URLエンコードを行うかを指定することもできます。UriFormat列挙体のUriEscapedを指定すればエンコードし、Unescapedを指定すればエンコードしません。SafeUnescapedを指定すると、UriComponentsで指定された部分で意味が予約されていれば、"%"、"#"、"?"、"/"、"\"、"@"がエンコードされます。

以下にGetComponentsメソッドの使用例を示します。

VB.NET
コードを隠すコードを選択
'解析するURL(このURLは実在しません)
Dim url As String = _
    "http://user:pass@www.dobon.net:80/a/b.cgi?id=a%20b&%?/\@##top"

'Uriオブジェクトを作成
Dim u As New Uri(url)

'スキームとパスを取得する
Console.WriteLine( _
    u.GetComponents(UriComponents.Scheme Or UriComponents.Path, _
                    UriFormat.SafeUnescaped))
'http:///a/b.cgi

'クエリーを取得する
'URLエンコードしない
Console.WriteLine( _
    u.GetComponents(UriComponents.Query, UriFormat.Unescaped))
'id=a b&%?/\@

'URLエンコードする
Console.WriteLine( _
    u.GetComponents(UriComponents.Query, UriFormat.UriEscaped))
'id=a%20b&%25?/%5C@

'意味が予約されている文字だけをURLエンコードする
Console.WriteLine( _
    u.GetComponents(UriComponents.Query, UriFormat.SafeUnescaped))
'id=a b&%25?/\@
C#
コードを隠すコードを選択
//解析するURL(このURLは実在しません)
string url = "http://user:pass@www.dobon.net:80/a/b.cgi?id=a%20b&%?/\\@##top";

//Uriオブジェクトを作成
Uri u = new Uri(url);

//スキームとパスを取得する
Console.WriteLine(
    u.GetComponents(UriComponents.Scheme | UriComponents.Path,
        UriFormat.SafeUnescaped));
//http:///a/b.cgi

//クエリーを取得する
//URLエンコードしない
Console.WriteLine(
    u.GetComponents(UriComponents.Query, UriFormat.Unescaped));
//id=a b&%?/\@

//URLエンコードする
Console.WriteLine(
    u.GetComponents(UriComponents.Query, UriFormat.UriEscaped));
//id=a%20b&%25?/%5C@

//意味が予約されている文字だけをURLエンコードする
Console.WriteLine(
    u.GetComponents(UriComponents.Query, UriFormat.SafeUnescaped));
//id=a b&%25?/\@
  • 履歴:
  • 2006/11/20 表を追加。
  • 2007/10/3 表中のGetLeftPart(UriPartial.Authority)を修正。GetLeftPart(UriPartial.Query)を追加。
  • 2009/1/9 説明を追加。
  • 2013/7/28 「Uri.GetComponentsメソッドを使用する方法」を追加。

注意:この記事では、基本的な事柄の説明が省略されているかもしれません。初心者の方は、特に以下の点にご注意ください。

  • .NET Tipsをご利用いただく際は、注意事項をお守りください。
共有する

この記事への評価

この記事へのコメント

この記事に関するコメントを投稿するには、下のボタンをクリックしてください。投稿フォームへ移動します。通常のご質問、ご意見等は掲示板へご投稿ください。