Score:2

ทำไมการเปลี่ยนเส้นทางใน .htaccess ไม่ทำงาน

ธง sa

ฉันมีเว็บไซต์ Wordpress ฉันต้องการเปลี่ยนเส้นทาง .php url ไปยังอันที่ไม่มี .php ต่อท้าย .htaccess เป็นดังนี้:

# เริ่มต้น WordPress
<IfModule mod_rewrite.c>
RewriteEngine เปิดอยู่


RewriteRule ^(.*)\.php$ "$1" [R=301,L,NC]


ฐานการเขียนซ้ำ /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
กฎการเขียนซ้ำ /index.php [L]
</หากโมดูล>

# จบเวิร์ดเพรส

แต่เมื่อฉันไปเยี่ยม https://www.example.com/somepage.phpไม่สามารถแสดงเพจได้ ข้อผิดพลาดต่อไปนี้แสดงในเบราว์เซอร์:

หน้าเปลี่ยนเส้นทางไม่ถูกต้อง

    เกิดข้อผิดพลาดระหว่างการเชื่อมต่อกับ www.example.com
    
        บางครั้งปัญหานี้อาจเกิดจากการปิดใช้งานหรือปฏิเสธที่จะยอมรับคุกกี้

และ URL ในแถบที่อยู่จะกลายเป็น https://www.example.com/index.

ถ้าฉันเปลี่ยนกฎการเขียนใหม่เป็น:

# เริ่มต้น WordPress
<IfModule mod_rewrite.c>
RewriteEngine เปิดอยู่


RewriteRule ^(.*)\.html$ "$1" [R=301,L,NC]


ฐานการเขียนซ้ำ /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
กฎการเขียนซ้ำ /index.php [L]
</หากโมดูล>

# จบเวิร์ดเพรส

และเยี่ยมชม https://www.example.com/somepage.htmlมันถูกเปลี่ยนเส้นทางสำเร็จไปที่ https://www.example.com/somepage และหน้าเว็บแสดงได้ตามปกติ ทำไม

Score:2
ธง kz

เพราะเนื่องจากการเปลี่ยนเส้นทางคือ ไม่มีเงื่อนไขคุณสิ้นสุดการเปลี่ยนเส้นทางอีกครั้ง หลังจาก URL ถูกเขียนใหม่ index.php (ตัวควบคุมด้านหน้าของ WordPress)

เมื่อคุณร้องขอ /somepage.php:

  1. คุณถูกนำไปที่ /บางเพจ (ตามกฎข้อแรก) การตอบสนองการเปลี่ยนเส้นทางจะถูกส่งกลับไปยังไคลเอ็นต์
  2. ในคำขอที่สอง /บางเพจ ถูกเขียนใหม่เป็นการภายใน /index.php ตามกฎข้อสุดท้าย เครื่องมือเขียนใหม่จะเริ่มต้นใหม่ (ใน a ไดเรกทอรี บริบท)...
  3. /index.php ถูกเปลี่ยนเส้นทางไปที่ /ดัชนี (ตามกฎข้อแรก)การตอบสนองการเปลี่ยนเส้นทางจะถูกส่งกลับไปยังไคลเอ็นต์
  4. ในคำขอที่สาม /ดัชนี ถูกเขียนใหม่เป็นการภายใน /index.php โดยการเขียนซ้ำครั้งล่าสุด เอ็นจิ้นการเขียนใหม่จึงเริ่มต้นใหม่...
  5. ไปที่ 3 (ติดอยู่ในวงจรการเปลี่ยนเส้นทางที่ไม่มีที่สิ้นสุด)

ใน ไดเรกทอรี บริบท (เช่น .htaccess) เอ็นจิ้นการเขียนใหม่ไม่ได้ทำเพียงแค่ผ่านสคริปต์เพียงครั้งเดียว มันวนซ้ำจนกว่า URL จะผ่านไปโดยไม่มีการเปลี่ยนแปลง (เว้นแต่คุณจะใช้ จบ แฟล็กบน Apache 2.4 หรือเกิดการเปลี่ยนเส้นทางภายนอก 3xx)

เปลี่ยนเพื่อเอาออก .html ใช้งานได้ดีเพราะคุณกำลังเขียนใหม่ /index.phpซึ่งไม่ลงท้ายด้วย .htmlดังนั้นคำสั่งเปลี่ยนเส้นทาง (ที่ลบ .html) ไม่ตรงกัน

ในการแก้ปัญหานี้ คุณต้องหลีกเลี่ยงการเปลี่ยนเส้นทางคำขอที่เขียนใหม่ คุณสามารถทำได้โดย:

  • ใช้ จบ ตั้งค่าสถานะ (Apache 2.4+) ในการเขียนซ้ำครั้งล่าสุด แทนที่จะเป็น แอล เพื่อป้องกันการวนซ้ำของเอ็นจิ้นการเขียนใหม่ แม้ว่าคุณควรหลีกเลี่ยงการเปลี่ยนคำสั่ง WordPress ของหุ้น (ดูด้านล่าง) ดังนั้นนี่อาจไม่ใช่ตัวเลือกที่ต้องการ สิ่งนี้ใช้ไม่ได้กับ Apache 2.2

  • หรือตรวจสอบสำหรับ .php ต่อ THE_REQUEST ตัวแปรเซิร์ฟเวอร์ (ซึ่งมีบรรทัดเริ่มต้นของส่วนหัวคำขอ HTTP และไม่เปลี่ยนแปลงเมื่อมีการเขียนคำขอใหม่) ตัวอย่างเช่น:

    # ลบส่วนขยาย ".php" ในคำขอ "โดยตรง" (ไม่เขียนซ้ำ) เท่านั้น
    RewriteCond %{THE_REQUEST} [A-Z]{3,7}\s/[^?]+\.php(?:\?|\s|$) [NC]
    RewriteRule (.+)\.php$ /$1 [R=301,L,NC]
    
  • หรือตรวจสอบที่ REDIRECT_STATUS ตัวแปรสภาพแวดล้อมซึ่งว่างเปล่าในคำขอเริ่มต้นและตั้งค่าเป็น 200 (เช่นเดียวกับสถานะ 200 OK HTTP) ในการเขียนซ้ำครั้งแรกที่สำเร็จ (ซึ่งง่ายกว่า regex ที่ค่อนข้างซับซ้อนด้านบน) ตัวอย่างเช่น:

    # ลบส่วนขยาย ".php" ในคำขอ "โดยตรง" (ไม่เขียนซ้ำ) เท่านั้น
    RewriteCond %{ENV:REDIRECT_STATUS} ^$
    RewriteRule (.+)\.php$ /$1 [R=301,L,NC]
    

อย่างไรก็ตาม คุณไม่ควรแก้ไขโค้ดภายใน # เริ่มต้น WordPress เนื่องจาก WordPress เองพยายามรักษาสิ่งนี้และอาจเขียนทับรหัสนี้ในภายหลัง กฎนี้จำเป็นต้องไป ก่อน เดอะ # เริ่มต้น WordPress เครื่องหมายความคิดเห็น คุณไม่จำเป็นต้องทำซ้ำ RewriteEngine เปิดอยู่ คำสั่งที่ปรากฏในภายหลังในไฟล์ (ในส่วน WordPress)

คุณจะต้องล้างแคชของเบราว์เซอร์ก่อนทำการทดสอบ เนื่องจากการเปลี่ยนเส้นทางที่ผิดพลาด (ถาวร) อาจถูกแคชโดยเบราว์เซอร์ ทดสอบครั้งแรกกับการเปลี่ยนเส้นทาง 301 (ชั่วคราว) เพื่อหลีกเลี่ยงปัญหาการแคช

