【问题标题】:Why URI-encoded ('#') anchors cause 404, and how to deal with it in JS?为什么 URI 编码 ('#') 锚点会导致 404,在 JS 中如何处理?
【发布时间】:2012-07-20 05:25:02
【问题描述】:

prettyPhoto 使用主题标签,但如果它们被编码(到 %23),大多数浏览器都会出现 404 错误。这个has been discussed before

您会收到 404 错误,因为 #callback 部分不是 URL 的一部分。 是浏览器使用的书签,从不发送 对服务器的请求。如果您对哈希进行编码,它将成为 而是文件名。

  1. 为什么哈希会因为它是 URI 编码而成为文件的一部分?不是bug吗?

  2. 我问是因为prettyPhoto 使用主题标签并遇到同样的问题。我想添加一个'?在哈希是最优雅的解决方案之前,我只是有点茫然如何在现有代码中做到这一点:

    函数getHashtag(){
    网址=位置.href;
    hashtag=url.indexOf('#gallery')!==-1)?decodeURI(url.substring(url.indexOf('#gallery')+1,url.length)):false;
    返回标签;
    }
    函数 setHashtag(){
    if(typeof theRel=='undefined')return; location.hash=theRel+'/'+rel_index+'/';
    }
    函数 clearHashtag(){
    if(location.href.indexOf('#gallery')!==-1)location.hash="";
    }
  3. 还有其他建议吗?我会考虑调整我的 404 页面,但这似乎更像是处理问题而不是阻止它。

谢谢!

编辑:显然,prettyphoto 处理这些哈希的方式没有任何问题,我最终将这些规则添加到我的 apache 服务器:

RewriteRule ^(.*).shtml(%23|#)$ /$1.shtml [R=301,NE,L]
RewriteRule ^(.*).shtml([^g]+)gallery(.+)$ /$1.shtml#gallery$3 [R=301,NE,L]

他们成功处理了 %23 引起问题的案例。

【问题讨论】:

  • 合并 ?在上面的代码中,您似乎可以修改已定义为读取 url=location.href+'?'的 'url' var?
  • 另请注意,SO 问题标签“哈希”明确指的是哈希算法。 URL/HTML 功能最好归类为“锚”。

标签: javascript hash webkit hashtag


【解决方案1】:
  1. 为什么哈希会因为它是 URI 编码而成为文件的一部分?不是bug吗?

如果您将浏览器指向http://example.com/index.html#title,浏览器会将此解释为从服务器example.com 请求文件index.html。请求完成后,浏览器会在文档中查找名称为“title”的锚元素(即<a name="title">My title</a>)。

如果您改为指向http://example.com/index.html%23title,浏览器会从example.com 请求文件index.html%23title,该文件可能在服务器上不存在,给您一个404。看到区别了吗?

这不是错误。它是 1998 年互联网标准last updated 的一部分。请参阅RFC 2396。引用:

字符“#”被排除在外,因为它用于将 URI 与 URI 引用中的片段标识符分隔(第 4 节)。

至于 2 和 3,您的示例代码中没有足够的上下文来说明您要做什么。你如何调用你的代码?你想用不工作的漂亮照片做什么?您是否尝试从用户点击或其他 javascript 事件重定向到特定照片或画廊?当有人访问特定页面时,您是否尝试打开图库?

我使用 twitter/oauth 检查了链接的问题,但我看不出它与您提供的代码有何关联。我也开始研究 prettyphoto,但我也看不出你的代码与它有什么关系。

您可能需要一个代码内处理程序或服务器重写规则,而不是更改您的 404 页面,该规则接收带有 %23 的未找到请求并将用户重定向到解码的 url。这可能有一些缺点,但如果您从无法控制的其他来源接收传入请求,那将是相当优雅的。你的服务器环境是什么? (语言、服务器技术、机器所有者等)

我很乐意为您提供解决方案或解决方法来更新我的答案。

【讨论】:

  • 谢谢大家!我的问题最初是由最终用户使用链接的编码版本并获得 404 引起的。我什至不确定它是如何编码的,可能是通过 Gmail 和 Earthlink 电子邮件程序旅行。出于这个原因,我想知道“?”方法不好,因为它也可能会被 URI 编码。
  • 对于 RFC 2396,我想知道为什么浏览器在发送 URL 之前不解码 %23,那么呢?
  • 如您所说,链接可能在用户看到之前就已编码。浏览器不会解码链接,因为它们无法知道编写者的意图。如果我实际上将一篇新闻文章命名为“谁吃了最后一个 cookie?”,并且您通过转到 http://example.com/Who+ate+the+last+cookie%3F 访问它,如果您的浏览器解码它,它会解释解码的 ?作为查询字符串的开头,你会得到一个 404。(实际上,可能不是 ?,但这是一个比我为 # 想到的 url 更现实的例子。)
  • 至于解决人们获得不良链接的问题,听起来您需要在服务器级别实现一些东西。在 apache 中,您可以通过重写规则来完成此操作:httpd.apache.org/docs/current/mod/mod_rewrite.html 我确信其他服务器也有等效方法,但我没有使用它们。发布您的服务器环境,有人可能会帮助您。
  • 我查看了 mod_write,我正在使用 Apache 2 运行我自己的 VPS,所以我可以完全控制。只需要正则表达式模式的帮助 - 我试图将字符串向上传递,直到第一次出现 %23。
【解决方案2】:

回答 #1)

它将成为 URL 的一部分,因为它不再是浏览器/服务器/等知道如何解析的令牌。

我的意思是“?”在 URL 中扮演着重要的角色——服务器知道区分之前和之后的内容。 浏览器不需要关心 URI 中什么是动态的,什么不是动态的——这都很重要(尽管 JavaScript 将位置对象中的值分开)。

浏览器不会向服务器发送“#......”,因为标签对浏览器具有特殊含义。

但是,如果您在 JavaScript 中转义该哈希,浏览器会毫不犹豫地将转义的字符串作为文字值发送到服务器。

为什么不呢?如果您的搜索查询合法地需要一个哈希字符(您向 facebook 墙发出 POST 请求,并且您正在提交一个电话号码),那么您就完蛋了。 或者您正在 411.com 或其他任何地方对某个号码进行基于 GET 的搜索,但他们并没有真正考虑过他们的申请。

问题在于,如果转义值发生在实际路径中,服务器不会理解转义值与 url 分开保存。

它必须接受转义字符,否则在文件名/路径/查询/值中有效的空格 (%20) 和其他日常字符会造成问题。

所以,如果您正在寻找:

//mysite.gov.on.ca/path/to/file.extension%23action%3Dfullscreen

真的,你肯定会 404。

我敢肯定,您可以做一些事情。 第一个将在 Apache 中,或者您所提供的任何服务,您可以编写一个正则表达式,它与第一个“%23”之前的任何 url 匹配,假设没有“?”提前。

减少灵魂撕裂的实现可能涉及弄清楚是否有办法逃避插件友好的“#”。

例如,Google 使用“hash-bang”策略(“#!”)要求以这种方式提交 URL,以了解是否进行编码。

其他选项可能是使用 url.indexOf("#"); 检查“#”字符并在哈希处拆分 URL,然后提交有效部分。

这真的取决于你想要完成的事情——我可以指出为什么这是一个问题,但如何最好地让它成为非问题取决于你想要做什么,你如何'正在尝试这样做,以及在您工作的上下文中允许的内容。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-09-02
    • 1970-01-01
    • 2019-11-21
    • 2012-10-05
    • 1970-01-01
    • 1970-01-01
    • 2021-12-07
    • 1970-01-01
    相关资源
    最近更新 更多