为什么URI编码('#')锚点会导致404,以及如何在JS中处理它?

时间:2012-07-20 22:28:35

标签: javascript hash webkit hashtag

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

  

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

  1. 为什么哈希会成为文件的一部分,因为它是由URI编码的?这不是一个错误吗?

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

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

  4. 谢谢!

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

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

    他们成功处理了%23导致问题的案例。

2 个答案:

答案 0 :(得分:10)

  
      
  1. 为什么哈希会成为文件的一部分,因为它是由URI编码的?这不是一个错误吗?
  2.   

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

如果您指向http://example.com/index.html%23title,则浏览器会从index.html%23title请求文件example.com,这可能在服务器上不存在,为您提供404。区别?

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

  

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

对于2和3,您的示例代码中没有足够的上下文来说明您要执行的操作。你怎么称呼你的代码?你想用Prettyphoto做什么不工作?您是否尝试从用户点击或其他javascript活动重定向到特定照片或图库?您是否在某人访问特定网页时尝试打开图库?

我用twitter / oauth查看了链接的问题,但是我没看到它与你提供的代码有什么联系。我也开始在prettyphoto上戳,但我不知道你的代码是如何与之相关的。

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

我很乐意通过解决方案或为您解决问题来更新我的答案。

答案 1 :(得分: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,或者你提供的任何东西,你可以编写一个RegEx,它匹配任何url,直到第一个“%23”,假设没有“?”预先。

减少灵魂的实施可能需要弄清楚是否有办法逃脱插件友好的“#”。

谷歌,例如,使用“哈希爆炸”策略(“#!”),它要求以这种方式提交URL,以了解是否编码。

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

这真的归结为你想要完成的事情 - 我可以指出为什么这是一个问题,但如何最好地使它成为一个非问题取决于你想要做什么,你如何我正在尝试这样做,以及你在工作环境中允许的内容。