RewriteMap ภายใน RewriteCond ไม่ทำงาน (Apache)
ฉันมีข้อมูลRewriteCondที่ตรวจสอบว่า{QUERY_STRING}มีหมายเลขเวอร์ชันที่ถูกต้องหรือไม่หากไม่ได้เปลี่ยนเส้นทางผู้ใช้ไปยังเวอร์ชันที่ถูกต้อง
ตัวอย่างเช่นหาก v0.7 เป็นเวอร์ชันล่าสุดผู้ใช้ที่เข้าถึงhttp://localhost/?v=0.5ควรถูกเปลี่ยนเส้นทางไปยังhttp://localhost/?v=0.7แต่ด้วยเหตุผลบางประการหากใช้งานRewriteMapในเงื่อนไขจะไม่ทำงาน ...
นี้ได้ผล
RewriteMap versions txt:/var/www/html/version.txt
RewriteCond "%{QUERY_STRING}" !^v=0.7
RewriteRule "^/$" "/?v=${versions:version}" [R,L]
สิ่งนี้ไม่
RewriteMap versions txt:/var/www/html/version.txt
RewriteCond "%{QUERY_STRING}" !^v=${versions:version} RewriteRule "^/$" "/?v=${versions:version}" [R,L]
เนื้อหาของ version.txt
##
## version.txt -- rewriting map
## The version number written here will be mapped to the URL
##
##
version 0.7
คำตอบ
RewriteCond "%{QUERY_STRING}" !^v=${versions:version}
สิ่งนี้ใช้ไม่ได้เนื่องจากCondPattern (อาร์กิวเมนต์ที่ 2 ของRewriteCondคำสั่ง) เป็นนิพจน์ทั่วไปและไม่สนับสนุนการขยายตัวแปร (เช่นเดียวกับที่คุณไม่สามารถใช้ backreferences ของฟอร์ม$nหรือ%nหรือตัวแปรเซิร์ฟเวอร์%(SERVER_VAR}หรือ env vars %{ENV:MY_ENV_VAR}เป็นต้น) มิฉะนั้นจะขัดแย้งกับไวยากรณ์ PCRE regex เฉพาะTestString (อาร์กิวเมนต์แรกของRewriteCondคำสั่ง) และอาร์กิวเมนต์การRewriteRule แทนที่เท่านั้นที่สนับสนุนการขยายตัวแปรเนื่องจากอาร์กิวเมนต์เหล่านี้เป็นสตริง "ปกติ" ไม่ใช่ regex
อย่างไรก็ตามคุณยังสามารถทำสิ่งที่คุณต้องการได้และตรวจสอบว่าหมายเลขเวอร์ชันที่ถูกต้องตามที่ส่งคืนมาRewriteMapนั้นมีอยู่ที่จุดเริ่มต้นของสตริงการสืบค้น ให้ขยายผลลัพธ์ของRewriteMapในTestString (ซึ่งรองรับการขยายตัวแปรเนื่องจากเป็นสตริง "ธรรมดา" ไม่ใช่ regex) และเปรียบเทียบสิ่งนี้โดยใช้ backreference ภายใน
ตัวอย่างเช่นเปลี่ยนเป็นRewriteCondอ่าน:
RewriteCond %{QUERY_STRING}@${versions:version} !^v=([\d.]+)(?:&[^@]*)?@\1
หลังจากที่ขยายตัวตัวแปรเราจบลงที่ตรงกับสตริงของรูปแบบ[email protected]กับ ^v=([\d.]+)(?:&.*)?@\1regex \1คือการอ้างอิงภายในของรูปแบบย่อยแรกที่จับได้ (เช่นค่าของvพารามิเตอร์ URL) ดังนั้นสิ่งนี้จึงจับคู่ค่าพารามิเตอร์ URL อย่างมีประสิทธิภาพกับค่าที่ส่งคืนจากไฟล์RewriteMap. จากนั้นนิพจน์ทั้งหมดนี้จะถูกลบ ( !คำนำหน้า) ดังนั้นจึงประสบความสำเร็จเมื่อเงื่อนไขไม่ตรงกันกล่าวคือ หมายเลขเวอร์ชันแตกต่างกัน
([\d.]+)- จับคู่หมายเลขเวอร์ชันในสตริงข้อความค้นหาซึ่งประกอบด้วยตัวเลข 1 ตัวขึ้นไปหรือจุดตามตัวอักษร เช่น.0.5
(?:&.*)? - จับคู่ส่วนที่เหลือของสตริงการสืบค้น (ถ้ามี)
@ เป็นเพียงสตริงที่กำหนดเองซึ่งไม่ได้เกิดขึ้นในสตริงการสืบค้นหรือสตริง "เวอร์ชัน"
คุณไม่จำเป็นต้องล้อมรอบอาร์กิวเมนต์ในเครื่องหมายอัญประกาศคู่เว้นแต่ว่าจะมีช่องว่าง (แม้ว่าคุณจะสามารถแบ็กสแลชหนีช่องว่างแทนได้) ดังนั้นคำพูดคู่จึงเป็นทางเลือกทั้งหมดในตัวอย่างนี้ เช่นเดียวกับRewriteRuleคำสั่ง