- ベストアンサー
http Hostヘッダの設定
VB.NET2008で RESTでhttpヘッダのHostを指定する必要があるプログラムを組んでいます。 WebClientクラスで行おうと思っているのですが、 WebClient.Headers.Add("Host","www.xxxx.co.jp")だと WebClient要求で例外が発生しました。 エラーが発生してしまいます。 Hostを指定することはできないのでしょうか? Socketを使用すればできるのはわかるのですが、SSL使用のため、敷居が高くて・・・ お願いいたします。
- みんなの回答 (4)
- 専門家の回答
質問者が選んだベストアンサー
SslStream.WriteTimeout/ReadTimeoutは元となるストリームの同プロパティを呼び出しているだけのようです。 元はNetworkStreamなのでこちらを見てみるとReadTimeoutプロパティの説明に このプロパティで指定した時間内に読み取り操作が完了しない場合、読み取り操作は IOException をスローします。 同じくWriteTimeoutプロパティも このプロパティで指定した時間内に書き込み操作が完了しない場合、書き込み操作は IOException をスローします。 となっているので、どちらもTry-Catchですね。実際に試してはいませんが。投げられるのが単なるIOExceptionだと、タイムアウト以外でも投げられる可能性があるかも・・・? そうなると判定は厄介ですね。Exception.Dataにタイムアウト特有の値があったりすれば判別可能ですけど。。。
その他の回答 (3)
- うぃず(@Wizard_Zero)
- ベストアンサー率69% (344/495)
> sslStream.Write Readでなくても大丈夫なのでしょうか? HTTPのヘッダに関してはリクエスト・レスポンスともに文字セットはUS-ASCII、改行コードは CR+LF で規定されてるはずです。なので、ASCIIエンコードのStreamWriter/Readerで読み書きちゃって大丈夫だと思います。 ただReadに関してHTML本体はヘッダのContent-Typeや<meta>で定義されたcharsetによるので、ヘッダと本体は本来別々に読まないといけないんですけど手抜きでまとめ読みしてます。。。 SslStreamの使用例があまりネットにないようなので、#2に投稿したコードを元にクラス化したコードをブログに載せました。よろしければそちらもごらんになってみてください。
お礼
ご回答いただきまして、ありがとうございます。 ご返答が遅くなり申し訳ありません。 サンプルまで載せていただき、助かります。 ここで、別の質問にもなるのですが sslstreamを使用している場合、タイムアウトは sslStream.ReadTimeout、sslStream.WriteTimeoutで可能だと思うのですが、 タイムアウトが発生した場合、その状態をキャッチするには、どのように したら良いのでしょうか?
- うぃず(@Wizard_Zero)
- ベストアンサー率69% (344/495)
Public Class Form1 Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click ' 指定したホストと接続したSSLストリームを取得 Using srm As IO.Stream = GetSslStream("hogehoge") ' HTTPリクエストの作成 Dim writer As New IO.StreamWriter(srm, System.Text.Encoding.ASCII) writer.WriteLine("GET /index.html HTTP/1.0") writer.WriteLine() writer.Flush() ' HTTPレスポンスの読み込み Dim reader As New IO.StreamReader(srm, System.Text.Encoding.ASCII) Dim stb As New System.Text.StringBuilder() While Not reader.EndOfStream stb.AppendLine(reader.ReadLine) End While TextBox1.Text = stb.ToString() End Using End Sub ' 指定したホストにHTTPSで接続 Private Function GetSslStream(ByVal RemoteHost As String) As IO.Stream ' TcpClientで接続 Dim client As New Net.Sockets.TcpClient() client.Connect(RemoteHost, 443) ' サーバー証明書の確認用メソッドのデリゲート Dim callback As Net.Security.RemoteCertificateValidationCallback callback = AddressOf ConnectionRemoteCertificateValidationCallback ' SSLストリームの作成とサーバー証明書の取り込み Dim ssl As New Net.Security.SslStream(client.GetStream(), True, callback) ssl.AuthenticateAsClient(RemoteHost) ' ストリームを返す Return ssl End Function ' 証明書の内容チェック用コールバック Private Function ConnectionRemoteCertificateValidationCallback( _ ByVal sender As Object, _ ByVal certificate As System.Security.Cryptography.X509Certificates.X509Certificate, _ ByVal chain As System.Security.Cryptography.X509Certificates.X509Chain, _ ByVal sslPolicyErrors As System.Net.Security.SslPolicyErrors) As Boolean ' すべての証明書を許可 Return True End Function End Class 恐ろしく手抜きなコードですがこんな具合です。
補足
早速のご返答ありがとうございます。 1点質問なんですがリクエストの読み書きにIO.StreamWriter Readerを 使用していますが、sslStream.Write Readでなくても大丈夫なのでしょうか?
- うぃず(@Wizard_Zero)
- ベストアンサー率69% (344/495)
手作業でヘッダに追加しなくても、ダウンロード系メソッドでURIを指定すれば、そのホスト名がヘッダに付加されるはずです。 URIと違うホスト名を指定、などの状況なのでしょうか?? どちらにしてもWebClientの要求ヘッダでHostの書き換えは不可のようです。 SSL通信は TcpClient と SslStream を使えばそれほど敷居高くないですよ。
補足
ご回答ありがとうございます。 詳細は分かっていないのですが、業者指定のホスト名を指定しなくてはならないのです。 WebClientではHostの書き換えは不可能ですか・・・ SslStreamの詳細の説明が見つからなくって困ってます。 説明しているサイトなどありましたら紹介お願いいたします。 (自分でももう一回調べます)
お礼
ご回答ありがとうございます。 確かにsslStream.WriteTimeoutの説明を見るとオーバライドしていますね。 IOExceptionで返ってくるにしても他の異常でも投げられますよね・・。 タイムオーバーの環境を強引に作成して試してみます。 結果をここに載せたいと思いますので、しばらくお時間をください。