# Apache URL重写实现CGI路径美化 - 完整技术文档
## 1. 功能实现
### ✅ 核心功能
**实现效果**:
- **隐藏 `/cgi-bin/` 目录**:用户看不到技术细节路径
- **隐藏 `.cgi` 扩展名**:URL更简洁美观
- **自动重定向**:访问旧URL自动跳转到新URL
- **透明执行**:后台正常执行CGI程序
**具体转换**:
| 原始URL | 浏览器显示URL | 实际执行 |
|---------|--------------|---------|
| `/cgi-bin/Artocarpus/searchGenome.cgi` | `/Artocarpus/searchGenome` | `/var/www/cgi-bin/Artocarpus/searchGenome.cgi` |
| `/cgi-bin/searchAnnotationAGD.cgi` | `/searchAnnotationAGD` | `/var/www/cgi-bin/searchAnnotationAGD.cgi` |
| `/go_carica.cgi?job_id=123` | `/go_carica?job_id=123` | `/var/www/cgi-bin/go_carica.cgi` |
### ✅ 附加功能
1. **参数保留**:所有URL查询参数(`?key=value`)完整传递
2. **静态文件保护**:HTML/CSS/JS/图片等不受影响
3. **向后兼容**:旧链接自动重定向,不会失效
4. **零代码修改**:不需要修改任何CGI或HTML文件
---
## 2. 方法缺点与性能影响
### ⚠️ 主要缺点
#### **性能开销**
- **延迟增加**:20-100ms(通常约50ms)
- **原因**:每次访问需要1次额外的HTTP重定向
- **流程**:
```
用户点击 → 浏览器请求旧URL → 服务器返回307重定向 (往返1)
→ 浏览器请求新URL → 服务器执行CGI (往返2)
```
- **影响评估**:
- 如果CGI执行时间 > 1秒(数据库查询等),50ms增加约**3-5%开销**,几乎可忽略
- 如果CGI执行时间 < 100ms(快速响应),50ms增加约**50%开销**,比较明显
#### **服务器负载**
- 每次请求变成2次HTTP处理(重定向 + 实际执行)
- 高并发时服务器压力增加约**2倍**
#### **配置复杂性**
- 需要维护复杂的重写规则
- 添加新CGI目录需要添加对应规则
- 调试困难(需要查看重写日志)
### 💡 优化建议
**如果追求最佳性能**,应该:
1. **修改HTML文件中的链接**(改为 `/Artocarpus/searchGenome`)
2. **简化Apache配置**(只保留内部重写,去掉重定向规则)
3. **结果**:零性能损失
---
## 3. 配置规则详细说明
### 📋 规则架构总览
```
外部重定向规则(4条)→ 修改浏览器地址栏
↓
内部重写规则(2条)→ 后台执行CGI
```
---
### **规则1a:Artocarpus子目录CGI重定向**
```apache
RewriteRule ^/cgi-bin/Artocarpus/(.+)\.cgi$ /Artocarpus/$1 [R=307,L,QSA]
```
**功能**:处理Artocarpus子目录下的CGI访问
**匹配**:`/cgi-bin/Artocarpus/任意文件名.cgi`
**重定向到**:`/Artocarpus/文件名`(去掉路径和扩展名)
**语法说明**:
- `^` - 行首锚点
- `/cgi-bin/Artocarpus/` - 字面匹配路径
- `(.+)` - 捕获组1:匹配1个或多个任意字符(文件名)
- `\.cgi` - 匹配 `.cgi`(反斜杠转义点号)
- `$` - 行尾锚点
- `$1` - 引用捕获组1的内容
**标志说明**:
- `R=307` - 临时重定向(保持POST方法)
- `L` - Last,停止处理后续规则
- `QSA` - Query String Append,保留URL参数
**示例**:
```
/cgi-bin/Artocarpus/searchGenome.cgi?id=123
↓
/Artocarpus/searchGenome?id=123
```
---
### **规则1b:Artocarpus目录直接访问.cgi重定向**
```apache
RewriteRule ^/Artocarpus/(.+)\.cgi$ /Artocarpus/$1 [R=307,L,QSA]
```
**功能**:处理直接访问 `/Artocarpus/*.cgi` 的情况
**原因**:有些链接可能直接指向 `/Artocarpus/xxx.cgi`(不通过 `/cgi-bin/`)
**匹配**:`/Artocarpus/任意文件名.cgi`
**重定向到**:`/Artocarpus/文件名`
**示例**:
```
/Artocarpus/searchmRNA.cgi?sp=ArNa
↓
/Artocarpus/searchmRNA?sp=ArNa
```
---
### **规则1c:根目录CGI重定向(通过cgi-bin)**
```apache
RewriteRule ^/cgi-bin/([^/]+)\.cgi$ /$1 [R=307,L,QSA]
```
**功能**:处理根目录CGI访问(通过 `/cgi-bin/` 路径)
**关键**:`[^/]+` 确保只匹配单层文件名,不匹配包含 `/` 的路径
**匹配**:`/cgi-bin/文件名.cgi`(文件名中不能包含 `/`)
**重定向到**:`/文件名`
**语法说明**:
- `[^/]+` - 字符类:匹配1个或多个**非斜杠**字符
- 这样 `/cgi-bin/Artocarpus/xxx.cgi` **不会**匹配(因为包含 `/`)
- 只匹配 `/cgi-bin/searchAnnotationAGD.cgi` 这种根目录文件
**示例**:
```
/cgi-bin/searchAnnotationAGD.cgi
↓
/searchAnnotationAGD
/cgi-bin/Artocarpus/searchGenome.cgi
✗ 不匹配(被规则1a处理)
```
---
### **规则1d:根目录直接访问.cgi重定向**
```apache
RewriteCond %{REQUEST_URI} !^/Artocarpus/
RewriteCond %{REQUEST_URI} !^/cgi-bin/
RewriteRule ^/([^/]+)\.cgi$ /$1 [R=307,L,QSA]
```
**功能**:处理直接访问 `/*.cgi` 的情况
**关键**:需要排除 `/Artocarpus/` 和 `/cgi-bin/` 路径,避免冲突
**匹配**:`/文件名.cgi`(根目录,不在Artocarpus或cgi-bin下)
**重定向到**:`/文件名`
**RewriteCond说明**:
- `%{REQUEST_URI}` - 当前请求的URI
- `!^/Artocarpus/` - 不以 `/Artocarpus/` 开头(感叹号表示否定)
- `!^/cgi-bin/` - 不以 `/cgi-bin/` 开头
**为什么需要这些条件**?
- 防止与规则1a、1b冲突
- 确保只处理根目录的 `.cgi` 文件
**示例**:
```
/go_carica.cgi?job_id=123
↓
/go_carica?job_id=123
/Artocarpus/searchGenome.cgi
✗ 不匹配(被规则1b处理)
```
---
### **规则2:Artocarpus目录内部重写**
```apache
RewriteCond %{REQUEST_URI} !\.htm$
RewriteCond %{REQUEST_URI} !\.html$
RewriteCond %{REQUEST_URI} !\.css$
RewriteCond %{REQUEST_URI} !\.js$
RewriteCond %{REQUEST_URI} !\.png$
RewriteCond %{REQUEST_URI} !\.jpg$
RewriteCond %{REQUEST_URI} !\.gif$
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^/Artocarpus/([^/]+)$ /var/www/cgi-bin/Artocarpus/$1.cgi [L,QSA]
```
**功能**:将简洁URL(`/Artocarpus/searchGenome`)内部重写到实际CGI路径
**关键**:这是**内部重写**,浏览器地址栏不变,只在服务器内部执行
**工作流程**:
```
浏览器显示:/Artocarpus/searchGenome
↓ (内部重写,浏览器不知道)
实际执行:/var/www/cgi-bin/Artocarpus/searchGenome.cgi
```
**RewriteCond详解**:
1. **排除静态文件**(前7条):
```apache
RewriteCond %{REQUEST_URI} !\.htm$
```
- 确保HTML、CSS、JS、图片等静态文件不被当作CGI处理
- `$` 表示行尾,确保扩展名在末尾
2. **文件/目录存在性检查**:
```apache
RewriteCond %{REQUEST_FILENAME} !-f # 文件不存在
RewriteCond %{REQUEST_FILENAME} !-d # 目录不存在
```
- 如果 `/var/www/html/Artocarpus/searchGenome` 文件存在,则不重写
- 保护现有静态文件不被覆盖
**RewriteRule说明**:
- `^/Artocarpus/([^/]+)$` - 匹配 `/Artocarpus/单层文件名`
- `[^/]+` - 不包含斜杠,确保只匹配单层路径
- `/var/www/cgi-bin/Artocarpus/$1.cgi` - 重写到实际CGI路径
- **无 `R` 标志** - 内部重写,不重定向
**示例**:
```
请求:/Artocarpus/searchGenome
内部重写到:/var/www/cgi-bin/Artocarpus/searchGenome.cgi
浏览器地址栏:/Artocarpus/searchGenome(不变)
```
---
### **规则3:根目录内部重写**
```apache
RewriteCond %{REQUEST_URI} !\.htm$
RewriteCond %{REQUEST_URI} !\.html$
RewriteCond %{REQUEST_URI} !\.css$
RewriteCond %{REQUEST_URI} !\.js$
RewriteCond %{REQUEST_URI} !\.png$
RewriteCond %{REQUEST_URI} !\.jpg$
RewriteCond %{REQUEST_URI} !\.gif$
RewriteCond %{REQUEST_URI} !\.ico$
RewriteCond %{REQUEST_URI} !^/Artocarpus/
RewriteCond %{REQUEST_URI} !^/cgi-bin/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} ^/[^/]+$
RewriteRule ^/([^/]+)$ /var/www/cgi-bin/$1.cgi [L,QSA]
```
**功能**:将根目录简洁URL(`/searchAnnotationAGD`)内部重写到实际CGI
**关键**:与规则2类似,但针对根目录,需要更多保护条件
**额外的RewriteCond**:
```apache
RewriteCond %{REQUEST_URI} !^/Artocarpus/ # 排除Artocarpus路径
RewriteCond %{REQUEST_URI} !^/cgi-bin/ # 排除cgi-bin路径
RewriteCond %{REQUEST_URI} ^/[^/]+$ # 只匹配单层路径
```
**为什么需要 `^/[^/]+$`**?
- 确保只匹配 `/filename` 格式
- 不匹配 `/path/to/file` 多层路径
- 不匹配 `/` 根路径
**示例**:
```
请求:/searchAnnotationAGD?param=test
内部重写到:/var/www/cgi-bin/searchAnnotationAGD.cgi
浏览器地址栏:/searchAnnotationAGD?param=test(不变)
请求:/some/path/file
✗ 不匹配(包含多层路径)
```
---
## 4. 易错点与注意事项
### ⚠️ 关键易错点
#### **1. 规则顺序至关重要**
```apache
# ✅ 正确顺序
规则1a: /cgi-bin/Artocarpus/*.cgi (最具体)
规则1b: /Artocarpus/*.cgi
规则1c: /cgi-bin/*.cgi (较通用)
规则1d: /*.cgi (最通用)
规则2: /Artocarpus/* 内部重写
规则3: /* 内部重写
```
**原因**:Apache从上到下匹配,遇到 `[L]` 标志就停止。如果把通用规则放前面,具体规则永远不会执行。
**错误示例**:
```apache
# ❌ 错误:通用规则在前
RewriteRule ^/cgi-bin/([^/]+)\.cgi$ /$1 [R=307,L,QSA]
RewriteRule ^/cgi-bin/Artocarpus/(.+)\.cgi$ /Artocarpus/$1 [R=307,L,QSA]
# 结果:第二条规则永远不会执行!
```
---
#### **2. 字符类 `[^/]` vs `.+` 的区别**
```apache
# 规则1c:只匹配单层文件名
RewriteRule ^/cgi-bin/([^/]+)\.cgi$ /$1 [R=307,L,QSA]
匹配: /cgi-bin/file.cgi ✅
不匹配: /cgi-bin/dir/file.cgi ❌
# 如果错误地使用 .+
RewriteRule ^/cgi-bin/(.+)\.cgi$ /$1 [R=307,L,QSA]
匹配: /cgi-bin/file.cgi ✅
匹配: /cgi-bin/dir/file.cgi ✅ (冲突!)
```
**教训**:使用 `[^/]+` 来限制只匹配单层路径,避免冲突。
---
#### **3. RewriteCond 的否定条件容易遗漏**
```apache
# ❌ 错误:没有排除条件
RewriteRule ^/([^/]+)\.cgi$ /$1 [R=307,L,QSA]
# 结果:/Artocarpus/file.cgi 也会匹配,导致冲突!
# ✅ 正确:添加排除条件
RewriteCond %{REQUEST_URI} !^/Artocarpus/
RewriteCond %{REQUEST_URI} !^/cgi-bin/
RewriteRule ^/([^/]+)\.cgi$ /$1 [R=307,L,QSA]
```
---
#### **4. 静态文件扩展名必须完整列出**
```apache
RewriteCond %{REQUEST_URI} !\.htm$
RewriteCond %{REQUEST_URI} !\.html$
RewriteCond %{REQUEST_URI} !\.css$
# ... 必须列出所有静态文件类型
```
**常见遗漏**:
- `.ico` (favicon)
- `.svg` (矢量图)
- `.pdf` (文档)
- `.txt` (文本)
- `.xml` (数据)
**如果遗漏**:这些文件会被当作CGI处理,导致404错误。
---
#### **5. 点号必须转义**
```apache
# ❌ 错误:点号未转义(匹配任意字符)
RewriteRule ^/file.cgi$ /file [R=307,L]
# ✅ 正确:点号转义
RewriteRule ^/file\.cgi$ /file [R=307,L]
```
**为什么**:在正则表达式中,`.` 匹配任意字符,`\.` 才匹配字面点号。
---
#### **6. QSA标志容易遗忘**
```apache
# ❌ 没有QSA:查询参数丢失
RewriteRule ^/cgi-bin/(.+)\.cgi$ /$1 [R=307,L]
# /cgi-bin/file.cgi?id=123 → /file (参数丢失!)
# ✅ 有QSA:查询参数保留
RewriteRule ^/cgi-bin/(.+)\.cgi$ /$1 [R=307,L,QSA]
# /cgi-bin/file.cgi?id=123 → /file?id=123 ✅
```
---
#### **7. REQUEST_FILENAME vs REQUEST_URI 的区别**
```apache
# REQUEST_URI:URL路径
%{REQUEST_URI} = "/Artocarpus/searchGenome"
# REQUEST_FILENAME:文件系统路径
%{REQUEST_FILENAME} = "/var/www/html/Artocarpus/searchGenome"
```
**用途**:
- 检查URL模式 → 用 `REQUEST_URI`
- 检查文件是否存在 → 用 `REQUEST_FILENAME`
---
## 5. 实现原理简介
### 📐 核心原理:双层处理机制
```
┌─────────────────────────────────────────────────────┐
│ 用户访问: /cgi-bin/Artocarpus/searchGenome.cgi │
└─────────────────┬───────────────────────────────────┘
│
▼
┌────────────────────┐
│ 规则1a 匹配 │
│ 外部重定向 (307) │
└────────┬───────────┘
│
▼
┌─────────────────────────────────────────────────────┐
│ 浏览器收到: Location: /Artocarpus/searchGenome │
│ 浏览器地址栏变为: /Artocarpus/searchGenome │
└─────────────────┬───────────────────────────────────┘
│
▼
┌────────────────────┐
│ 浏览器发起新请求 │
│ /Artocarpus/searchGenome │
└────────┬───────────┘
│
▼
┌────────────────────┐
│ 规则2 匹配 │
│ 内部重写(透明) │
└────────┬───────────┘
│
▼
┌─────────────────────────────────────────────────────┐
│ Apache内部执行: │
│ /var/www/cgi-bin/Artocarpus/searchGenome.cgi │
│ 浏览器不知道,地址栏保持不变 │
└─────────────────────────────────────────────────────┘
```
### 🔑 关键技术点
1. **外部重定向(R=307)**:
- 告诉浏览器"你访问的URL变了,请访问新URL"
- 浏览器地址栏会更新
- 需要1次额外的HTTP往返
2. **内部重写(无R标志)**:
- 在Apache内部修改请求路径
- 浏览器完全不知道
- 地址栏保持不变
- 无性能损失
3. **PT标志的困境**:
- 理论上 `PT`(Pass Through)应该让重写后的URL继续被ScriptAlias处理
- 实际测试中 `PT` 在您的环境不工作(pass through但不执行)
- 解决方案:直接重写到文件系统路径(`/var/www/cgi-bin/...`)
---
## 6. 扩展与维护指南
### 📌 添加新CGI程序的注意事项
#### **情况1:在现有目录添加CGI(最简单)**
```bash
# 在 /var/www/cgi-bin/Artocarpus/ 添加新CGI
touch /var/www/cgi-bin/Artocarpus/newScript.cgi
chmod +x /var/www/cgi-bin/Artocarpus/newScript.cgi
```
**✅ 无需修改配置**:现有规则1a、1b、规则2自动处理
**访问方式**:
- 旧URL:`/cgi-bin/Artocarpus/newScript.cgi` → 自动重定向
- 新URL:`/Artocarpus/newScript` → 直接访问
---
#### **情况2:在根目录添加CGI**
```bash
# 在 /var/www/cgi-bin/ 添加新CGI
touch /var/www/cgi-bin/newTool.cgi
chmod +x /var/www/cgi-bin/newTool.cgi
```
**✅ 无需修改配置**:现有规则1c、1d、规则3自动处理
**访问方式**:
- 旧URL:`/cgi-bin/newTool.cgi` → 自动重定向
- 新URL:`/newTool` → 直接访问
---
#### **情况3:添加新的子目录(需要修改配置)**
```bash
# 创建新目录
mkdir /var/www/cgi-bin/NewModule
touch /var/www/cgi-bin/NewModule/process.cgi
```
**⚠️ 需要添加规则**:
```apache
# 在规则1b后添加
# 规则1e: 新模块重定向
RewriteRule ^/cgi-bin/NewModule/(.+)\.cgi$ /NewModule/$1 [R=307,L,QSA]
RewriteRule ^/NewModule/(.+)\.cgi$ /NewModule/$1 [R=307,L,QSA]
# 在规则2后添加
# 规则4: 新模块内部重写
RewriteCond %{REQUEST_URI} !\.htm$
RewriteCond %{REQUEST_URI} !\.html$
# ... (复制所有静态文件排除条件)
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^/NewModule/([^/]+)$ /var/www/cgi-bin/NewModule/$1.cgi [L,QSA]
# 添加目录权限
<Directory "/var/www/cgi-bin/NewModule">
Options +ExecCGI
SetHandler cgi-script
Require all granted
</Directory>
```
**规则顺序**:新规则应放在"更具体"的位置,即在通用规则之前。
---
### 🔍 正则表达式注意事项
#### **1. 文件名命名规范**
**推荐**:
```
✅ searchGenome.cgi (驼峰命名)
✅ search_genome.cgi (下划线)
✅ search-genome.cgi (连字符)
✅ searchGenome123.cgi (数字)
```
**避免**:
```
❌ search genome.cgi (空格会导致URL编码问题)
❌ search/genome.cgi (斜杠会被误解为路径)
❌ search.old.cgi (多个点号可能引起混淆)
```
#### **2. 字符类使用**
```apache
[^/]+ # 匹配除斜杠外的任意字符(推荐用于文件名)
[^/\.]+ # 匹配除斜杠和点号外的任意字符
[a-zA-Z0-9_-]+ # 只匹配字母、数字、下划线、连字符(最严格)
.+ # 匹配任意字符(包括斜杠,慎用)
```
**推荐使用 `[^/]+`**:既灵活又安全。
#### **3. 锚点的重要性**
```apache
# ❌ 没有锚点:过度匹配
RewriteRule /cgi-bin/(.+)\.cgi /$1 [R=307,L,QSA]
# 会匹配: /some/path/with/cgi-bin/in/middle/file.cgi
# ✅ 有锚点:精确匹配
RewriteRule ^/cgi-bin/(.+)\.cgi$ /$1 [R=307,L,QSA]
# 只匹配: /cgi-bin/开头 且 .cgi结尾 的URL
```
**教训**:始终使用 `^` 和 `$` 锚点。
---
### 🛠️ 调试技巧
#### **1. 启用重写日志**
```apache
# 在VirtualHost中添加
LogLevel alert rewrite:trace6
# 重启Apache
sudo systemctl restart httpd
# 查看详细日志
sudo tail -f /var/log/httpd/morac_error.log | grep rewrite
```
**trace级别**:
- `trace1` - 最少信息
- `trace3` - 中等信息(推荐)
- `trace6` - 最详细信息
#### **2. 测试单条规则**
```bash
# 临时注释掉其他规则,只保留要测试的规则
# 然后测试
curl -I http://morac.ficusgd.com/test/path
```
#### **3. 使用 curl 的 -v 选项**
```bash
curl -v http://morac.ficusgd.com/cgi-bin/test.cgi 2>&1 | grep -E "(Location|HTTP)"
```
查看完整的HTTP头信息,包括重定向的Location。
---
### 📚 维护检查清单
定期检查(每季度或添加新功能时):
- [ ] 检查错误日志中是否有重写相关错误
- [ ] 测试所有重要的CGI是否正常访问
- [ ] 验证静态文件(HTML/CSS/JS)是否正常加载
- [ ] 测试带参数的URL是否正确传递参数
- [ ] 检查新添加的CGI是否被正确处理
- [ ] 确认规则顺序没有被意外改动
---
## 总结
这套配置实现了:
- ✅ **零代码修改**的URL美化方案
- ✅ **自动处理**现有和新增的CGI(在已配置目录下)
- ✅ **向后兼容**旧URL自动重定向
- ✅ **路径隔离**多个目录互不干扰
**性能代价**:每次访问增加约50ms延迟(1次重定向)
**适用场景**:
- 已有大量CGI脚本,不想修改代码
- 对50ms延迟可接受(数据库查询类应用)
- 需要向后兼容旧链接
**不适用场景**:
- 追求极致性能(< 100ms响应时间)
- 高并发(> 10000 req/s)
**最佳实践**:逐步迁移到修改HTML链接的方式,最终去掉重定向规则,只保留内部重写,实现零性能损失。
***************************************************************************************************
=================================================================================
***************************************************************************************************
#成功的httpd.conf添加于最后的配置规则(对应上文)
# ======================================
473 # morac.ficusgd.com 站点配置
474 # 实现URL美化:隐藏 /cgi-bin/ 和 .cgi 后缀
475 # =====================================
476
477 #再次添加对/var/www/cgi-bin/下的cgi程序的url美化
478
479 <VirtualHost *:80>
480 ServerName morac.ficusgd.com
481 DocumentRoot /var/www/html
482
483 ScriptAlias /cgi-bin/ /var/www/cgi-bin/
484
485 RewriteEngine On
486
487 # 规则1a:重定向 /cgi-bin/Artocarpus/*.cgi
488 RewriteRule ^/cgi-bin/Artocarpus/(.+)\.cgi$ /Artocarpus/$1 [R=307,L,QSA]
489
490 # 规则1b:重定向 /Artocarpus/*.cgi(处理直接访问.cgi的情况)
491 RewriteRule ^/Artocarpus/(.+)\.cgi$ /Artocarpus/$1 [R=307,L,QSA]
492
493 # 规则1c:重定向 /cgi-bin/*.cgi → /*(只匹配根目录文件,不含路径)
494 RewriteRule ^/cgi-bin/([^/]+)\.cgi$ /$1 [R=307,L,QSA]
495
496 # 规则1d:重定向 /*.cgi → /*(新增!处理直接访问根目录.cgi的情况)
497 RewriteCond %{REQUEST_URI} !^/Artocarpus/
498 RewriteCond %{REQUEST_URI} !^/cgi-bin/
499 RewriteRule ^/([^/]+)\.cgi$ /$1 [R=307,L,QSA]
500
501 # 规则2:内部重写 - 只处理不带扩展名的URL
502 RewriteCond %{REQUEST_URI} !\.htm$
503 RewriteCond %{REQUEST_URI} !\.html$
504 RewriteCond %{REQUEST_URI} !\.css$
505 RewriteCond %{REQUEST_URI} !\.js$
506 RewriteCond %{REQUEST_URI} !\.png$
507 RewriteCond %{REQUEST_URI} !\.jpg$
508 RewriteCond %{REQUEST_URI} !\.gif$
509 RewriteCond %{REQUEST_FILENAME} !-f
510 RewriteCond %{REQUEST_FILENAME} !-d
511 RewriteRule ^/Artocarpus/([^/]+)$ /var/www/cgi-bin/Artocarpus/$1.cgi [L,QSA]
512
513 # 规则3:根目录简洁URL → 执行根目录CGI
514 RewriteCond %{REQUEST_URI} !\.htm$
515 RewriteCond %{REQUEST_URI} !\.html$
516 RewriteCond %{REQUEST_URI} !\.css$
517 RewriteCond %{REQUEST_URI} !\.js$
518 RewriteCond %{REQUEST_URI} !\.png$
519 RewriteCond %{REQUEST_URI} !\.jpg$
520 RewriteCond %{REQUEST_URI} !\.gif$
521 RewriteCond %{REQUEST_URI} !\.ico$
522 RewriteCond %{REQUEST_URI} !^/Artocarpus/
523 RewriteCond %{REQUEST_URI} !^/cgi-bin/
524 RewriteCond %{REQUEST_FILENAME} !-f
525 RewriteCond %{REQUEST_FILENAME} !-d
526 RewriteCond %{REQUEST_URI} ^/[^/]+$
527 RewriteRule ^/([^/]+)$ /var/www/cgi-bin/$1.cgi [L,QSA]
528
529 <Directory "/var/www/html/Artocarpus">
530 Options Indexes FollowSymLinks
531 Require all granted
532 </Directory>
533
534 <Directory "/var/www/cgi-bin/Artocarpus">
535 Options +ExecCGI
536 SetHandler cgi-script
537 Require all granted
538 </Directory>
539
540 <Directory "/var/www/cgi-bin">
541 Options +ExecCGI
542 SetHandler cgi-script
543 Require all granted
544 </Directory>
545
546 ErrorLog /var/log/httpd/morac_error.log
547 CustomLog /var/log/httpd/morac_access.log combined
548 </VirtualHost>
~
#######################################################
######################################################
#deepseek修改一个小bug(url访问必须带/)后版本,未测试
<VirtualHost *:80>
ServerName morac.ficusgd.com
DocumentRoot /var/www/html
ScriptAlias /cgi-bin/ /var/www/cgi-bin/
RewriteEngine On
# ========== 新增:目录斜杠自动重定向 ==========
# 规则0:自动为目录添加斜杠(必须在其他规则之前)
RewriteCond %{REQUEST_FILENAME} -d
RewriteCond %{REQUEST_URI} !/$
RewriteRule ^(.*)$ $1/ [R=301,L]
# ========== 原有的重定向规则 ==========
# 规则1a:重定向 /cgi-bin/Artocarpus/*.cgi
RewriteRule ^/cgi-bin/Artocarpus/(.+)\.cgi$ /Artocarpus/$1 [R=307,L,QSA]
# 规则1b:重定向 /Artocarpus/*.cgi
RewriteRule ^/Artocarpus/(.+)\.cgi$ /Artocarpus/$1 [R=307,L,QSA]
# 规则1c:重定向 /cgi-bin/*.cgi → /*
RewriteRule ^/cgi-bin/([^/]+)\.cgi$ /$1 [R=307,L,QSA]
# 规则1d:重定向 /*.cgi → /*
RewriteCond %{REQUEST_URI} !^/Artocarpus/
RewriteCond %{REQUEST_URI} !^/cgi-bin/
RewriteRule ^/([^/]+)\.cgi$ /$1 [R=307,L,QSA]
# ========== 修改后的内部重写规则 ==========
# 规则2:内部重写 - 处理 Artocarpus 下的CGI请求
# 排除对目录本身的处理
RewriteCond %{REQUEST_URI} !^/Artocarpus/?$ # 排除 /Artocarpus 目录本身
RewriteCond %{REQUEST_URI} !\.(htm|html|css|js|png|jpg|gif|ico)$
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^/Artocarpus/([^/]+)/?$ /var/www/cgi-bin/Artocarpus/$1.cgi [L,QSA]
# 规则3:根目录简洁URL → 执行根目录CGI
RewriteCond %{REQUEST_URI} !\.(htm|html|css|js|png|jpg|gif|ico)$
RewriteCond %{REQUEST_URI} !^/Artocarpus
RewriteCond %{REQUEST_URI} !^/cgi-bin/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^/([^/]+)/?$ /var/www/cgi-bin/$1.cgi [L,QSA]
# ========== 原有的目录配置 ==========
<Directory "/var/www/html/Artocarpus">
Options Indexes FollowSymLinks
# 确保设置了默认索引文件
DirectoryIndex index.html index.php
Require all granted
</Directory>
<Directory "/var/www/cgi-bin/Artocarpus">
Options +ExecCGI
SetHandler cgi-script
Require all granted
</Directory>
<Directory "/var/www/cgi-bin">
Options +ExecCGI
SetHandler cgi-script
Require all granted
</Directory>
ErrorLog /var/log/httpd/morac_error.log
CustomLog /var/log/httpd/morac_access.log combined
</VirtualHost>