【问题标题】:.htaccess replace " ? | & | = " with "_" in Query String.htaccess 在查询字符串中将“? | & | =”替换为“_”
【发布时间】:2021-06-29 17:41:22
【问题描述】:

我正在尝试为“按需”PHP 图像调整器创建一个缓存系统。

我需要能够检查缓存中是否存在以下文件和查询字符串:

https://www.example.com/images/img.jpg?w=400&h=300&fit=crop

我的 PHP 脚本通过将所有特殊字符 (?,&,=) 替换为下划线来生成缓存文件。 这是缓存对象的样子: /cache/images/img.jpg_w_400_h_300_fit_crop

如何检查/cache 中是否存在requst + 查询作为文件并在存在时提供它?

我目前对没有查询变量的文件有效的是:

# if file exists in /cache/ directory
# serve file from /cache/ directory
RewriteCond  %{DOCUMENT_ROOT}/cache/$1 -f
RewriteRule ^(.*)$ /cache/$1 [L,QSA]

我尝试过这样的事情,但它不起作用,因为我很讨厌 htaccess/regex :)

RewriteCond %{QUERY_STRING} ^(.*)(:?\&|\?|\=)(.*)$
RewriteCond %{DOCUMENT_ROOT}/cache/$1_%1_%2 -f 
RewriteRule ^(.*)$  /cache/$1 [L]

【问题讨论】:

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


    【解决方案1】:

    我的 PHP 脚本通过将所有特殊字符 (?,&,=) 替换为下划线来生成缓存文件。

    您可以在.htaccess 中做同样的事情。然后它会处理“任意数量”1 个 URL 参数(因为您已经声明这是 cmets 中的变量)。

    在您的 .htaccess 文件顶部附近尝试以下脚本。理想情况下,由于搜索/替换循环的递归性质,这需要靠近顶部。

    # 1. Create env var for the image cache filename (IMAGE_CACHE_FN)
    RewriteCond %{ENV:IMAGE_CACHE_FN} ^$
    RewriteCond %{QUERY_STRING} (.+)
    RewriteRule ^images/[\w-]+\.jpg$ - [E=IMAGE_CACHE_FN:cache/$0_%1]
    
    # 2. Recursively replace "=" and "&" in IMAGE_CACHE_FN with "_"
    RewriteCond %{ENV:IMAGE_CACHE_FN} ^(.*)[=&](.*)$
    RewriteRule ^ - [E=IMAGE_CACHE_FN:%1_%2,N=50]
    
    # 3. Test if image cache file exists and rewrite if so
    RewriteCond %{ENV:IMAGE_CACHE_FN} .
    RewriteCond %{DOCUMENT_ROOT}/%{ENV:IMAGE_CACHE_FN} -f
    RewriteRule ^ %{ENV:IMAGE_CACHE_FN} [L]
    

    我选择使用环境变量IMAGE_CACHE_FN 来保存构建时图像缓存文件名的值,而不是就地修改查询字符串或 URL 路径,因为我希望您稍后可能会使用这些你的 PHP 脚本。

    1 在上面的脚本中,我将其限制为最多 50 个递归“循环”(相当于大约 26 个 URL 参数)。这由第二个 RewriteRule 上的 N=50 标志标识。

    对此的一个潜在警告是,如果 URL 参数以不同的顺序提供,那么您自然会为本质上相同的资源获得不同的缓存文件名。尽管这同样适用于您的 PHP 脚本,除非您首先订购参数? (但是除非您重定向请求,否则您可能会遇到重复图像和缓存问题。)我假设您按特定顺序提供 URL 参数。

    您可以在.htaccess 中对 URL 参数进行排序,但它可能会变得很麻烦...

    【讨论】:

    • 出色的解决方案。也学到了新东西。在这一点上,我并不担心参数顺序。另一种方法是使用 PHP 来提供所有文件,但我怀疑 file_get_contents 比 apache 重写到现有文件要慢得多。
    【解决方案2】:

    对于您显示的示例,您能否尝试以下操作。请确保在测试您的 URL 之前清除您的浏览器缓存。

    RewriteEngine ON
    ##Rules for URL like: https://www.example.com/images/img.jpg?w=400&h=300&fit=crop
    RewriteCond %{THE_REQUEST} \s/(?:[^?]*)\?([^=]*)=([^&]*)&([^=]*)=([^&]*)&([^=]*)=(.*)\s
    RewriteCond %{DOCUMENT_ROOT}/cache/$1_%1_%2_%3_%4_%5_%6 -f
    RewriteRule ^(.*)$ /cache/$1?%1_%2_%3_%4_%5_%6 [L]
    

    【讨论】:

    • 应该是RewriteCond %{DOCUMENT_ROOT}/cache/$1_%1_%2_%3_%4_%5_%6 -f 并且它确实有效但是我担心这对于那个设置来说是严格的。如果有更多的变量或更少的变量怎么办?有什么办法让它自动而不是列出 %1_%2...._%6?
    • @Miro,感谢您更正该文档根规则。对于您的问题,如果 vars 或多或少,那么最好的方法将是您将获取查询字符串的任何可能方式,将它们全部捕获在单独的规则中,因为捕获的东西的数量会改变,您可以让我知道不同类型的查询字符串示例,我可以按照那个添加规则,干杯。
    • ? 应该是_RewriteRule substitution 字符串中(以匹配前面的文件系统检查)。 (作为“整理”,您还可以删除带有 QSD 标志的查询字符串。)
    猜你喜欢
    • 2012-07-10
    • 1970-01-01
    • 1970-01-01
    • 2015-10-06
    • 1970-01-01
    • 1970-01-01
    • 2012-06-16
    • 2013-10-20
    • 2014-03-30
    相关资源
    最近更新 更多