có vẻ như việc truy cập site.com/api/v1/ không thực thi api_v1.php. Thay vào đó, nó sẽ tiếp tục và thực thi index.php
Có, bởi vì quy tắc đầu tiên viết lại yêu cầu thành api_v1.php
và điều này cuối cùng được viết lại thành index.php
theo quy tắc thứ hai (vì php
không có trong danh sách các tiện ích mở rộng bị loại trừ trong lần đầu tiên điều kiện, tình trạng, trạng thái, điều kiện thứ hai cũng thành công nên điều kiện thứ ba không được xử lý - xem bên dưới) trong lần chuyển thứ hai của công cụ viết lại. trong một danh mục bối cảnh (tức là .htaccess
) các l
cờ không dừng tất cả quá trình xử lý, nó chỉ dừng dòng điện đi qua công cụ viết lại. Công cụ viết lại lặp lại cho đến khi URL đi qua không thay đổi.
Bạn có thể giải quyết vấn đề này trên Apache 2.4 bằng cách sử dụng CHẤM DỨT
cờ, thay vì l
, theo quy tắc đầu tiên để dừng tất cả quá trình xử lý bằng công cụ viết lại.
Ví dụ:
RewriteRule ^api/v1/ api_v1.php [NC,END]
(Tôi đã xóa dấu (.*)$
trên biểu thức chính quy vì nó không cần thiết ở đây và làm cho biểu thức chính quy kém hiệu quả hơn một chút.)
Tuy nhiên, thực tế là một yêu cầu cho một hiện có .php
tệp được viết lại bởi các quy tắc sau này của bạn thực sự chứng minh rằng các quy tắc thứ hai và thứ ba của bạn dường như không hoạt động như dự định...
#2. Viết lại vào index.php ngoại trừ các tệp thiết kế/tài liệu/favicon/robots tồn tại
RewriteCond %{REQUEST_URI} !.(css|js|png|jpg|jpeg|bmp|gif|ttf|eot|svg|woff|woff2|ico|webp|pdf)$
RewriteCond %{REQUEST_URI} !^(robots\.txt|favicon\.ico)$ [OR]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php [L]
#3. Viết lại mọi thứ khác
RewriteRule ^(.*)$ index.php [L]
Nếu bạn yêu cầu một cái gì đó.php
sau đó là người đầu tiên điều kiện, tình trạng, trạng thái thành công (vì .php
Là không phải đưa vào danh sách). Điều kiện thứ hai cũng thành công (không phải robot.txt
hoặc favicon.ico
). Vì điều kiện thứ hai rõ ràng HOẶC với điều kiện thứ ba nên điều kiện thứ ba không được xử lý.Tất cả các điều kiện đều thành công và yêu cầu được viết lại thành index.php
(bất kể một cái gì đó.php
tồn tại hay không).
Mặt khác, nếu bạn yêu cầu tài nguyên.css
sau đó là người đầu tiên điều kiện, tình trạng, trạng thái thất bại (vì nó có một .css
sự mở rộng). Vì điều kiện này hoàn toàn là AND'd nên không có điều kiện nào khác được xử lý và quy tắc không được kích hoạt. Quy tắc thứ ba sau đó viết lại vô điều kiện tài nguyên.css
đến index.php
, bất kể nó có tồn tại hay không!
Vì vậy, điều này không kiểm tra xem tài nguyên được yêu cầu (css
, jpg
, v.v.) "tồn tại" như được ngụ ý bởi nhận xét trước đó. Điều kiện thứ ba (kiểm tra yêu cầu không ánh xạ tới tệp) chỉ được xử lý khi điều kiện OR trước đó không thành công VÀ điều kiện đầu tiên thành công. Nói cách khác, điều kiện thứ 3 chỉ được xử lý khi bạn yêu cầu /robots.txt
- mà tôi chắc chắn không phải là ý định của bạn.
Nói cách khác, các quy tắc #2 và #3 (bất chấp sự phức tạp rõ ràng của chúng) dường như được viết lại khá nhiều. mọi thứ đến index.php
.
Giải pháp hoàn chỉnh
Dựa trên nhận xét bổ sung của bạn:
Đối với một tập hợp con các loại tệp, hãy cung cấp tài nguyên - nếu nó tồn tại. Nếu tài nguyên không tồn tại thì hãy gửi yêu cầu tới index.php
.
Đối với các loại tệp khác, hãy gửi yêu cầu tới index.php
, bất kể tài nguyên đó có tồn tại hay không.
Một vài yêu cầu (tức là. /robots.txt
và /favicon.ico
) không được gửi đến index.php
.
Thay vào đó, hãy thử những cách sau:
# Ngăn chặn chuyển hướng 301 bằng dấu gạch chéo khi thư mục tồn tại và không có dấu gạch chéo được thêm vào
# Đây không phải là vấn đề bảo mật ở đây vì bộ định tuyến PHP được sử dụng và tất cả các đường dẫn đều được chuyển hướng
Thư mụcSlash Off
# Vì "DirectorySlash Off" được đặt, hãy đảm bảo rằng danh sách thư mục mod_auotindex bị tắt
Tùy chọn -Chỉ mục
Viết LạiEngine Trên
#1. Viết lại cho url API
RewriteRule ^api/v1/ api_v1.php [NC,END]
#2. Các URL/tệp đã biết được phục vụ trực tiếp
RewriteRule ^(index\.php|robots\.txt|favicon\.ico)$ - [END]
#3.Một số loại tệp (tài nguyên) được cung cấp trực tiếp nếu chúng tồn tại
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule \.(css|js|png|jpe?g|bmp|gif|ttf|eot|svg|woff|woff2|ico|webp|pdf)$ - [END]
#4. Viết lại mọi thứ khác
RewriteRule ^ index.php [KẾT THÚC]
Các quy tắc kết thúc sớm cho mọi thứ cần được phục vụ trực tiếp, vì vậy chúng tôi chỉ cần viết lại thành index.php
một lần trong quy tắc cuối cùng.
Lưu ý rằng tôi đã bao gồm index.php
trong quy tắc #2. Đây là một sự tối ưu hóa, mặc dù không thực sự cần thiết nếu sử dụng CHẤM DỨT
cờ (trái ngược với l
) trên quy tắc cuối cùng.
Theo tùy chọn, bạn có thể chọn chuyển hướng bất kỳ thẳng thắn yêu cầu index.php
quay lại thư mục gốc (để chuẩn hóa URL cho các công cụ tìm kiếm). Đây chỉ là trong trường hợp /index.php
được hiển thị (hoặc đoán) cho người dùng cuối.
Ví dụ: thêm phần sau vào sau quy tắc đầu tiên cho API:
#1.5 Chuyển hướng các yêu cầu trực tiếp tới "/index.php" trở lại "/" (gốc)
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule ^index\.php$ / [R=301,L]
Các điều kiện, tình trạng, trạng thái kiểm tra chống lại REDIRECT_STATUS
biến môi trường là cần thiết để ngăn vòng lặp chuyển hướng - để tránh chuyển hướng URL đã viết lại. (Mặc dù, một lần nữa, điều này không bắt buộc nếu sử dụng CHẤM DỨT
gắn cờ trên quy tắc cuối cùng/viết lại.)