11

我遇到了 HttpWebRequest 的一个问题,如果 URI 长度超过 2048 个字符,则请求失败并返回 404 错误,即使服务器完全有能力为具有这么长的 URI 的请求提供服务。我知道这一点,因为如果通过 HttpWebRequest 提交会导致错误的相同 URI 在直接粘贴到浏览器地址栏中时可以正常工作。

我当前的解决方法是允许用户设置一个兼容性标志,以表示在 URI 太长的情况下将参数作为 POST 请求发送是安全的,但这并不理想,因为我使用的协议是 RESTful并且 GET 应该用于查询。此外,无法保证该协议的其他实现者将接受 POSTed 查询

.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 .
  }

}

4

4 回答 4

6

我使用的协议是 RESTful 并且 GET 应该用于查询。

没有理由不能将 POST 也用于查询;对于非常长的请求数据,您必须这样做,因为非常长的 URI 不受全球支持,而且从来没有。这是 HTTP 不符合 REST 理想的一个领域。

POST 通常不用于纯 HTML 级别的原因是停止浏览器提示重新加载,并促进例如。书签。但是对于 HttpWebRequest 你没有这些顾虑,所以继续发布它。Web 应用程序应该使用参数或 URI 路径部分来区分写入请求和查询,而不仅仅是请求方法。(当然,来自 GET 方法的写入请求仍应被拒绝。)

于 2009-10-19T10:20:24.437 回答
3

我不认为 HttpWebRequest 实际上与您正在谈论的大小的 GET URL 不兼容。我这么说是基于两件事:

  1. 在我自己的工作中,我使用 HttpWebRequest 发送长度超过 2048 个字符的 HTTP GET 请求而不会遇到麻烦。我不确定我最长的是什么,但我们说的是 10,000 多个字符。(这主要是在 Web 应用程序和在 Tomcat 下运行的 Solr 实例之间。)

  2. .NET 确实对 GET URL 长度有一些限制,但我知道的长度远高于 2048 个字符。例如,我今天从我的分析器中了解到 WebRequest.Create(string url) 调用Uri 类构造函数,如果“uriString 的长度超过 65534 个字符”,则会抛出 UriFormatException。

如果不是 HttpWebRequest 本身,我不确定您的问题可能出在哪里。您知道您的 Web 服务在什么情况下会返回 HTTP 404(即“未找到”)吗?(我假设 404 来自您的 Web 服务,而不是在 .NET 的深处伪造。)我还想仔细检查您粘贴到浏览器中的地址实际上与正在使用的地址相同由 .NET 发送;正如 feroze 建议的那样,您应该为此使用网络嗅探工具。如果这两个地址相同,那么接下来可能会比较 .NET 案例和浏览器案例之间的 HTTP 标头如何变化。(顺便说一句,我个人发现Fiddler比 wireshark 在这些方面的 HTTP 调试任务更方便。)

另请参阅这个有点相关的问题:HttpWebRequest 与将 URL 粘贴到地址栏中有何不同(功能性)?

于 2010-02-27T02:44:30.257 回答
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!");

在我的机器上(在运行 .Net 4.5 的 LINQPad 中),此代码段输出:

Error occurred at url length: 65520
System.UriFormatException: Invalid URI: The Uri string is too long.
于 2015-09-18T15:38:54.853 回答
0

根据 RFC3986,您的查询字符串是错误的。URI 中不允许使用“{”和“}”字符。

于 2010-10-17T21:17:42.017 回答