2009-10-19 29 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.