2009-10-19 105 views
11

我遇到過HttpWebRequest的問題,即如果URI長度超過2048個字符,請求失敗並返回404錯誤,即使服務器完全能夠使用長的URI來處理請求。我知道這一點,因爲如果通過HttpWebRequest提交時導致錯誤的相同URI直接粘貼到瀏覽器地址欄時可以正常工作。HttpWebRequest長URI解決方法?

我目前的解決方法是允許用戶設置一個兼容性標誌來表示將參數作爲POST請求發送是安全的,而不是在URI過長的情況下,但這不是理想的,因爲協議I' m使用RESTful,GET應該用於查詢。另外,沒有保證協議的其他實現者將接受POST的查詢

.Net中是否有另一個具有與HttpWebRequest等效的功能,它不受URI長度限制的限制?
我知道WebClient,但我不想使用它,因爲我需要能夠完全控制WebClient限制其能力的HTTP標頭。

編輯

因爲Shoban問它:

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 

該數值爲下列編碼到查詢字符串:

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

我想看到超過2048個字符的url ;-) – Shoban 2009-10-19 10:01:59

+0

@Shoban爲您添加了一個示例 – RobV 2009-10-19 10:43:33

回答

6

的我使用的協議是RESTful,GET應該用於查詢。

沒有理由POST不能也可用於查詢;對於需要長時間的請求數據,由於非常長的URI不是全局支持的,並且從來沒有。這是HTTP不符合REST理想的一個領域。

POST通常不會在純HTML級別上使用的原因是停止瀏覽器提示重新加載,並促進例如。書籤。但是對於HttpWebRequest,你沒有這些擔憂,所以繼續併發布它。 Web應用程序應該使用參數或URI路徑部分來區分來自查詢的寫請求,而不僅僅是請求方法。 (當然,從GET方法寫入請求還是應該被拒絕。)

+0

是的,我查看了該協議的文檔,它說實現者可以支持POST的查詢,所以他們應該支持th但是沒有保障人員 – RobV 2009-10-19 10:42:45

+0

+ 1 POST是長途旅行的方式。 – db42 2013-09-11 18:09:10

+0

從方法論和哲學的角度來看,這是無稽之談,但它的工作原理!謝謝。 – 2015-08-11 09:30:22

3

我不認爲HttpWebRequest的是與你談論大小的GET網址居然不兼容。我這樣說基於兩件事:

  1. 在我自己的工作中,我使用HttpWebRequest來發送長度超過2048個字符的HTTP GET請求沒有麻煩。我不確定我最長的是什麼,但我們正在談論10,000多個角色。 (這主要是在一個web應用程序和在Tomcat下運行的Solr實例之間)。

  2. .NET對GET URL長度有一些限制,但我知道的那些遠遠高於2048個字符。例如,我今天從我的分析器瞭解到WebRequest.Create(string url)調用Uri class constructor,並且如果「uriString的長度超過65534個字符,則記錄該文件以引發UriFormatException。「

我不知道您的問題可能是,如果它不是HttpWebRequest的本身。你知道在什麼情況下您的Web服務將返回HTTP 404(即‘未找到’)?(我假設404來自你的web服務,而不是在.NET的深處僞裝)我也想仔細檢查你粘貼到瀏覽器的地址是否與.NET發送的地址是一樣的;正如feroze所建議的,你應該使用網絡嗅探工具,如果這兩個地址是相同的,那麼下一步可以比較一下.NET的情況和瀏覽器情況下HTTP標頭的不同(順便說一下,我個人發現Fiddler a比沿着這些線的HTTP調試任務的wireshark更方便。)

另請參閱這個有點相關的問題:How does HttpWebRequest differ (functional) from pasteing a URL into an address bar?

0

根據RFC3986,您的查詢字符串是錯誤的。在URI中不允許使用'{'和'}'字符。

+0

呵呵,給出的URI是由.Net的'Uri.EscapeDataString()'方法生成的,不知道哪個URI RFC符合 – RobV 2010-10-18 09:32:03

2

這裏,直到一個異常被拋出它構造HttpWebRequest實例有越來越大的URL值的片段:

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!"); 

在我的機器(在LINQPad運行.NET 4.5),這個片段輸出:

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