2010-09-15 16 views
9

Sto lavorando a un progetto che prevede alcune operazioni di base per la scansione del web. Sto usando HttpWebRequest e HttpWebResponse abbastanza con successo. Per la gestione dei cookie ho solo un CookieContainer che assegno a HttpWebRequest.CookieContainer ogni volta. Automaticamente viene popolato con i nuovi cookie ogni volta e non richiede alcun trattamento aggiuntivo da parte mia. Tutto ciò ha funzionato fino a poco tempo fa quando uno dei siti Web che lavorava all'improvviso ha smesso di funzionare. Sono ragionevolmente sicuro che sia un problema con i cookie, ma non ho tenuto traccia dei cookie da quando funzionava, quindi non sono sicuro al 100%.CookieContainer gestione dei percorsi (Chi ha mangiato il mio cookie?)

Sono riuscito a simulare il problema come la vedo io con il seguente codice:

CookieContainer cookieJar = new CookieContainer(); 

Uri uri1 = new Uri("http://www.somedomain.com/some/path/page1.html"); 
CookieCollection cookies1 = new CookieCollection(); 
cookies1.Add(new Cookie("NoPathCookie", "Page1Value")); 
cookies1.Add(new Cookie("CookieWithPath", "Page1Value", "/some/path/")); 

Uri uri2 = new Uri("http://www.somedomain.com/some/path/page2.html"); 
CookieCollection cookies2 = new CookieCollection(); 
cookies2.Add(new Cookie("NoPathCookie", "Page2Value")); 
cookies2.Add(new Cookie("CookieWithPath", "Page2Value", "/some/path/")); 

Uri uri3 = new Uri("http://www.somedomain.com/some/path/page3.html"); 

// Add the cookies from page1.html 
cookieJar.Add(uri1, cookies1); 

// Add the cookies from page2.html 
cookieJar.Add(uri2, cookies2); 

// We should now have 3 cookies 
Console.WriteLine(string.Format("CookieJar contains {0} cookies", cookieJar.Count)); 

Console.WriteLine(string.Format("Cookies to send to page1.html: {0}", cookieJar.GetCookieHeader(uri1))); 
Console.WriteLine(string.Format("Cookies to send to page2.html: {0}", cookieJar.GetCookieHeader(uri2))); 
Console.WriteLine(string.Format("Cookies to send to page3.html: {0}", cookieJar.GetCookieHeader(uri3))); 

Questo simula la visita di due pagine, entrambi i quali stabiliscono due biscotti. Quindi controlla quali di quei cookie verrebbero impostati su ognuna delle tre pagine.

Dei due cookie, uno viene impostato senza specificare un percorso e l'altro ha un percorso specificato. Quando non viene specificato un percorso, ho presupposto che il cookie sarebbe stato rispedito a qualsiasi pagina in quel dominio, ma sembra essere solo rinviato a quella pagina specifica. Sto assumendo che sia corretto in quanto coerente.

Il problema principale per me è la gestione dei cookie con un percorso specificato. Sicuramente, se viene specificato un percorso, il cookie deve essere inviato a qualsiasi pagina contenuta all'interno di quel percorso. Quindi, nel codice sopra, 'CookieWithPath' dovrebbe essere valido per qualsiasi pagina all'interno di/some/path /, che include page1.html, page2.html e page3.html. Certamente se commentate le due istanze di 'NoPathCookie', quindi 'CookieWithPath' viene inviato a tutte e tre le pagine come mi aspetterei. Tuttavia, con l'inclusione di "NoPathCookie" come sopra, quindi "CookieWithPath" viene inviato solo a page2.html e page3.html, ma non page1.html.

Perché è questo ed è corretto?

Ricerca di questo problema Ho trovato una discussione su un problema con la gestione del dominio in CookieContainer, ma non sono stato in grado di trovare alcuna discussione sulla gestione dei percorsi.

sto usando Visual Studio 2005/.NET 2,0

risposta

2

Quando un percorso non viene specificato, ho dato per scontato che il cookie sarebbe stato rimandato a qualsiasi pagina di tale dominio, ma sembra solo essere rispediti a quella pagina specifica. Sto assumendo che sia corretto in quanto coerente.

Sì, è corretto. Ogni volta che il dominio o il percorso non viene specificato, viene preso dall'URI corrente.

OK, diamo un'occhiata a CookieContainer. Il metodo in questione è InternalGetCookies(Uri). Ecco la parte interessante:

while (enumerator2.MoveNext()) 
{ 
    DictionaryEntry dictionaryEntry = (DictionaryEntry)enumerator2.get_Current(); 
    string text2 = (string)dictionaryEntry.get_Key(); 
    if (!uri.AbsolutePath.StartsWith(CookieParser.CheckQuoted(text2))) 
    { 
     if (flag2) 
     { 
      break; 
     } 
     else 
     { 
      continue; 
     } 
    } 
    flag2 = true; 
    CookieCollection cookieCollection2 = (CookieCollection)dictionaryEntry.get_Value(); 
    cookieCollection2.TimeStamp(CookieCollection.Stamp.Set); 
    this.MergeUpdateCollections(cookieCollection, cookieCollection2, port, flag, i < 0); 
    if (!(text2 == "/")) 
    { 
     continue; 
    } 
    flag3 = true; 
    continue; 
} 

enumerator2 ecco un (ordinate) elenco di percorsi biscotti. È ordinato in modo tale che percorsi più specifici (come /directory/subdirectory/) precedono quelli meno specifici (come /directory/) e in altro modo - in ordine lessicografico (/directory/page1 precedono lo /directory/page2).

Il codice in realtà è il seguente: itera su questo elenco di percorsi dei cookie fino a quando non trova un primo percorso, ovvero un prefisso per il percorso dell'URI richiesto.Quindi aggiunge un cookie sotto quel percorso all'output e imposta flag2 su true, che significa "OK, ho finalmente trovato il posto nell'elenco che si riferisce effettivamente all'URI richiesto". Dopodiché, il primo percorso incontrato, che NON è un prefisso per il percorso URI richiesto, è considerato la fine dei percorsi correlati, quindi il codice interrompe la ricerca dei cookie facendo break.

Ovviamente, questo è un tipo di ottimizzazione per impedire la scansione dell'intero elenco e funziona apparentemente se nessuno dei percorsi porta a una pagina concreta. Ora, per il vostro caso, l'elenco percorso assomiglia a quello:

/some/path/page1.html 
/some/path/page2.html 
/some/path/ 

È possibile verificare che con un debugger, guardando ((System.Net.PathList)(cookieJar.m_domainTable["www.somedomain.com"])).m_list nella finestra di controllo

Quindi, per 'page1.html' URI, il codice interrompe l'articolo page2.html, non avendo la possibilità di elaborare anche l'articolo /some/path/.

In conclusione: questo è ovviamente un altro bug in CookieContainer. Credo che dovrebbe essere segnalato sulla connessione.

PS: Sono troppi bug per una classe. Spero solo che il ragazzo della MS che ha scritto i test per questa classe sia già stato licenziato.

Problemi correlati