Я работаю над средством проверки ссылок, в общем, я могу выполнять запросы 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
, вся загрузка загружается (я смотрел это в wirehark).
Есть ли способ настроить базовые ServicePoint
или HttpWebRequest
, чтобы не буферизовать или не загружать тело ответа вообще?
(Если бы я был ручным кодированием, я бы установил очень малое окно приема TCP, а затем хватало достаточно пакетов, чтобы получить заголовки, прекратите отмечать TCP-пакеты, как только у меня будет достаточно информации.)
для тех, кто задается вопросом, чего это должно достичь, я не хочу загружать 40k 404, когда я получаю 404, делая это несколько сотен тысяч раз дороже в сети