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

Why URI-encoded ('#') anchors cause 404, and how to deal with it in JS?

本文关键字:JS 处理 编码 URI 为什么      更新时间:2023-12-27

prettyPhoto使用标签,但如果它们被编码(到%23),大多数浏览器都会出现404错误。这在前面已经讨论过:

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

  1. 为什么散列仅仅因为是URI编码的就成为文件的一部分?这不是一只虫子吗?

  2. 我这么问是因为prettyPhoto使用了标签,也遇到了同样的问题。我想加一个"?"在散列成为最优雅的解决方案之前,我只是有点不知所措如何在现有代码中进行:

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

谢谢!

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

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

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

  1. 为什么散列仅仅因为是URI编码的就成为文件的一部分?这不是一只虫子吗

如果您将浏览器指向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年。参见RFC 2396。报价:

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

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

我在twitter/oauth上检查了链接的问题,但我不知道这与您提供的代码有什么关系。我也开始研究prettypoto,但我也不明白你的代码与之有什么关系。

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

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

回答#1)

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

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

浏览器不会向服务器发送"#……",因为标签对浏览器有特殊的含义。

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

为什么不呢?如果你的搜索查询合法地需要一个散列字符(你向脸书墙发出POST请求,并且你提交了一个电话号码),那么你就完蛋了。或者你正在411.com或其他网站上进行基于GET的搜索,但他们并没有真正仔细考虑他们的应用程序。

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

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

因此,如果你正在寻找:

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

的确,你肯定会404。

我敢肯定,你可以做一些事情。第一个是在Apache中,或者无论你从哪里提供服务,你都可以编写一个RegEx,它匹配第一个"%23"之前的任何url,假设事先没有"?"。

不那么令人心碎的实现可能需要弄清楚是否有办法摆脱插件友好的"#"。

例如,谷歌使用"hash-bang"策略("#!"),要求以这种方式提交URL,以知道是否进行编码。

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

实际上,这一切都取决于你试图实现的目标——我可以指出为什么这是一个问题,但如何最好地使它成为一个非问题取决于你正在努力做什么,如何努力做到这一点,以及在你工作的环境中允许做什么。