1 // ================================================================================================
3 // アプリケーション設定値を用いてウェブアクセスするプロキシクラスソース</summary>
5 // <copyright file="AppConfigWebProxy.cs" company="honeplusのメモ帳">
6 // Copyright (C) 2012 Honeplus. All rights reserved.</copyright>
9 // ================================================================================================
11 namespace Honememo.Wptscs.Utilities
16 using System.Reflection;
17 using System.Threading;
18 using Honememo.Utilities;
19 using Honememo.Wptscs.Properties;
22 /// アプリケーション設定値を用いてウェブアクセスするプロキシクラスです。
24 public class AppConfigWebProxy : IWebProxy
29 /// このプロキシで使用するUserAgent。
31 private string userAgent;
34 /// このプロキシで使用するReferer。
36 private string referer;
40 #region インタフェース実装プロパティ
43 /// このプロキシで使用するUserAgent。
45 /// <remarks>アプリ設定値→プロパティ→アプリデフォルト値を生成 の順に見つけたものを返す。</remarks>
46 public string UserAgent
51 string ua = Settings.Default.UserAgent;
52 if (!String.IsNullOrEmpty(ua))
57 // 存在しない場合、このプロパティの値を確認
58 if (this.userAgent != null)
60 return this.userAgent;
63 // いずれも存在しない場合は、デフォルトの値を生成して返す
64 Version ver = Assembly.GetExecutingAssembly().GetName().Version;
65 return String.Format(Settings.Default.DefaultUserAgent, ver.Major, ver.Minor);
70 this.userAgent = value;
75 /// このプロキシで使用するReferer。
77 /// <remarks>アプリ設定値→プロパティ の順に見つけたものを返す。</remarks>
83 string r = Settings.Default.Referer;
84 if (String.IsNullOrEmpty(r))
86 // 存在しない場合、このプロパティの値を返す
90 return StringUtils.DefaultString(r);
101 #region インタフェース実装メソッド
104 /// 指定されたURIの情報をストリームで取得。
106 /// <param name="uri">取得対象のURI。</param>
107 /// <returns>取得したストリーム。使用後は必ずクローズすること。</returns>
109 /// 通信エラー等の場合、アプリケーション設定に指定されている回数リトライする。
110 /// それでも取得できない場合は例外を投げる。
112 public Stream GetStream(Uri uri)
114 // 実際の処理はサブメソッドで行い、このメソッドでは通信エラー時のリトライを行う
115 int retry = Settings.Default.MaxConnectRetries;
116 int wait = Settings.Default.ConnectRetryTime;
121 return this.GetStreamBody(uri);
123 catch (WebException e)
125 // 通信エラーの場合、指定回数までリトライを試みる
126 if (--retry < 0 || !this.IsRetryable(e))
128 // リトライ回数を消化、またはリトライしても意味が無い場合、そのまま例外を投げる
132 // 時間を置いてからリトライする(0はスレッド停止のため除外)
133 System.Diagnostics.Debug.WriteLine("AppConfigWebProxy.GetStream > retry : " + e.Message);
147 /// 指定されたURIの情報をストリームで取得。
149 /// <param name="uri">取得対象のURI。</param>
150 /// <returns>取得したストリーム。使用後は必ずクローズすること。</returns>
152 /// 通信エラー等の場合、アプリケーション設定に指定されている回数リトライする。
153 /// それでも取得できない場合は例外を投げる。
155 private Stream GetStreamBody(Uri uri)
157 // URIに応じたWebRequestを取得
158 WebRequest req = WebRequest.Create(uri);
161 // ※ HttpWebRequest, FileWebRequestを想定(後者は特に処理無し)
163 if (req is HttpWebRequest)
166 this.InitializeHttpWebRequest((HttpWebRequest)req);
169 // 応答データを受信するためのStreamを取得し、データを取得
170 return req.GetResponse().GetResponseStream();
174 /// <see cref="HttpWebRequest"/>用の設定を行う。
176 /// <param name="req">設定対象の<see cref="HttpWebRequest"/>。</param>
177 private void InitializeHttpWebRequest(HttpWebRequest req)
180 req.UserAgent = this.UserAgent;
183 req.Referer = this.Referer;
185 // 可能であれば自動的に圧縮を行う用設定
186 req.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;
190 /// 渡された<see cref="WebException"/>がリトライ可能なものか?
192 /// <param name="e">発生した<see cref="WebException"/>。</param>
193 /// <returns>リトライ可能な場合<c>true</c>。</returns>
194 private bool IsRetryable(WebException e)
196 // HTTPプロトコルエラーの場合、ステータスコードで判断する
197 if (e.Status == WebExceptionStatus.ProtocolError)
199 HttpStatusCode sc = ((HttpWebResponse)e.Response).StatusCode;
200 return sc == HttpStatusCode.InternalServerError
201 || sc == HttpStatusCode.BadGateway
202 || sc == HttpStatusCode.ServiceUnavailable
203 || sc == HttpStatusCode.GatewayTimeout;
206 // それ以外は、応答ステータスで判断する
207 // ※ fileスキームのエラー等はUnknownErrorで来るので注意
208 return e.Status != WebExceptionStatus.TrustFailure
209 && e.Status != WebExceptionStatus.UnknownError
210 && e.Status != WebExceptionStatus.RequestProhibitedByCachePolicy
211 && e.Status != WebExceptionStatus.RequestProhibitedByProxy;