Sto lavorando a un correttore di link, in generale posso eseguire richieste HEAD
, tuttavia alcuni siti sembrano disabilitare questo verbo, quindi in caso di errore devo anche eseguire una richiesta GET
(per ricontrollare che il link sia davvero morto)Come posso eseguire una richiesta GET senza scaricare il contenuto?
io uso il seguente codice come il mio link tester:
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;
}
Questo tutto funziona bene e dandy. Tranne che quando eseguo una richiesta GET
, l'intero payload viene scaricato (l'ho visto in wireshark).
C'è un modo per configurare lo ServicePoint
sottostante o lo HttpWebRequest
per non bufferizzare o caricare il corpo della risposta a tutti?
(Se fossi d'uso e questo vorrei impostare la finestra di ricezione TCP veramente basso, e poi prendere solo abbastanza pacchetti per ottenere le intestazioni, smettere di ACKing pacchetti TCP, non appena ho abbastanza informazioni.)
per quelli che si chiedono che cosa si intende ottenere, non voglio scaricare un 40k 404 quando ottengo un 404, facendo questo alcune centinaia di migliaia di volte è costoso sulla rete
nota, anche se la codifica manuale della versione HTTP è abbastanza semplice, l'HTTPS mi spaventa un po '. (forse esiste già una libreria del sistema operativo?) –
Prova un download parziale. È possibile scaricare solo un intervallo con l'intestazione http del range. – rekire
@rekire 'Content-Range' può essere ok per i server HTTP 1.1 che hanno il contenuto, ma se si ottiene un 404, verrebbe comunque rispedito completamente –