0

我想使用在符号链接存在但被破坏时执行的重写规则。

所以场景是:

  1. 符号链接不存在:正常的 404/403 错误。
  2. 符号链接存在但已损坏:调用 generate-cache.php。
  3. 符号链接存在并且正在工作:目标文件已正常加载。

例如:

## Symlink does not exist.
GET /links/cache/secret.jpg
404 Not Found

## Symlink is broken.
GET /links/cache/secret.jpg
  Links to /images/cache/secret.jpg
  Because it's broken, rewrites to: generate-cache.php?path=cache/secret.jpg
200 OK

## Symlink works.
GET /links/cache/secret.jpg
  Links to /images/cache/secret.jpg
200 OK

更新:我想避免使用 PHP 进行这些检查,因为它会导致性能瓶颈。如果文件存在,则通过 PHP 输出文件会导致 PHP 锁定。我也没有选择使用多个 PHP 线程或安装额外的 apache 模块。

4

1 回答 1

2

我不知道在 mod_rewrite 中测试损坏的符号链接的方法(-l检查符号链接是否存在,但不尝试遵循它),这可能意味着您需要在 PHP 中编写某种回调(或其他语言)。

另一种方法是重写所有请求,并在 PHP 中构建此逻辑:

  1. 如果文件存在于缓存目录中,则设置适当的标题并用于readfile()输出数据
  2. 如果符号链接存在(或者只是“控制”目录中具有正确名称的空文件;我认为您有其他进程创建符号链接,因此可以将其修改为touch文件),进行适当的生成
  3. 如果符号链接/控制文件不存在,发送 404 标头并立即退出

另一种更有效的变体是让 Apache 直接提供缓存的图像(如果存在),并在第 2 步和第 3 步重写为 PHP。像这样:

RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} !-f
RewriteRule /links/cache/(.*) generate-cache.php?path=$1

在 PHP 中

if ( ! file_exists('cache_control/' . $_GET['path'] )
{
     header('HTTP/1.1 404 Not Found');
     exit;
}
else
{
     // Control file exists, so this is an allowable file; carry on...
     generate_file_by_whatever_magic_you_have( 'links/cache/' . $_GET['path'] );
     header('Content-Type: image/jpeg'); // May need to support different types
     readfile( 'links/cache/' . $_GET['path'] );
     exit;
}

假设您可以用控制文件替换符号链接,并且名称直接匹配(即您的符号链接的目标可以从其名称“猜测”),您也可以将控制文件检查移动到 mod_rewrite 中:

# If the requested file doesn't exist (if it does, let Apache serve it)
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} !-f
# Match the basic path format and capture image name into %1
RewriteCond %{REQUEST_FILENAME} /links/cache/(.*)
# Check if a cache control file exists with that image name
RewriteCond %{DOCUMENT_ROOT}/cache_control/%1 -f
# If so, serve via PHP; if not, no rewrite will happen, so Apache will return a 404
RewriteRule /links/cache/(.*) generate-cache.php?path=$1
于 2013-05-15T17:27:43.480 回答