如何使用htaccess从url中删除%u

时间:2012-10-23 20:18:32

标签: apache .htaccess mod-rewrite url-rewriting

我从浏览器收到错误请求(下​​面的错误消息)

错误请求

您的浏览器发送了此服务器无法理解的请求。 客户端发送了格式错误的主机标头

最后我意识到它上面有一个特殊字符“%u”。如何使用.htaccess删除特殊字符?

例如,我想从

更改网址

http://www.example.com/property-listings/A/B/C/D/E/F-%uG/H/I-101.html

http://www.example.com/property-listings/A/B/C/D/E/F-G/H/I-101.html

任何想法。

的问候,

2 个答案:

答案 0 :(得分:1)

简短的回答是你不能 - 至少不能使用.htaccess。

这是因为在获取.htaccess文件之前,Apache会解析(或者更确切地说,不解析)%u。不幸的是,请求本身在语法上是错误的,Apache无法解析它,因此 400 Bad Request

%uHHHH是一种非标准(IIS)编码Unicode字符的方式。 %uHHHH表示Unicode字符U + HHHH,其中HHHH是十六进制表示。例如,%u20AC代表字符

Apache无法识别%uHHHH语法(或任何其他迷路%符号),您无能为力。

但是,有一种解决方法 - 您可以使用ErrorDocument指令使用PHP脚本(或您正在使用的任何脚本语言)来处理 400 Bad Request 错误。< / p>

E.g。

httpd.conf 中添加以下行:

ErrorDocument 400 /400.php

这必须添加到主Apache配置(http.conf)中。出于安全原因,您无法将此添加到.htaccess中,即使您可以为其他HTTP响应代码添加指令(例如404和500)。 Apache认为400响应代码的ErrorDocument指令被认为是安全风险:

  

虽然可以覆盖大多数错误消息,但在某些情况下,无论ErrorDocument的设置如何,都会使用内部消息。特别是,如果检测到格式错误的请求,将立即停止正常的请求处理并返回内部错误消息。这是防止由不良请求引起的安全问题所必需的。

(来自Apache documentation。)

然后在您的网络根目录中创建 400.php 文件:

<?php

$uri = isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : null;
if (preg_match('!%u[0-9a-f]{4}!i', $uri)) {
    // Convert all %uHHHH encodings to UTF-8 characters
    $redirectUri = preg_replace_callback('!%u(([0-9a-f]){4})!i', function($matches) { return json_decode('"\u' . $matches[1] . '"'); }, $uri);
    header('HTTP/1.1 301 Moved Permanently');
    header("Location: $redirectUri");
    die;
}

// Apache returned 400 Bad Request for some other reason, so just display the
// default error page

// Return a 404 Not Found response if anyone accesses the URL /400.php directly
$errorCode = preg_match('!^/400\.php!', $uri) ? 404 : 400;

?>
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title><?php echo $errorCode == 404 ? '404 Not Found' : '400 Bad Request'; ?></title>
</head><body>
<?php if ($errorCode == 404) { ?>
<h1>Not Found</h1>
<p>The requested URL <?php echo htmlspecialchars(preg_replace('!([^?#]+).*!', '$1', $uri)); ?> was not found on this server.</p>
<?php } else { ?>
<h1>Bad Request</h1>
<p>Your browser sent a request that this server could not understand.</p>
<?php } ?>
</body></html>

这会将包含%uHHHH编码字符的任何请求重定向到相同的URI,但使用UTF-8。

我知道这并没有完全回答你的问题(因为你自己的URI包含字符串%u,没有任何十六进制代码),但是你可以很容易地为你自己的目的调整脚本,并且脚本就像我一样已经写过它对一般人来说会更有用。

答案 1 :(得分:0)

尝试:

RewriteRule ^(.*)%u(.*)$ /$1$2 [L,R=301]