2009-10-19 2 views
11

Ho riscontrato un problema con HttpWebRequest che se l'URI supera i 2048 caratteri la richiesta non riesce e restituisce un errore 404 anche se il server è perfettamente in grado di servire una richiesta con un URI così lungo. Lo so poiché lo stesso URI che causa un errore se inviato tramite HttpWebRequest funziona bene quando viene incollato direttamente nella barra degli indirizzi del browser.HttpWebRequest soluzione URI lungo?

La mia soluzione attuale consiste nel consentire agli utenti di impostare un flag di compatibilità per dire che è sicuro inviare i parametri come richiesta POST nel caso in cui l'URI sarebbe troppo lungo ma questo non è l'ideale dal protocollo I ' m using è RESTful e GET dovrebbe essere usato per le query. Inoltre non vi è garanzia che altri implementatori del protocollo accetteranno le interrogazioni POSTed

Esiste un'altra classe in .Net che abbia funzionalità equivalenti a HttpWebRequest che non soffra del limite di lunghezza URI che potrei usare?
Sono a conoscenza di WebClient ma non desidero veramente utilizzarlo poiché è necessario essere in grado di controllare completamente le intestazioni HTTP che WebClient limita la capacità di eseguire.

Modifica

Perché Shoban chiesto per esso:

http://localhost/BBCDemo/sparql/?query=PREFIX+rdf%3A+%3Chttp%3A%2F%2Fwww.w3.org%2F1999%2F02%2F22-rdf-syntax-ns%23%3E%0D%0APREFIX+rdfs%3A+%3Chttp%3A%2F%2Fwww.w3.org%2F2000%2F01%2Frdf-schema%23%3E%0D%0APREFIX+xsd%3A+%3Chttp%3A%2F%2Fwww.w3.org%2F2001%2FXMLSchema%23%3E%0D%0APREFIX+skos%3A+%3Chttp%3A%2F%2Fwww.w3.org%2F2004%2F02%2Fskos%2Fcore%23%3E%0D%0APREFIX+dc%3A+%3Chttp%3A%2F%2Fpurl.org%2Fdc%2Felements%2F1.1%2F%3E%0D%0APREFIX+po%3A+%3Chttp%3A%2F%2Fpurl.org%2Fontology%2Fpo%2F%3E%0D%0APREFIX+timeline%3A+%3Chttp%3A%2F%2Fpurl.org%2FNET%2Fc4dm%2Ftimeline.owl%23%3E%0D%0ASELECT+*+WHERE+{%0D%0A++++%3Chttp%3A%2F%2Fwww.bbc.co.uk%2Fprogrammes%2Fb00n4d6y%23programme%3E+dc%3Atitle+%3Ftitle+.%0D%0A++++%3Chttp%3A%2F%2Fwww.bbc.co.uk%2Fprogrammes%2Fb00n4d6y%23programme%3E+po%3Ashort_synopsis+%3Fsynopsis-short+.%0D%0A++++%3Chttp%3A%2F%2Fwww.bbc.co.uk%2Fprogrammes%2Fb00n4d6y%23programme%3E+po%3Amedium_synopsis+%3Fsynopsis-med+.%0D%0A++++%3Chttp%3A%2F%2Fwww.bbc.co.uk%2Fprogrammes%2Fb00n4d6y%23programme%3E+po%3Along_synopsis+%3Fsynopsis-long+.%0D%0A++++%3Chttp%3A%2F%2Fwww.bbc.co.uk%2Fprogrammes%2Fb00n4d6y%23programme%3E+po%3Amasterbrand+%3Fchannel+.%0D%0A++++%3Chttp%3A%2F%2Fwww.bbc.co.uk%2Fprogrammes%2Fb00n4d6y%23programme%3E+po%3Agenre+%3Fgenre+.%0D%0A++++%3Fchannel+dc%3Atitle+%3Fchanneltitle+.%0D%0A++++OPTIONAL+{%0D%0A++++++++%3Chttp%3A%2F%2Fwww.bbc.co.uk%2Fprogrammes%2Fb00n4d6y%23programme%3E+po%3Abrand+%3Fbrand+.%0D%0A++++++++%3Fbrand+dc%3Atitle+%3Fbrandtitle+.%0D%0A++++}%0D%0A++++OPTIONAL+{%0D%0A++++++++%3Chttp%3A%2F%2Fwww.bbc.co.uk%2Fprogrammes%2Fb00n4d6y%23programme%3E+po%3Aversion+%3Fver+.%0D%0A++++++++%3Fver+po%3Atime+%3Finterval+.%0D%0A++++++++%3Finterval+timeline%3Astart+%3Fstart+.%0D%0A++++++++%3Finterval+timeline%3Aend+%3Fend+.%0D%0A++++}%0D%0A}&default-graph-uri=&timeout=30000 

Qual è il seguente codificato sul querystring:

PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> 
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> 
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#> 
PREFIX skos: <http://www.w3.org/2004/02/skos/core#> 
PREFIX dc: <http://purl.org/dc/elements/1.1/> 
PREFIX po: <http://purl.org/ontology/po/> 
PREFIX timeline: <http://purl.org/NET/c4dm/timeline.owl#> 
SELECT * WHERE { 
    <http://www.bbc.co.uk/programmes/b00n4d6y#programme> dc:title ?title . 
    <http://www.bbc.co.uk/programmes/b00n4d6y#programme> po:short_synopsis ?synopsis-short . 
    <http://www.bbc.co.uk/programmes/b00n4d6y#programme> po:medium_synopsis ?synopsis-med . 
    <http://www.bbc.co.uk/programmes/b00n4d6y#programme> po:long_synopsis ?synopsis-long . 
    <http://www.bbc.co.uk/programmes/b00n4d6y#programme> po:masterbrand ?channel . 
    <http://www.bbc.co.uk/programmes/b00n4d6y#programme> po:genre ?genre . 
    ?channel dc:title ?channeltitle . 
    OPTIONAL { 
    <http://www.bbc.co.uk/programmes/b00n4d6y#programme> po:brand ?brand . 
    ?brand dc:title ?brandtitle . 
    } 
    OPTIONAL { 
    <http://www.bbc.co.uk/programmes/b00n4d6y#programme> po:version ?ver . 
    ?ver po:time ?interval . 
    ?interval timeline:start ?start . 
    ?interval timeline:end ?end . 
    } 

}

+0

Voglio vedere l'url che è più di 2048 caratteri ;-) – Shoban

+0

@Shoban ha aggiunto un esempio per te – RobV

risposta

6

la il protocollo che sto usando è RESTful e GET dovrebbe essere usato per le query.

Non c'è motivo per cui POST non possa essere utilizzato anche per le query; per i dati di richiesta veramente lunghi, poiché gli URI molto lunghi non sono supportati globalmente e non lo sono mai stati. Questa è un'area in cui HTTP non è all'altezza dell'ideale REST.

Il motivo per cui il POST in genere non viene utilizzato su un livello HTML semplice è quello di interrompere la richiesta del browser di ricaricare e promuovere ad es. bookmarking. Ma per HttpWebRequest non hai nessuno di questi problemi, quindi vai avanti e postalo. Le applicazioni Web devono utilizzare un parametro o una parte del percorso URI per distinguere le richieste di scrittura dalle query, non solo il metodo di richiesta. (Ovviamente una richiesta di scrittura da un metodo GET dovrebbe ancora essere negata.)

+0

Sì, ho esaminato la documentazione per il protocollo e dice che gli implementatori POSSONO supportare le query POSTed in modo che possano supportare ma non ci sono garanzie – RobV

+0

+1 POST è la strada da percorrere per gli url lunghi. – db42

+0

Dalla metodologia e dal punto di vista filosofico non ha senso, ma FUNZIONA! Grazie. –

3

Non penso che HttpWebRequest sia effettivamente incompatibile con gli URL GET della dimensione di cui si sta parlando. Dico questo sulla base di due cose:

  1. Nel mio lavoro uso HttpWebRequest per inviare richieste HTTP GET più lungo di 2048 caratteri senza problemi. Non sono sicuro di cosa siano i miei più lunghi, ma parliamo di oltre 10.000 caratteri. (Ciò si verifica principalmente tra un'applicazione Web e un'istanza di Solr in esecuzione in Tomcat.)

  2. .NET ha alcuni limiti sulle lunghezze degli URL GET, ma quelli a cui sono a conoscenza sono molto più grandi di 2048 caratteri. Ad esempio, ho appreso oggi dal mio profiler che WebRequest.Create (string url) chiama lo Uri class constructor e che è documentato per lanciare UriFormatException se "la lunghezza di uriString supera 65534 caratteri."

non sono sicuro dove il vostro problema potrebbe essere, se non HttpWebRequest per sé è. Sapete in quali condizioni il servizio web restituirà HTTP 404 (vale a dire 'non trovato')? (Suppongo che il 404 proviene dal tuo servizio web, piuttosto che essere falsificato nelle profondità di .NET.) Vorrei anche ricontrollare che l'indirizzo che stai incollando nel browser è in realtà lo stesso che viene inviato da .NET. ; come suggerito da feroze, è necessario utilizzare uno strumento di sniffing della rete per questo.Se i due indirizzi sono uguali, allora forse prossimo confronto come le intestazioni HTTP variano tra il caso .NET e il caso del browser. (Per inciso, personalmente trovo Fiddler a un po 'più pratico di wireshark per le attività di debug HTTP lungo queste linee.)

Vedere anche questa domanda in qualche modo correlata: How does HttpWebRequest differ (functional) from pasteing a URL into an address bar?

0

La stringa di query è errata in base a RFC3986. I caratteri '{' e '}' non sono ammessi in un URI.

+0

Huh, l'URI dato è generato dal metodo 'Uri.EscapeDataString()' di .Net, non è sicuro quale URI RFC sia conforme a – RobV

2

Ecco un frammento che costruisce HttpWebRequest casi con valori url sempre più grandi fino a quando un'eccezione viene buttato:

using System.Net; 

... 

StringBuilder url = new StringBuilder("http://example.com?p="); 
try 
{ 
    for (int i = 1; i < Int32.MaxValue; i++) 
    { 
     url.Append("0"); 
     HttpWebRequest request = HttpWebRequest.CreateHttp(url.ToString()); 
    } 
} 
catch (Exception ex) 
{ 
    Console.Out.WriteLine("Error occurred at url length: " + url.Length); 
    Console.Out.WriteLine(ex.GetType().ToString() + ": " + ex.Message); 
    return; 
} 
Console.Out.WriteLine("Completed without error!"); 

Sulla mia macchina (in LINQPad corsa .Net 4.5), queste uscite frammento:

Error occurred at url length: 65520 
System.UriFormatException: Invalid URI: The Uri string is too long.