简体   繁体   English

如何 mod_rewrite 包含路径和参数的查询字符串?

[英]How to mod_rewrite query string which includes path and parameters?

My website uses a rather complicated query string parameter: Its value is a path including parameters.我的网站使用了一个相当复杂的查询字符串参数:它的值是一个包含参数的路径。

For SEO (Search Engine Optimization) etc. I'm now attempting to mod_rewrite shortened versions...对于 SEO(搜索引擎优化)等。我现在正在尝试 mod_rewrite 缩短版本...

  • example.com/path/c1/d1/e1.html?x=x1&y=y1
  • example.com/path/c2/d2/e2.html?x=x2&y=y2
  • example.com/path/c2/d3/e4.html?x=x5&y=y6

...to the currently required... ...到当前所需...

  • example.com/path/?param=a/b/c1/d1/e1?x=x1&y=y1
  • example.com/path/?param=a/b/c2/d2/e2?x=x2&y=y2
  • example.com/path/?param=a/b/c2/d3/e4?x=x5&y=y6

So the goal is to...所以目标是...

  1. get rid of the fixed part ( ?param=a/b/ ) to shorten the address and don't have two ?去掉固定部分( ?param=a/b/ )以缩短地址并且没有两个? in the visible address在可见地址
  2. preserve the query string value's necessary variable path components (like c1/d1/e1 or c2/d2/e2 or c2/d3/e4 )保留查询字符串值的必要变量路径组件(如c1/d1/e1c2/d2/e2c2/d3/e4
  3. add .html to the final part before the query string value's ?.html添加到查询字符串值之前的最后一部分? to make the folder structure appear 1 level less deep使文件夹结构看起来少 1 级
  4. preserve the query string value's necessary variable parameters (like ?x=x1&y=y1 or ?x=x2&y=y2 or ?x=x5&y=y6 )保留查询字符串值的必要变量参数(如?x=x1&y=y1?x=x2&y=y2?x=x5&y=y6

After hours of research and attempting lots of things that did not work, I signed up here to request your advice on how to solve this mess.经过数小时的研究并尝试了许多不起作用的事情,我在这里注册以征求您关于如何解决这个烂摊子的建议。 Would you please be so kind to assist?请你帮忙好吗?

Edit / additional infos:编辑/附加信息:

  • After the fixed string /path/?param=a/b/ it is always 3 variable path segments like c1/d1/e1 .在固定字符串/path/?param=a/b/它总是像c1/d1/e1这样的 3 个可变路径段。
  • These variable segments can contain alphanumerical characters az AZ 0-9 , dash symbol - and bracket symbols ( and ) .这些可变区段可以包含字母数字字符az AZ 0-9 ,短划线符号-和托架符号()
  • Same applies to the parameter values (x1, y1).这同样适用于参数值 (x1, y1)。 Additionally, y1 can contain percent symbol % due to URL-encoding.此外,由于 URL 编码,y1 可以包含百分比符号%
  • Using two question marks (one to start the query string and the other as part of the parameter value) looks invalid but works.使用两个问号(一个作为查询字符串的开始,另一个作为参数值的一部分)看起来无效但有效。
  • The actual file that handles the request is /path/index.php .处理请求的实际文件是/path/index.php

Try the following at the top of your .htaccess file, using mod_rewrite:使用 mod_rewrite 在.htaccess文件的顶部尝试以下操作:

RewriteEngine on

# REDIRECT: /path/?param=a/b/c1/d1/e1?x=1&y=y1
RewriteCond %{THE_REQUEST} ^[A-Z]{3,7}\s/path/(?:index\.php)?\?param=a/b/([^/]+/[^/]+/[^/]+)\?(x=[^&]+&y=[^&]+)\s
RewriteRule ^(path)/(?:index\.php)?$ /$1/%1.html?%2 [R=302,L]

# REWRITE: /path/c1/d1/e1.html?x=x1&y=y1
RewriteCond %{QUERY_STRING} ^(x=[^&]+&y=[^&]+)$
RewriteRule ^(path)/([^/]+/[^/]+/[^/]+)\.html$ $1/index.php?param=a/b/$2?%1 [L]

The first rule redirects any direct requests for the "old" URL of the form /path/?param=a/b/c1/d1/e1?x=1&y=y1 ( index.php is optional) to the "new" canonical URL of the form /path/c1/d1/e1.html?x=x1&y=y1 .第一规则重定向任何直接请求的形式的“旧” URL /path/?param=a/b/c1/d1/e1?x=1&y=y1index.php是可选的)到“新”规范形式为/path/c1/d1/e1.html?x=x1&y=y1 URL。 This is for the benefit of search engines and any third party inbound links that cannot be updated.这是为了搜索引擎和任何无法更新的第三方入站链接的利益。 You must, however, have already changed all your internal links to the "new" canonical URL.但是,您必须已经将所有内部链接更改为“新”规范 URL。