อย่างไรก็ตามสิ่งนี้ไม่อนุญาตให้คุณเข้าถึง .php ไฟล์ที่ไม่มี .php การขยาย. เนื่องจาก URL ที่ไม่มีส่วนขยายจะต้องถูกเขียนใหม่ภายในกลับไปเป็น .php ไฟล์.

peter avatar
sa flag
ระหว่างคำขอแรก "/somepage.php" หลังจากประมวลผล "RewriteRule ^(.*)\.php$ "$1" [R=301,L,NC]" โปรแกรมเขียนใหม่จะเริ่มต้นใหม่หรือไม่เนื่องจาก URL ที่เขียนใหม่ "/ "somepage" ไม่เหมือนเดิม?
kz flag
@peter ในระหว่างการร้องขอครั้งแรก กลไกการเขียนซ้ำจะถูกยกเลิกทันทีเมื่อเปลี่ยนเส้นทาง มันจะไม่เริ่มต้นใหม่ ระหว่าง _second request_ เครื่องมือเขียนใหม่ "เริ่มต้นใหม่" เนื่องจาก URL ที่เขียนใหม่ `/index.php` ไม่เหมือนกับของเดิม (`/somepage`)ใช่ เครื่องมือเขียนใหม่ "เริ่มต้นใหม่" เนื่องจาก URL มีการเปลี่ยนแปลงในระหว่างกระบวนการเขียนใหม่
peter avatar
sa flag
แล้วฉันจะบอกได้อย่างไรว่าเอ็นจิ้นเขียนใหม่จะเริ่มต้นใหม่หรือไม่? คำขอทั้งสองเขียน URL ใหม่เป็นรายการอื่น ทำไมคำขอที่สองทำให้เกิดการเริ่มต้นใหม่ แต่คำขอแรกไม่เป็นเช่นนั้น
kz flag
@peter หากมีการตั้งค่ารหัสตอบกลับ 3xx (เปลี่ยนเส้นทางภายนอก) เมื่อสิ้นสุดการส่งผ่านปัจจุบันผ่านเอ็นจิ้นการเขียนซ้ำ เอ็นจิ้นการเขียนซ้ำจะยุติลงและเกิดการเปลี่ยนเส้นทาง จะไม่มีการส่งผ่านเพิ่มเติมผ่านเอ็นจิ้นการเขียนซ้ำในกรณีนี้ ในข้างต้น กระบวนการเขียนใหม่จะถูกยกเลิกโดยการเปลี่ยนเส้นทางเสมอ หากไม่มี "การเปลี่ยนเส้นทาง" (เช่น ลบแฟล็ก `R` ออกจากกฎข้อแรก) ก็จะส่งผลให้เกิดการวนซ้ำภายใน (500 Internal Server Error ที่ตอบกลับไปยังไคลเอ็นต์)
kz flag
เพื่อชี้แจงว่า "การเปลี่ยนเส้นทางเกิดขึ้น" ฉันหมายถึงการตอบสนองการเปลี่ยนเส้นทาง 3xx ถูกส่งกลับไปยังไคลเอนต์
kz flag
@peter ฉันได้อัปเดตคำตอบเพื่อหวังว่าจะชี้แจงบางประเด็น (เกี่ยวกับการเปลี่ยนเส้นทาง) และเพิ่มตัวอย่างที่ใช้ `THE_REQUEST` เพื่อป้องกันการวนรอบการเปลี่ยนเส้นทาง แม้ว่าฉันยังคงคิดว่าตัวอย่างที่ฉันโพสต์ในตอนแรก (โดยใช้ `REDIRECT_STATUS` env var) เป็นโซลูชันที่ต้องการ/สะอาดที่สุดในไซต์ WordPress นี้
peter avatar
sa flag
คำตอบของคุณมีรายละเอียดมาก ชัดเจน และเป็นประโยชน์ ยอดเยี่ยม! ขอบคุณมาก!

โพสต์คำตอบ

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