Score:1

.htaccess mod_rewrite ไม่พบ RewriteRules ทั้งหมด

ธง de

มีแอปพลิเคชัน PHP ที่มีเราเตอร์ PHP เป็นจุดเริ่มต้นสำหรับคำขอทั้งหมดที่อยู่ใน index.php ฉันกำลังพยายามเขียนไฟล์ .htaccess เพื่อส่งต่อทุกคำขอไปยัง index.php ยกเว้นคำขอ API และทรัพยากรการออกแบบ ดังนั้นฉันจึงพยายามรับพฤติกรรมต่อไปนี้:

  1. example.com/api/v1/* ควรให้บริการ api_v1.php
  2. example.com/any_path/resource.css => ควรให้บริการ ทรัพยากร.css ถ้ามีอยู่ (มีหลายนามสกุลที่อนุญาต; .css เป็นเพียงตัวอย่างเดียว)
  3. ให้บริการ index.php สำหรับสิ่งที่ไม่เป็นไปตามเงื่อนไขข้างต้น

กำหนดว่า .htaccess ถูกประเมินจากบนลงล่าง จากเงื่อนไขเฉพาะไปจนถึงเงื่อนไขทั่วไปและแฟล็กนั้น [L] จะหยุดการดำเนินการหากมีสิ่งใดที่ตรงกัน ฉันได้จัดการสิ่งต่อไปนี้ .htaccess:

RewriteEngine เปิดอยู่

# ป้องกันการเปลี่ยนเส้นทาง 301 ด้วยเครื่องหมายทับเมื่อมีโฟลเดอร์อยู่และไม่ได้ใส่เครื่องหมายทับ
# นี่ไม่ใช่ปัญหาด้านความปลอดภัยเนื่องจากใช้เราเตอร์ PHP และเส้นทางทั้งหมดถูกเปลี่ยนเส้นทาง
DirectorySlash ปิด

#1. เขียนใหม่สำหรับ API url
RewriteRule ^api/v1/(.*)$ api_v1.php [L,NC]

#2. เขียนใหม่เป็น index.php ยกเว้นสำหรับไฟล์ design/document/favicon/robots ที่มีอยู่
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)$ [หรือ]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php [L]

#3. เขียนซ้ำสิ่งอื่นใด
RewriteRule ^(.*)$ index.php [L]

การใช้รหัสด้านบนดูเหมือนว่าการเข้าถึง ตัวอย่าง.com/api/v1/ ไม่ดำเนินการ api_v1.php. แต่จะดำเนินต่อไปและดำเนินการแทน index.php

ตัวอย่าง.com/api/v1/ จะใช้งานได้ก็ต่อเมื่อฉันลบเงื่อนไขทั้งหมดหลังจากบรรทัดที่ 8

ฉันทำอะไรผิดที่นี่?

kz flag
ไม่ชัดเจนว่าคุณกำลังพยายามทำอะไรคำขอบางรายการควรเขียนใหม่เป็น `index.php` แม้ว่าจะมีอยู่ในไฟล์จริง แต่ไม่ได้ระบุประเภทไฟล์ใดประเภทหนึ่งหรือไม่ คำขอทรัพยากร (`.css`, `.jpg` ฯลฯ) ควรเขียนใหม่เป็น `index.php` ไหม ถ้าไม่มี (เช่น คุณมี URL ที่ถูกต้องซึ่งมี "นามสกุลไฟล์" แบบนี้หรือไม่)
caffeine avatar
de flag
@MrWhite ใช่ หากไม่พบไฟล์ .css ให้เขียนใหม่เป็น index.php เพื่อให้ฉันสามารถจัดการกับข้อผิดพลาด 404 จาก index.php ได้อย่างเหมาะสม หากมีไฟล์ .css อยู่ ให้เขียนใหม่เป็น index.php
kz flag
แต่ประเภทไฟล์ที่คุณไม่ได้ระบุไว้อย่างชัดเจนล่ะ ควรกำหนดเส้นทางเหล่านี้ผ่าน `index.php` ไม่ว่าจะมีอยู่หรือไม่ก็ตาม (คุณจำเป็นต้องระบุรายการประเภทไฟล์ที่รู้จักอย่างชัดเจนหรือไม่)
caffeine avatar
de flag
ใช่ อะไรก็ตามที่ไม่อยู่ในรายการนั้น ไม่ว่าจะมีอยู่หรือไม่ก็ตาม ควรเขียนใหม่เป็น index.php ภาวะแทรกซ้อนเดียวที่นี่คือฉันยังเขียนใหม่เป็น index.php สำหรับชื่อไฟล์ที่อยู่ในรายการ แต่ไม่มีอยู่ในเซิร์ฟเวอร์ โดยพื้นฐานแล้ว ฉันพยายามให้บริการไฟล์ .css โดยตรงหากมีสิ่งเหล่านี้อยู่ มิฉะนั้น ให้เขียนทุกอย่างใหม่เป็น index.php (อ้างอิงถึงเงื่อนไข #2 และ #3)
kz flag
ฉันได้อัปเดตคำตอบด้วยโซลูชันที่สมบูรณ์ตามความคิดเห็นของคุณ
Score:1
ธง kz

ดูเหมือนว่าการเข้าถึง site.com/api/v1/ จะไม่เรียกใช้งาน api_v1.php แต่จะดำเนินการต่อและเรียกใช้งาน index.php

ใช่ เนื่องจากกฎข้อแรกเขียนคำขอใหม่เป็น api_v1.php และสิ่งนี้จบลงด้วยการเขียนใหม่ index.php ตามกฎข้อที่สอง (เพราะ php.ini ไม่ได้อยู่ในรายการส่วนขยายที่ยกเว้นในตอนแรก เงื่อนไขเงื่อนไขที่สองก็สำเร็จเช่นกัน ดังนั้นเงื่อนไขที่สามจึงไม่ได้รับการประมวลผล - ดูด้านล่าง) ระหว่างรอบที่สองของกลไกเขียนใหม่ ใน ไดเรกทอรี บริบท (เช่น .htaccess) ที่ แอล แฟล็กไม่ได้หยุดการประมวลผลทั้งหมด แต่จะหยุดการผ่านปัจจุบันผ่านเอ็นจิ้นการเขียนซ้ำ เอ็นจิ้นการเขียนซ้ำจะวนซ้ำจนกว่า URL จะผ่านไปโดยไม่มีการเปลี่ยนแปลง

คุณสามารถแก้ไขปัญหานี้บน Apache 2.4 ได้โดยใช้ไฟล์ จบ ธง แทน แอลตามกฎข้อแรกให้หยุดการประมวลผลทั้งหมดโดยโปรแกรมเขียนใหม่

ตัวอย่างเช่น:

RewriteRule ^api/v1/ api_v1.php [NC,END]

(ผมลบคำต่อท้าย (.*)$ ใน regex เนื่องจากไม่จำเป็นที่นี่ และทำให้ regex มีประสิทธิภาพน้อยลงเล็กน้อย)

อย่างไรก็ตามข้อเท็จจริงที่ว่าขอที่มีอยู่ .php ไฟล์ถูกเขียนใหม่โดยกฎในภายหลังของคุณ แสดงให้เห็นว่ากฎข้อที่สองและสามของคุณดูเหมือนจะไม่ทำงานตามที่ตั้งใจไว้...

#2. เขียนใหม่เป็น index.php ยกเว้นสำหรับไฟล์ design/document/favicon/robots ที่มีอยู่
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)$ [หรือ]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php [L]

#3. เขียนซ้ำสิ่งอื่นใด
RewriteRule ^(.*)$ index.php [L]

หากคุณร้องขอ บางสิ่งบางอย่าง.php จากนั้นเป็นครั้งแรก เงื่อนไข ประสบความสำเร็จ (เพราะ .php เป็น ไม่ รวมอยู่ในรายการ) เงื่อนไขที่สองก็สำเร็จเช่นกัน (ไม่ใช่ โรบ็อต.txt หรือ favicon.ico). เนื่องจากเงื่อนไขที่สองนั้นชัดเจนหรือขัดแย้งกับเงื่อนไขที่สาม เงื่อนไขที่สามจึงไม่ถูกประมวลผลเงื่อนไขทั้งหมดสำเร็จและคำขอจะถูกเขียนใหม่ index.php (ไม่ว่าจะ บางสิ่งบางอย่าง.php มีอยู่หรือไม่)

ถ้าในทางกลับกันคุณร้องขอ ทรัพยากร.css จากนั้นเป็นครั้งแรก เงื่อนไข ล้มเหลว (เพราะมีไฟล์ .css การขยาย). เนื่องจากเงื่อนไขนี้เป็นแบบ AND โดยปริยาย จึงไม่มีการประมวลผลเงื่อนไขเพิ่มเติมและกฎจะไม่ทำงาน กฎข้อที่สามจะเขียนใหม่โดยไม่มีเงื่อนไข ทรัพยากร.css ถึง index.phpไม่ว่าจะมีอยู่หรือไม่ก็ตาม!

ดังนั้น นี่จะไม่ตรวจสอบว่าทรัพยากรที่ร้องขอ (css, jpgฯลฯ) "มีอยู่" ตามที่ดูเหมือนจะบอกเป็นนัยในความคิดเห็นก่อนหน้า เงื่อนไขที่สาม (ที่ตรวจสอบว่าคำขอไม่ได้แมปกับไฟล์) จะได้รับการประมวลผลก็ต่อเมื่อเงื่อนไข OR ก่อนหน้าล้มเหลว และเงื่อนไขแรกสำเร็จ กล่าวอีกนัยหนึ่ง เงื่อนไขที่ 3 จะดำเนินการเมื่อคุณร้องขอเท่านั้น /robots.txt - ซึ่งผมแน่ใจว่าไม่ใช่เจตนาของคุณ

กล่าวอีกนัยหนึ่ง กฎข้อที่ 2 และข้อที่ 3 (แม้จะดูซับซ้อนก็ตาม) ดูเหมือนจะเป็นการเขียนใหม่ค่อนข้างมาก ทุกอย่าง ถึง index.php.

โซลูชั่นที่สมบูรณ์

ตามความคิดเห็นเพิ่มเติมของคุณ:

  • สำหรับชุดย่อยของประเภทไฟล์ ให้บริการทรัพยากร - หากมีอยู่ หากไม่มีทรัพยากรให้ส่งคำขอไปที่ index.php.

  • สำหรับไฟล์ประเภทอื่น ๆ ให้ส่งคำขอไปที่ index.phpโดยไม่คำนึงว่าทรัพยากรนั้นมีอยู่หรือไม่

  • คำขอเล็กน้อย (เช่น /robots.txt และ /favicon.ico) ไม่ควรส่งไปที่ index.php.

ลองทำสิ่งต่อไปนี้แทน:

# ป้องกันการเปลี่ยนเส้นทาง 301 ด้วยเครื่องหมายทับเมื่อมีโฟลเดอร์อยู่และไม่ได้ใส่เครื่องหมายทับ
# นี่ไม่ใช่ปัญหาด้านความปลอดภัยเนื่องจากใช้เราเตอร์ PHP และเส้นทางทั้งหมดถูกเปลี่ยนเส้นทาง
DirectorySlash ปิด

# เนื่องจากมีการตั้งค่า "DirectorySlash Off" ตรวจสอบให้แน่ใจว่ารายการไดเรกทอรี mod_auotindex ถูกปิดใช้งาน
ตัวเลือก -ดัชนี

RewriteEngine เปิดอยู่

#1. เขียนใหม่สำหรับ API url
RewriteRule ^api/v1/ api_v1.php [NC,END]

#2. URL/ไฟล์ที่รู้จักจะถูกส่งโดยตรง
RewriteRule ^(index\.php|robots\.txt|favicon\.ico)$ - [จบ]

#3.ไฟล์บางประเภท (ทรัพยากร) จะให้บริการโดยตรงหากมีอยู่
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule \.(css|js|png|jpe?g|bmp|gif|ttf|eot|svg|woff|woff2|ico|webp|pdf)$ - [จบ]

#4. เขียนใหม่ทั้งหมดอื่น
RewriteRule ^ index.php [จบ]

กฎเสร็จสิ้นก่อนเวลาสำหรับทุกสิ่งที่ต้องให้บริการโดยตรง ดังนั้นเราจำเป็นต้องเขียนใหม่เท่านั้น index.php ครั้งเดียวในกฎข้อสุดท้าย

โปรดทราบว่าฉันได้รวม index.php ในกฎข้อที่ 2 นี่คือการเพิ่มประสิทธิภาพ แม้ว่าจะไม่จำเป็นอย่างยิ่งหากใช้ จบ ธง (ตรงข้ามกับ แอล) ในกฎข้อสุดท้าย

หรือคุณอาจเลือกที่จะเปลี่ยนเส้นทางก็ได้ โดยตรง ขอให้ index.php กลับไปที่รูท (เพื่อบัญญัติ URL สำหรับเครื่องมือค้นหา) นี่เป็นเพียงในกรณีที่ /index.php เปิดเผย (หรือเดา) ต่อผู้ใช้ปลายทาง

ตัวอย่างเช่น เพิ่มสิ่งต่อไปนี้หลังจากกฎข้อแรกสำหรับ API:

#1.5 เปลี่ยนเส้นทางคำขอโดยตรงไปที่ "/index.php" กลับไปที่ "/" (รูท)
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule ^index\.php$ / [R=301,L]

เดอะ เงื่อนไข ที่ตรวจสอบกับ REDIRECT_STATUS ตัวแปรสภาพแวดล้อมเป็นสิ่งจำเป็นเพื่อป้องกันการวนรอบการเปลี่ยนเส้นทาง - เพื่อหลีกเลี่ยงการเปลี่ยนเส้นทาง URL ที่เขียนใหม่ (แม้ว่าจะไม่จำเป็นอย่างยิ่งหากใช้ไฟล์ จบ แฟล็กในกฎสุดท้าย/เขียนใหม่)

caffeine avatar
de flag
ขอบคุณสำหรับคำอธิบายที่กว้างขวาง สิ่งนี้ช่วยแก้ปัญหาของฉันได้อย่างแน่นอนและนำข้อมูลที่เป็นประโยชน์ในหัวข้อนี้มาให้
Score:0
ธง ng

พยายามวางเงื่อนไขการเขียนซ้ำก่อนกฎแต่ละข้อ แล้วจึงทำลายกฎ กล่าวอีกนัยหนึ่ง ทุกเงื่อนไขจำเป็นต้องมีกฎของมันเอง

เงื่อนไข -> กฎ
เงื่อนไข -> กฎ
...

โพสต์คำตอบ

คนส่วนใหญ่ไม่เข้าใจว่าการถามคำถามมากมายจะปลดล็อกการเรียนรู้และปรับปรุงความสัมพันธ์ระหว่างบุคคล ตัวอย่างเช่น ในการศึกษาของ Alison แม้ว่าผู้คนจะจำได้อย่างแม่นยำว่ามีคำถามกี่ข้อที่ถูกถามในการสนทนา แต่พวกเขาไม่เข้าใจความเชื่อมโยงระหว่างคำถามและความชอบ จากการศึกษาทั้ง 4 เรื่องที่ผู้เข้าร่วมมีส่วนร่วมในการสนทนาด้วยตนเองหรืออ่านบันทึกการสนทนาของผู้อื่น ผู้คนมักไม่ตระหนักว่าการถามคำถามจะมีอิทธิพลหรือมีอิทธิพลต่อระดับมิตรภาพระหว่างผู้สนทนา