私はリンクチェッカーに取り組んでいます。通常はHEAD
リクエストを実行できますが、一部のサイトではこの動詞が無効になっているようです。そのため、失敗した場合はGET
リクエストも実行する必要があります (リンクが実際に無効であることを再確認するため)。
リンクテスターとして次のコードを使用します。
public class ValidateResult
{
public HttpStatusCode? StatusCode { get; set; }
public Uri RedirectResult { get; set; }
public WebExceptionStatus? WebExceptionStatus { get; set; }
}
public ValidateResult Validate(Uri uri, bool useHeadMethod = true,
bool enableKeepAlive = false, int timeoutSeconds = 30)
{
ValidateResult result = new ValidateResult();
HttpWebRequest request = WebRequest.Create(uri) as HttpWebRequest;
if (useHeadMethod)
{
request.Method = "HEAD";
}
else
{
request.Method = "GET";
}
// always compress, if you get back a 404 from a HEAD it can be quite big.
request.AutomaticDecompression = DecompressionMethods.GZip;
request.AllowAutoRedirect = false;
request.UserAgent = UserAgentString;
request.Timeout = timeoutSeconds * 1000;
request.KeepAlive = enableKeepAlive;
HttpWebResponse response = null;
try
{
response = request.GetResponse() as HttpWebResponse;
result.StatusCode = response.StatusCode;
if (response.StatusCode == HttpStatusCode.Redirect ||
response.StatusCode == HttpStatusCode.MovedPermanently ||
response.StatusCode == HttpStatusCode.SeeOther)
{
try
{
Uri targetUri = new Uri(Uri, response.Headers["Location"]);
var scheme = targetUri.Scheme.ToLower();
if (scheme == "http" || scheme == "https")
{
result.RedirectResult = targetUri;
}
else
{
// this little gem was born out of http://tinyurl.com/18r
// redirecting to about:blank
result.StatusCode = HttpStatusCode.SwitchingProtocols;
result.WebExceptionStatus = null;
}
}
catch (UriFormatException)
{
// another gem... people sometimes redirect to http://nonsense:port/yay
result.StatusCode = HttpStatusCode.SwitchingProtocols;
result.WebExceptionStatus = WebExceptionStatus.NameResolutionFailure;
}
}
}
catch (WebException ex)
{
result.WebExceptionStatus = ex.Status;
response = ex.Response as HttpWebResponse;
if (response != null)
{
result.StatusCode = response.StatusCode;
}
}
finally
{
if (response != null)
{
response.Close();
}
}
return result;
}
これはすべてうまく機能します。GET
リクエストを実行すると、ペイロード全体がダウンロードされることを除いて(私はこれをwiresharkで見ました)。
応答本文をバッファリングまたは熱心にロードしないServicePoint
ように、基礎となるものを構成する方法はありますか?HttpWebRequest
(これを手作業でコーディングしていた場合、TCP 受信ウィンドウを非常に低く設定し、ヘッダーを取得するのに十分なパケットのみを取得し、十分な情報が得られたらすぐに TCP パケットの ack を停止します。)
これが何を達成しようとしているのか疑問に思っている人のために、404 を取得したときに 40k の 404 をダウンロードしたくありません。これを数十万回行うと、ネットワークに負荷がかかります。