By matching against THE_REQUEST (as opposed to the QUERY_STRING ) we avoid a redirect loop by preventing the rewritten URL from being redirected.通过匹配THE_REQUEST (而不是QUERY_STRING ),我们通过防止重写的 URL 被重定向来避免重定向循环。 THE_REQUEST contains the first line of the request headers and is not changed by other rewrites. THE_REQUEST包含请求头的第一行,不会被其他重写更改。 For example, THE_REQUEST would contain a string of the form:例如, THE_REQUEST将包含以下形式的字符串:

GET /path/?param=a/b/c1/d1/e1?x=1&y=y1 HTTP/1.1

This is currently a 302 (temporary) redirect.这是当前的 302(临时)重定向。 Only change this to a 301 (permanent) redirect once you have tested that this works OK, in order to avoid potential caching issues.仅在您测试此操作正常后才将其更改为 301(永久)重定向,以避免潜在的缓存问题。

The second rule internally rewrites requests for the "new" canonical URL, eg.第二条规则在内部重写对“新”规范 URL 的请求,例如。 /path/c1/d1/e1.html?x=x1&y=y1 , back to the original/underlying URL-path, eg. /path/c1/d1/e1.html?x=x1&y=y1 ,回到原始/底层 URL-path,例如。 /path/index.php?param=a/b/c1/d1/e1?x=1&y=y1 . /path/index.php?param=a/b/c1/d1/e1?x=1&y=y1 The & before the last URL parameter is intentional un-escaped (ie. URL decoded) as discussed in comments.正如评论中所讨论的,最后一个 URL 参数之前的&是有意未转义的(即 URL 解码)。

The $1 and $2 backreferences refer back to the captured groups in the RewriteRule pattern . $1$2反向引用返回到RewriteRule模式中捕获的组。 Whereas the %1 and %2 backreferencs refer to the captured groups in the preceding CondPattern .%1%2反向引用指的是前面CondPattern 中捕获的组。

These variable segments can contain alphanumerical characters az AZ 0-9 , dash symbol - and bracket symbols ( and ) .这些可变区段可以包含字母数字字符az AZ 0-9 ,短划线符号-和托架符号()

I've used a more general (and shorter) subpattern in the regex above which will match more characters, but is arguably easier to read.我在上面的正则表达式中使用了更通用(和更短)的子模式,它将匹配更多字符,但可以说更容易阅读。 ie. IE。 [^/]+ - matches anything except a slash and [^&]+ - matches anything except a & . [^/]+ - 匹配除斜杠以外的任何内容,而[^&]+ - 匹配除&以外的任何内容。

If you specifically wanted to match only the allowed characters then you could change the above subpatterns to [a-zA-Z0-9()%-]+ or [\\w()%-]+ which also matches underscores ( _ ).如果您特别想只匹配允许的字符,那么您可以将上述子模式更改为[a-zA-Z0-9()%-]+[\\w()%-]+ ,这也匹配下划线 ( _ )。


UPDATE: x and y are just examples for parameter names, but in reality there can be lots of different parameter names.更新: x 和 y 只是参数名称的示例,但实际上可以有很多不同的参数名称。
the parameters have more than a single character.参数有多个字符。 They consist of letters az, AZ and in the future maybe digits 0-9.它们由字母 az、AZ 组成,将来可能是数字 0-9。 There can be more than the two parameters x and y.可以有多个参数 x 和 y。

Maybe just match any query string (providing there is a query string).也许只匹配任何查询字符串(前提是有一个查询字符串)。

Try the following instead:请尝试以下操作:

# REDIRECT: /path/?param=a/b/c1/d1/e1?x=1&y=y1
RewriteCond %{THE_REQUEST} ^[A-Z]{3,7}\s/path/(?:index\.php)?\?param=a/b/([^/]+/[^/]+/[^/]+)\?([^\s]+)
RewriteRule ^(path)/(?:index\.php)?$ /$1/%1.html?%2 [R=302,L]

# REWRITE: /path/c1/d1/e1.html?x=x1&y=y1
RewriteCond %{QUERY_STRING} ^(.+)$
RewriteRule ^(path)/([^/]+/[^/]+/[^/]+)\.html$ $1/index.php?param=a/b/$2?%1 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM