将变量从文件读取到 .htaccess 会导致内部服务器错误

问题描述 投票:0回答:1

我想要实现的目标

  1. 我有超过 1,000 个格式为

    https://example.com/archives/<NNNNNN>.php
    的单独文件,其中
    N
    是一个整数。

  2. 我需要保持现有的结构不变,尽管我可以添加它。在这种情况下,每个页面都有一个唯一的

    data-url-title="<url-friendly-title>"

  3. 我希望我的

    .htaccess
    配置来确定读取的文件,使用正则表达式提取
    url-friendly-title
    ,并重写最终 URL 以替换
    <NNNNNN>
    ,格式为
    https://example.com/archives/url-friendly-title.php
    (然后我会删除
    .php 
    从它开始——但我没有走那么远)。

我尝试做什么

# Enable rewriting
RewriteEngine On

# Match the old archive URL
RewriteCond %{REQUEST_URI} ^/archives/([0-9]+)\.php$

# Check that the file exists
RewriteCond expr "-f '%{DOCUMENT_ROOT}/archives/%1.php'"

# Extract data-url-title from the file content
RewriteCond expr "file('%{DOCUMENT_ROOT}/archives/%1.php') =~ /data-url-title=\"([^\"]+)\"/"

# Rewrite the URL to the new friendly URL
RewriteRule ^archives/([0-9]+)\.php$ /archives/%1.php [R=301,L]

发生了什么

任何使用此配置的尝试都会导致我的整个网站抛出内部服务器错误并显示日志消息

RewriteCond: bad flag delimiters

  • 我认为我的正则表达式中没有任何空格。

  • 我已将我的

    .htaccess
    文件转换为 Unix 结尾。

我查看了许多已回答的问题,它们似乎表明,在 Apache 2.4.x 中,可以使用

RewriteCond expr "<expression>"
:

从外部文件读取变量

我无法让它工作。还有什么:

  • htaccess 测试器 对于两个

    Unsupported TestString: expr
    语句都会抛出
    RewriteCond expr

  • .htaccess check 特别声明

    RewriteCond: bad flag delimiters
    第二 RewriteCond 行。

更新:我尝试将

s
推迟到
RewriteCond expr "file('%{DOCUMENT_ROOT}/archives/%1.php') =~ /data-url-title=\"([^\"]+)\"/s"
进行换行匹配,但结果是相同的:浏览器中的内部服务器错误;
RewriteCond: bad flag delimiters
在日志中。

apache .htaccess mod-rewrite url-rewriting
1个回答
0
投票

嗯,因为根据变量inin重写页面URL,仅使用

.htaccess
,似乎行不通。 。 。这就是我所做的:

/.htaccess

首先,我检查所需的模式并将其传递给

redirect.php
处理程序脚本。然而,这里有一个技巧,我还将重写的 URL 传递给处理程序脚本,以确保使用旧式 URL 的任何人仍然可以获得有效的结果。

# Enable rewriting
RewriteEngine On

# Redirect numeric IDs to friendly URLs
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule ^archives/(\d+)\.php$ /archives/redirect.php?id=$1 [R=301,L,QSA]

# Handle friendly URLs
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^archives/([a-z0-9-]+)/?$ /archives/redirect.php?title=$1 [L,QSA]

/archives/redirect.php

这就是乐趣的开始。代码中的注释解释了脚本的工作原理,但现在的重点是:

  • 导航至
    https://example.com/archives/friendly-name
    工作正常
  • 导航到
    https://example.com/archives/000001.php
    仍会重定向到
    example.com/archives/friendly-name
    ,以实现向后兼容性
<?php
// Iterate through all available `<NNNNNN>.php` files and check
// whether file contains the `data-url-title` attribute
function findMatchingFile($fileFormat, $isId = false) {
  $files = glob(__DIR__ . "/*.php");
  foreach ($files as $file) {
    if (basename($file) === 'redirect.php') continue;
    $content = file_get_contents($file); 
    if ($isId) {
      if (basename($file) === $fileFormat . '.php') {
        if (preg_match('/data-url-title="([a-z0-9-]+)"/', $content, $matches)) {
          return array($file, $matches[1]);
        }
      }
    } else {
      if (preg_match('/data-url-title="' . preg_quote($fileFormat, '/') . '"/', $content)) {
        return array($file, $fileFormat);
      }
    }
  }
  return false;
}

// Get input from query parameters
$input = isset($_GET['id']) ? $_GET['id'] : (isset($_GET['title']) ? $_GET['title'] : '');

// Sanitize input
$input = trim(preg_replace('/[^a-z0-9-]/', '', strtolower($input)), '-');

// Find file matching input: if searchin by ID and matching file is found,
// redirect to archive URL; if searching by title, include matching fild
if (!empty($input)) {
  $result = findMatchingFile($input, isset($_GET['id']));
  if ($result) {
    if (isset($_GET['id'])) {
      header("HTTP/1.1 301 Moved Permanently");
      header("Location: /archives/" . urlencode($result[1]));
      exit();
    } else {
      include($result[0]);
      exit();
    }
  }
}

header("HTTP/1.0 404 Not Found");
echo "404 Not Found";
?>
最新问题
© www.soinside.com 2019 - 2025. All rights reserved.