ฉันมีเว็บไซต์ที่มี nginx ที่ส่งคืน index.html (แอปตอบกลับหน้าเดียว) สำหรับคำขอเกือบทั้งหมดคำขอใด ๆ สำหรับเกือบทุกเส้นทาง (เช่น /some/บทความ
) ก็จะกลับมาเช่นกัน index.html
และแอป react (react router) จะแปลพาธเป็นการเรียก API นี่คือวิธีการทำงาน และไม่สามารถเปลี่ยนแปลงได้ (เว็บไซต์มีขนาดใหญ่ ใช้งานมากเกินไป และฉันก็อยู่ในฐานะที่จะเปลี่ยนแปลงไม่ได้อยู่ดี)
ควรมีข้อยกเว้นสองประการสำหรับคำขอเหล่านี้:
- คำขอทั้งหมดที่เริ่มต้นด้วยเส้นทาง /api/* จะถูกส่งผ่านไปยังอัพสตรีม (เซิร์ฟเวอร์แอปพลิเคชัน) ดังนั้นแบ็กเอนด์อื่นจะจัดการคำขอ API จริงทั้งหมด
- ข้อยกเว้นอื่นควรเป็น facebook ภายนอกฮิต มีจุดสิ้นสุดที่แตกต่างกันภายใต้ /api/open_graph บนแอปพลิเคชันเซิร์ฟเวอร์สำหรับสิ่งนั้น เช่น. /api/open_graph ควรวางไว้ข้างหน้าเส้นทางเดิม จุดสิ้นสุดนั้นส่งคืนเนื้อหาจริง (และไม่ใช่แอปตอบโต้หน้าเดียวทั่วไปที่ไม่มีเนื้อหาจริง) รูปแบบก็แตกต่างกันเช่นกัน การเรียก API ปกติมักจะส่งคืนข้อมูล JSON แต่ปลายทาง open_graph ส่งคืน HTML แบบง่าย
ตัวอย่างการกำหนดค่า nginx:
ต้นน้ำ www {
# ...
}
เซิร์ฟเวอร์ {
# ...
# ใช้ /api/open_graph บนอัปสตรีมสำหรับ facebook ภายนอกฮิต
ถ้า ($http_user_agent ~* "^facebookexternalhit.*$") {
เขียนใหม่ ^/(.*)$ /api/open_graph/$1 ถาวร;
}
# คำขอ API จะไปที่อัปสตรีม
ตำแหน่ง ~ ^/api/ {
proxy_pass http://www;
proxy_read_timeout 90;
proxy_redirect http://www https://example.com;
}
# คำขออื่น ๆ ทั้งหมดใช้แอปตอบสนอง
# react เราเตอร์จัดการคำขอเพิ่มเติมทั้งหมด
ที่ตั้ง / {
ดัชนี index.html;
error_page 404 =200 /index.html;
}
}
การกำหนดค่าด้านบนทำงานดังนี้:
# curl -A "facebookexternalhit" -s -D - -o /dev/null https://example.com/article1
HTTP/1.1 301 ย้ายอย่างถาวร
เซิร์ฟเวอร์: nginx
วันที่: วันพุธที่ 20 ตุลาคม 2021 08:14:13 GMT
ประเภทเนื้อหา: text/html
ความยาวเนื้อหา: 162
ที่ตั้ง: https://example.com/api/open_graph/article1
การเชื่อมต่อ: มีชีวิตอยู่
เข้มงวด-การขนส่ง-ความปลอดภัย: max-age=31536000
X-Content-Type-Options: ไร้สาระ
X-XSS-การป้องกัน: 1; โหมด = บล็อก
ตัวเลือก X-Frame: SAMEORIGIN
เกือบดีแล้ว ยกเว้นว่ากราฟ API ของ Facebook ไม่รองรับการเปลี่ยนเส้นทาง (ใครจะรู้ว่าทำไม?) ดังนั้นแทนที่จะเปลี่ยนเส้นทางไปที่ /api/open_graph/*
เซิร์ฟเวอร์ควรเชื่อมต่ออัปสตรีมโดยตรงและส่งต่อคำขอ
แต่ไม่รู้เป็นไง? ทางออกที่ไร้เดียงสาจะเป็น:
# ใช้ /api/open_graph บนอัปสตรีมสำหรับ facebook ภายนอกฮิต
ถ้า ($http_user_agent ~* "^facebookexternalhit.*$") {
เขียนใหม่ ^/(.*)$ /api/open_graph/$1 ถาวร;
proxy_pass http://www;
proxy_read_timeout 90;
proxy_redirect http://www https://example.com;
}
แต่มันไม่ได้ผลเพราะ proxy_pass
ใช้ได้เฉพาะภายในก ที่ตั้ง
. ไม่สามารถใช้ภายใน ถ้า
. ถ้าฉันลองกำหนดค่านั้น ฉันจะได้รับ:
nginx: [emerg] ไม่อนุญาตให้ใช้คำสั่ง "proxy_pass" ใน /etc/nginx/sites-enabled/example-www:62
nginx: การทดสอบไฟล์การกำหนดค่า /etc/nginx/nginx.conf ล้มเหลว
ฉันอาจเปลี่ยนรหัสโปรแกรมในอัปสตรีมได้ (เช่น เพิ่มตัวกรองสำหรับตัวแทนผู้ใช้ที่นั่น) แต่มันคงค่อนข้างยาก
มีวิธีแก้ปัญหาสำหรับสิ่งนี้ใน nginx หรือไม่
คำถามนี้เกี่ยวข้องกับ: nginx - proxy_pass บน user_agent แต่นั่นก็ไม่ได้ผลสำหรับฉันเช่นกัน (เกิดข้อผิดพลาด)