S3 เว็บไซต์คงที่โฮสต์เส้นทางทั้งหมดเส้นทางไปยัง Index.html


250

ฉันใช้ S3 เพื่อโฮสต์แอป javascript ที่จะใช้ HTML5 pushStates ปัญหาคือถ้าผู้ใช้บุ๊กมาร์ก URL ใด ๆ ก็จะไม่สามารถแก้ไขอะไรได้ สิ่งที่ฉันต้องการคือความสามารถในการรับคำขอ url ทั้งหมดและแสดงรูต index.html ในที่ฝากข้อมูล S3 ของฉันแทนที่จะเปลี่ยนเส้นทางเต็มรูปแบบ จากนั้นแอปพลิเคชันจาวาสคริปต์ของฉันสามารถแยก URL และแสดงหน้าเว็บที่เหมาะสม

มีวิธีใดที่จะบอกให้ S3 ให้บริการ index.html สำหรับคำขอ URL ทั้งหมดแทนที่จะทำการเปลี่ยนเส้นทาง? นี้จะคล้ายกับการตั้งค่า Apache เพื่อจัดการการร้องขอเข้ามาทั้งหมดโดยการให้บริการขึ้น index.html เดียวในตัวอย่างนี้: https://stackoverflow.com/a/10647521/1762614 ฉันต้องการหลีกเลี่ยงการเรียกใช้เว็บเซิร์ฟเวอร์เพียงเพื่อจัดการเส้นทางเหล่านี้ การทำทุกอย่างจาก S3 นั้นน่าสนใจมาก


คุณพบวิธีแก้ปัญหานี้หรือไม่?
w2lame

คำตอบ:


302

มันง่ายมากที่จะแก้ปัญหาโดยไม่ต้องแฮ็ค url ด้วยความช่วยเหลือของ CloudFront

  • สร้างที่ฝากข้อมูล S3 ตัวอย่างเช่น: ตอบสนอง
  • สร้างการกระจาย CloudFront ด้วยการตั้งค่าเหล่านี้:
    • วัตถุรูทเริ่มต้น : index.html
    • ชื่อโดเมนต้นทาง : โดเมนที่ฝากข้อมูล S3 ตัวอย่างเช่น: react.s3.amazonaws.com
  • ไปที่แท็บหน้าผิดพลาดคลิกที่สร้างการตอบสนองข้อผิดพลาดที่กำหนดเอง :
    • รหัสข้อผิดพลาด HTTP : 403: ต้องห้าม (404: ไม่พบในกรณีของเว็บไซต์ S3 แบบคงที่)
    • ปรับแต่งการตอบสนองข้อผิดพลาด : ใช่
    • เส้นทางหน้าการตอบสนอง : /index.html
    • HTTP Response Code : 200: ตกลง
    • คลิกที่สร้าง

8
ขอบคุณ คำตอบที่ดีที่สุด
jgb

และสิ่งที่ไม่ชัดเจนคือคุณเก็บตำแหน่งไว้เพื่อให้คุณสามารถกำหนดเส้นทาง "ธรรมชาติ" ได้
Lukasz Marek Sielski

5
สิ่งนี้ทำงานเหมือนมีเสน่ห์สำหรับฉันเฉพาะรหัสข้อผิดพลาดที่กำหนดเองที่ฉันต้องการคือ 404 ไม่ใช่ 403
Jeremy S.

4
บิตของการแฮ็ก แต่ใช้งานได้ดี :) มันคงจะดีถ้า CloudFront ให้เราแมปช่วงของพา ธ ไปยังไฟล์ S3 (โดยไม่มีการเปลี่ยนเส้นทาง)
บ๊อบ

3
มันไม่ทำงานสำหรับฉัน การแก้ปัญหานี้มักจะเปลี่ยนเส้นทางไปยังหน้าบ้านและไม่ถูกต้อง ... หน้า
จิม

201

วิธีที่ฉันสามารถทำให้งานนี้มีดังนี้:

ในส่วนแก้ไขกฎการเปลี่ยนเส้นทางของคอนโซล S3 สำหรับโดเมนของคุณเพิ่มกฎต่อไปนี้:

<RoutingRules>
  <RoutingRule>
    <Condition>
      <HttpErrorCodeReturnedEquals>404</HttpErrorCodeReturnedEquals>
    </Condition>
    <Redirect>
      <HostName>yourdomainname.com</HostName>
      <ReplaceKeyPrefixWith>#!/</ReplaceKeyPrefixWith>
    </Redirect>
  </RoutingRule>
</RoutingRules>

การดำเนินการนี้จะเปลี่ยนเส้นทางทุกเส้นทางที่ทำให้ไม่พบ 404 ไปยังโดเมนรูทของคุณด้วยเส้นทางรุ่นแฮช - แบง ดังนั้นhttp://yourdomainname.com/postsจะเปลี่ยนเส้นทางไปที่http://yourdomainname.com/#!/postsหากไม่มีไฟล์ที่ / โพสต์

ในการใช้ HTML5 pushStates เราต้องดำเนินการตามคำขอนี้และสร้าง pushState ที่เหมาะสมด้วยตนเองตามเส้นทางของแฮช - โครม ดังนั้นให้เพิ่มส่วนนี้ลงในไฟล์ index.html ของคุณ:

<script>
  history.pushState({}, "entry page", location.hash.substring(1));
</script>

นี่จะเป็นการแฮชและเปลี่ยนเป็น HTML5 pushState จากจุดนี้คุณสามารถใช้ pushStates เพื่อให้มีเส้นทางที่ไม่ใช่แฮชแบงในแอป


4
วิธีนี้ใช้งานได้ดี! ในความเป็นจริง angularjs จะทำ pushState ประวัติโดยอัตโนมัติหากมีการกำหนดค่าโหมด html
wcandillon

1
สิ่งนี้จะล้มเหลวเมื่อใช้ IE เวอร์ชันเก่ากว่าถ้าคุณมี GET params รวมอยู่ใน URL ของคุณถูกต้องไหม คุณจะแก้ไขปัญหานี้ได้อย่างไร
clexmond

3
ขอบคุณ! มันใช้งานได้ดีสำหรับฉันบนกระดูกสันหลังด้วยการบิดเล็กน้อย ฉันเพิ่มในการตรวจสอบเบราว์เซอร์รุ่นเก่า: <script language="javascript"> if (typeof(window.history.pushState) == 'function') { window.history.pushState(null, "Site Name", window.location.hash.substring(2)); } else { window.location.hash = window.location.hash.substring(2); } </script>
AE Grey

10
ประสบความสำเร็จกับreact-routerโซลูชันนั้นโดยใช้ HTML5 pushStates และ<ReplaceKeyPrefixWith>#/</ReplaceKeyPrefixWith>
Felix D.

5
มันไม่ทำงานในซาฟารีและเป็นปัญหาใหญ่กับกลยุทธ์การปรับใช้ การเขียน js ขนาดเล็กเพื่อเปลี่ยนเส้นทางเป็นวิธีโทรม นอกจากนี้จำนวนการเปลี่ยนเส้นทางก็เป็นปัญหาเช่นกัน ฉันพยายามคิดว่ามีวิธีใดที่ URL S3 ทั้งหมดจะชี้ไปที่ index.html เสมอ
moha297

129

มีปัญหาเล็กน้อยกับแนวทางแบบ S3 / Redirect ที่กล่าวถึงโดยผู้อื่น

  1. การเปลี่ยนเส้นทาง Mutliple เกิดขึ้นเมื่อเส้นทางของแอปของคุณได้รับการแก้ไข ตัวอย่างเช่น: www.myapp.com/path/for/test รับการเปลี่ยนเส้นทางเป็น www.myapp.com/#/path/for/test
  2. มีการสั่นไหวในแถบ URL เนื่องจาก '#' มาและไปเนื่องจากการกระทำของกรอบ SPA ของคุณ
  3. seo ได้รับผลกระทบเพราะ - เฮ้! google บังคับให้เขาต้องเปลี่ยนเส้นทาง '
  4. การสนับสนุน Safari สำหรับแอปของคุณจะเป็นการโยน

ทางออกคือ:

  1. ตรวจสอบให้แน่ใจว่าคุณกำหนดเส้นทางดัชนีสำหรับเว็บไซต์ของคุณ ส่วนใหญ่เป็น index.html
  2. ลบกฎการกำหนดเส้นทางออกจากการกำหนดค่า S3
  3. วาง Cloudfront ไว้ข้างหน้า S3 bucket ของคุณ
  4. กำหนดค่ากฎหน้าข้อผิดพลาดสำหรับอินสแตนซ์ Cloudfront ของคุณ ในกฎข้อผิดพลาดระบุ:

    • รหัสข้อผิดพลาด Http: 404 (และ 403 หรือข้อผิดพลาดอื่น ๆ ตามต้องการ)
    • เกิดข้อผิดพลาดในการแคช TTL ขั้นต่ำ (วินาที): 0
    • กำหนดค่าการตอบกลับ: ใช่
    • เส้นทางหน้าการตอบสนอง: /index.html
    • รหัสตอบกลับ HTTP: 200

      1. สำหรับ SEO ที่ต้องการ + ตรวจสอบให้แน่ใจว่า index.html ของคุณไม่ได้แคชให้ทำดังนี้:
    • กำหนดค่าอินสแตนซ์ EC2 และตั้งค่าเซิร์ฟเวอร์ nginx

    • กำหนด IP สาธารณะให้กับอินสแตนซ์ EC2 ของคุณ
    • สร้าง ELB ที่มีอินสแตนซ์ EC2 ที่คุณสร้างเป็นอินสแตนซ์
    • คุณควรกำหนด ELB ให้กับ DNS ของคุณ
    • ตอนนี้กำหนดค่าเซิร์ฟเวอร์ nginx ของคุณให้ทำสิ่งต่อไปนี้: Proxy_pass คำขอทั้งหมดไปยัง CDN ของคุณ (สำหรับ index.html เท่านั้นให้บริการสินทรัพย์อื่น ๆ โดยตรงจาก cloudfront ของคุณ) และสำหรับบอตค้นหาเปลี่ยนเส้นทางการรับส่งข้อมูลตามบริการที่กำหนดเช่น Prerender.io

ฉันสามารถช่วยในรายละเอียดเพิ่มเติมเกี่ยวกับการตั้งค่า nginx เพียงออกจากบันทึก ได้เรียนรู้มันอย่างหนักหน่วง

เมื่อมีการอัพเดทการกระจายของคลาวด์ ทำให้แคช Cloudfront ของคุณไม่ถูกต้องหนึ่งครั้งเพื่ออยู่ในโหมดที่เก่าแก่ กด url ในเบราว์เซอร์และควรจะดี


6
ตั้งแต่ S3 ตอบกลับด้วยสิ่งต้องห้าม 403 เมื่อไฟล์ไม่มีอยู่ฉันคิดว่าขั้นตอนที่ 4 ข้างต้นจะต้องมีการทำซ้ำสำหรับรหัสข้อผิดพลาด Http 403 เช่นกัน
Andreas

4
สำหรับฉันนี่เป็นคำตอบเดียวที่ส่งผลให้เกิดพฤติกรรมที่ยอมรับได้
mabe.berlin

1
@ moha297 ในจุดที่ 5 คุณทำการกำหนดค่าเว็บไซต์ของคุณเพื่อดึงข้อมูลจาก nginx ซึ่งเป็นผู้รับมอบฉันทะจาก CDN (ยกเว้นสำหรับ index.html และคำขอรวบรวมข้อมูล) หรือไม่ หากเป็นเช่นนั้นคุณจะไม่เสียประโยชน์จากเซิร์ฟเวอร์ขอบ CDN หรือไม่
ราหุลปาเทล

2
@ moha297 คุณช่วยอธิบายความคิดเห็นนี้ได้: "คุณไม่ควรให้บริการ index.html จาก CDN" ฉันไม่เห็นปัญหาในการแสดง index.html จาก S3 ด้วย CloudFront
Carl G

1
ดูstackoverflow.com/a/10622078/4185989สำหรับข้อมูลเพิ่มเติมเกี่ยวกับวิธีการที่ TTL เป็น 0 (รุ่นสั้น: มันถูกแคชโดย Cloudfront แต่If-Modified-Sinceคำขอ GET ถูกส่งไปยังจุดเริ่มต้น) - อาจเป็นประโยชน์สำหรับผู้ที่ไม่ต้องการ เพื่อตั้งค่าเซิร์ฟเวอร์เช่นในขั้นตอนที่ 5
jmq

18

มันเป็นเรื่องเกี่ยวกับวง แต่นี่เป็นคำแนะนำสำหรับผู้ที่ใช้ห้องสมุด React Router ของ Rackt ที่ มีประวัติเบราว์เซอร์ (HTML5) ที่ต้องการโฮสต์บน S3

สมมติว่าผู้ใช้เข้าชม/foo/bearเว็บไซต์แบบโฮสต์ S3 ของคุณ ได้รับของดาวิด ข้อเสนอแนะก่อนหน้านี้/#/foo/bearกฎการเปลี่ยนเส้นทางจะส่งพวกเขาไป หากแอปพลิเคชันของคุณสร้างขึ้นโดยใช้ประวัติเบราว์เซอร์สิ่งนี้จะทำได้ไม่ดีนัก อย่างไรก็ตามแอปพลิเคชันของคุณถูกโหลด ณ จุดนี้และสามารถจัดการประวัติได้

รวมถึงประวัติ Rackt ในโครงการของเรา (ดูเพิ่มเติมที่การใช้ประวัติที่กำหนดเองจากโครงการ React Router) คุณสามารถเพิ่มผู้ฟังที่ทราบเส้นทางแฮชประวัติและแทนที่เส้นทางตามความเหมาะสมดังที่แสดงในตัวอย่างนี้:

import ReactDOM from 'react-dom';

/* Application-specific details. */
const route = {};

import { Router, useRouterHistory } from 'react-router';
import { createHistory } from 'history';

const history = useRouterHistory(createHistory)();

history.listen(function (location) {
  const path = (/#(\/.*)$/.exec(location.hash) || [])[1];
  if (path) history.replace(path);
});

ReactDOM.render(
  <Router history={history} routes={route}/>,
  document.body.appendChild(document.createElement('div'))
);

วิธีการสรุป:

  1. กฎการเปลี่ยนเส้นทางของดาวิด S3 จะนำไป/foo/bear/#/foo/bear
  2. ใบสมัครของคุณจะโหลด
  3. ฟังประวัติจะตรวจจับ#/foo/bearสัญกรณ์ประวัติ
  4. และแทนที่ประวัติด้วยเส้นทางที่ถูกต้อง

Linkแท็กจะทำงานได้ตามที่คาดหวังเช่นเดียวกับฟังก์ชั่นประวัติเบราว์เซอร์อื่น ๆ ทั้งหมด ข้อเสียเดียวที่ฉันสังเกตเห็นคือการเปลี่ยนเส้นทางคั่นระหว่างหน้าที่เกิดขึ้นกับคำขอเริ่มต้น

สิ่งนี้ได้รับแรงบันดาลใจจากวิธีแก้ปัญหาสำหรับ AngularJSและฉันสงสัยว่าสามารถปรับใช้กับแอปพลิเคชันใด ๆ


2
สิ่งนี้ช่วยฉันไมเคิลขอบคุณ! คุณอาจต้องการเปลี่ยนการอ้างอิงจากประวัติและเพียงแค่ใช้ BrowserHistory iebrowserHistory.listen
Marshall Moutenot

ยินดีต้อนรับคุณ! ดีใจที่ได้ช่วยเหลือ นอกจากนี้เห็นด้วยและสำหรับกรณีการใช้งานเฉพาะนี้ฉันได้อัปเดตข้อมูลโค้ดเพื่อแก้ไขคำเตือนการคัดค้านจาก React Router
Michael Ahlers

ด้วยการเปิดตัว react-router v3.0.0 สิ่งนี้ไม่ทำงานเนื่องจาก react-router v3.0.0 ใช้ History v3.0.0
Varand Pezeshkian

ความคิดใด ๆ วิธีการป้องกัน history.listen วงวนการโทรไม่สิ้นสุด? เกิดจากการเปลี่ยนเส้นทางฉันเดา
Mirko Flyktman

14

ฉันเห็นวิธีแก้ปัญหา 4 ข้อสำหรับปัญหานี้ 3 คำถามแรกนั้นได้รับการกล่าวถึงแล้วและสุดท้ายคือคำตอบของฉัน

  1. ตั้งค่าเอกสารข้อผิดพลาดเป็น index.html
    ปัญหา : เนื้อหาการตอบสนองจะถูกต้อง แต่รหัสสถานะจะเป็น 404 ซึ่งทำให้ SEO เสียหาย

  2. ตั้งกฎการเปลี่ยนเส้นทาง
    ปัญหา : URL ที่ปนเปื้อนด้วย#!และหน้ากะพริบเมื่อโหลด

  3. กำหนดค่า CloudFront
    ปัญหา : หน้าทั้งหมดจะคืนค่า 404 จากจุดเริ่มต้นดังนั้นคุณต้องเลือกว่าคุณจะไม่แคชอะไร (TTL 0 ตามที่แนะนำ) หรือถ้าคุณจะแคชและมีปัญหาเมื่อทำการอัพเดตเว็บไซต์

  4. แสดงผลล่วงหน้าทุกหน้า
    ปัญหา : งานเพิ่มเติมในการแสดงหน้าล่วงหน้าโดยเฉพาะอย่างยิ่งเมื่อหน้าเปลี่ยนบ่อย ตัวอย่างเช่นเว็บไซต์ข่าว

ข้อเสนอแนะของฉันคือการใช้ตัวเลือก 4 หากคุณแสดงหน้าทุกหน้าล่วงหน้าจะไม่มีข้อผิดพลาด 404 สำหรับหน้าเว็บที่คาดหวัง หน้าจะโหลดได้ดีและกรอบงานจะควบคุมและดำเนินการตามปกติเป็นสปา คุณยังสามารถตั้งค่าเอกสารข้อผิดพลาดเพื่อแสดงหน้า error.html ทั่วไปและกฎการเปลี่ยนเส้นทางเพื่อเปลี่ยนเส้นทางข้อผิดพลาด 404 ไปยังหน้า 404.html (โดยไม่ต้องใช้ hashbang)

เกี่ยวกับข้อผิดพลาดที่ต้องห้าม 403 ฉันจะไม่ปล่อยให้พวกเขาเกิดขึ้นเลย ในแอปพลิเคชันของฉันฉันพิจารณาว่าไฟล์ทั้งหมดในที่ฝากข้อมูลโฮสต์เป็นสาธารณะและฉันตั้งค่านี้พร้อมตัวเลือกทุกคนที่ได้รับอนุญาตให้อ่าน หากเว็บไซต์ของคุณมีหน้าเว็บที่เป็นส่วนตัวการให้ผู้ใช้ดูเค้าโครง HTML ไม่ควรเป็นปัญหา สิ่งที่คุณต้องปกป้องคือข้อมูลและสิ่งนี้จะทำในแบ็กเอนด์

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


1
และไซต์ของคุณมีตัวอย่างที่ยอดเยี่ยมในการใช้การแสดงผลล่วงหน้าสำหรับทุกหน้า zanon.io/posts/ ...... .- ขอบคุณ
frekele

วิธีที่สี่นี้ระบุผู้ใช้ที่โหลด URL pushState หรือไม่ มันจัดการการนำทางได้ดี แต่ในการรีโหลดมันจะยังไปถึงเซิร์ฟเวอร์
อัลฟ่า

@ อัลฟ่าฉันไม่แน่ใจว่าฉันเข้าใจคำถามของคุณถูกต้องหรือไม่ แต่ในการรีโหลดมันจะทำหน้าที่เป็นคำขอใหม่ S3 จะได้รับการร้องขอและกลับสู่หน้าที่แสดงผลอีกครั้ง ไม่มีเซิร์ฟเวอร์ในกรณีนี้
Zanon

@Zanon Ah ฉันคิดว่าฉันเข้าใจ ฉันคิดว่ามันหมายถึงการแคชเพจที่แสดงผลล่วงหน้าและหลีกเลี่ยงการใช้ทรัพยากรที่ไม่มีอยู่จริงของ S3 นี่จะทิ้งเส้นทางที่มีองค์ประกอบแบบไดนามิกใช่ไหม
อัลฟ่า

1
@Zanon ในที่สุดฉันก็เข้าใจ - ขอบคุณ! ใช่นั่นคือสิ่งที่ฉันหมายถึง :)
อัลฟ่า

13

วันนี้ฉันพบปัญหาเดียวกัน แต่วิธีการแก้ปัญหาของ @ Mark-Nutter ไม่สมบูรณ์เพื่อลบ hashbang ออกจากแอปพลิเคชันเชิงมุมของฉัน

ในความเป็นจริงคุณต้องไปที่แก้ไขการอนุญาตคลิกที่เพิ่มการอนุญาตแล้วเพิ่มรายการที่ถูกต้องในที่เก็บข้อมูลของคุณให้ทุกคน ด้วยการกำหนดค่านี้ทำให้ AWS S3 สามารถกลับสู่ข้อผิดพลาด 404 จากนั้นกฎการเปลี่ยนเส้นทางจะตรวจจับกรณีและปัญหาได้อย่างถูกต้อง

เช่นนี้ ป้อนคำอธิบายรูปภาพที่นี่

จากนั้นคุณสามารถไปที่แก้ไขกฎการเปลี่ยนเส้นทางและเพิ่มกฎนี้:

<RoutingRules>
    <RoutingRule>
        <Condition>
            <HttpErrorCodeReturnedEquals>404</HttpErrorCodeReturnedEquals>
        </Condition>
        <Redirect>
            <HostName>subdomain.domain.fr</HostName>
            <ReplaceKeyPrefixWith>#!/</ReplaceKeyPrefixWith>
        </Redirect>
    </RoutingRule>
</RoutingRules>

ที่นี่คุณสามารถแทนที่HostName subdomain.domain.fr ด้วยโดเมนของคุณและKeyPrefix #! / หากคุณไม่ได้ใช้วิธี hashbang เพื่อการทำ SEO

แน่นอนว่าทั้งหมดนี้จะใช้งานได้หากคุณมี html5mode ตั้งค่าอยู่แล้วในแอปพลิเคชันเชิงมุมของคุณ

$locationProvider.html5Mode(true).hashPrefix('!');

ปัญหาเดียวของฉันคือคุณมีแฟลช hashbang ซึ่งคุณไม่มีอะไรเหมือนกฎ nginx ผู้ใช้อยู่ในหน้าและรีเฟรช: / products / 1 -> #! / products / 1 -> / products / 1
Intellix

1
ฉันคิดว่าคุณควรเพิ่มกฎสำหรับข้อผิดพลาด 403 แทนที่จะให้สิทธิ์รายการทุกคน
Hamish Moffatt

11

ทางออกที่ง่ายที่สุดในการทำให้แอปพลิเคชัน Angular 2+ ให้บริการจาก Amazon S3 และ URL โดยตรงทำงานได้คือการระบุ index.html ทั้งเป็นดัชนีและเอกสารข้อผิดพลาดในการกำหนดค่า S3 bucket

ป้อนคำอธิบายรูปภาพที่นี่


11
นี่คือคำตอบเดียวกันของคำตอบนี้ downvoted อย่างหนัก มันใช้งานได้ดี แต่สำหรับbodyการตอบกลับเท่านั้น รหัสสถานะจะ 404 และจะทำให้ SEO เสียหาย
Zanon

เพราะวิธีนี้ใช้ได้ผลbodyถ้าคุณมีสคริปต์ใด ๆ ที่คุณนำเข้าheadพวกเขาจะไม่ทำงานเมื่อคุณกดเส้นทางย่อยใด ๆ ในเว็บไซต์ของคุณโดยตรง
Mohamed Hajr

4

เนื่องจากปัญหายังคงมีฉันแม้ว่าฉันจะโยนในทางออกอื่น กรณีของฉันคือฉันต้องการปรับใช้คำขอดึงทั้งหมดกับ s3 โดยอัตโนมัติเพื่อทำการทดสอบก่อนที่จะรวมเข้ากับ [mydomain] / pull-ร้องขอ / [หมายเลข pr] /
(เช่น www.example.com/pull-requests/822/) )

ตามความรู้ที่ดีที่สุดของฉันที่ไม่ใช่กฎของ s3 จะอนุญาตให้มีหลายโครงการในที่เก็บข้อมูลเดียวโดยใช้การกำหนดเส้นทาง html5 ดังนั้นในขณะที่ข้อเสนอแนะที่โหวตส่วนใหญ่ทำงานในโครงการในโฟลเดอร์รูทมันไม่ได้มีหลายโครงการในโฟลเดอร์ย่อยของตนเอง

ดังนั้นฉันจึงชี้โดเมนของฉันไปที่เซิร์ฟเวอร์ของฉันซึ่งการตั้งค่า nginx ที่ตามมาทำงานได้

location /pull-requests/ {
    try_files $uri @get_files;
}
location @get_files {
    rewrite ^\/pull-requests\/(.*) /$1 break;
    proxy_pass http://<your-amazon-bucket-url>;
    proxy_intercept_errors on;
    recursive_error_pages on;
    error_page 404 = @get_routes;
}

location @get_routes {
    rewrite ^\/(\w+)\/(.+) /$1/ break;
    proxy_pass http://<your-amazon-bucket-url>;
    proxy_intercept_errors on;
    recursive_error_pages on;
    error_page 404 = @not_found;
}

location @not_found {
    return 404;
}

จะพยายามรับไฟล์และหากไม่พบจะถือว่าเป็นเส้นทาง HTML5 และลองทำเช่นนั้น หากคุณมีหน้า 404 เชิงมุมสำหรับเส้นทางที่ไม่พบคุณจะไม่ไปที่ @not_found และให้คุณกลับมาที่มุม 404 หน้าแทนที่จะเป็นไฟล์ที่ไม่พบซึ่งอาจแก้ไขได้ถ้ากฎใน @get_routes หรืออะไรบางอย่าง

ฉันต้องบอกว่าฉันรู้สึกไม่สบายใจในเรื่องของการตั้งค่า nginx และการใช้ regex สำหรับเรื่องนั้นฉันได้ทำงานกับการทดลองและข้อผิดพลาดบางอย่างดังนั้นในขณะที่ทำงานฉันแน่ใจว่ามีห้องพักสำหรับการปรับปรุงและแบ่งปันความคิดของคุณ .

หมายเหตุ : ลบกฎการเปลี่ยนเส้นทาง s3 หากคุณมีกฎเหล่านั้นใน S3 config

และ btw ทำงานใน Safari


สวัสดี .. ขอบคุณสำหรับการแก้ปัญหา ... คุณวางไฟล์ nginx conf นี้ไว้ที่ไหนสำหรับการปรับใช้ s3 มันเป็นเช่นเดียวกับฝักถั่วยืดหยุ่นที่ฉันต้องสร้างโฟลเดอร์ .extensions และวางไว้ในไฟล์ proxy.config?
user3124360

@ user3124360 ไม่แน่ใจเกี่ยวกับ elastic beanstack แต่ในกรณีของฉันฉันชี้ชื่อโดเมนของฉันไปที่อินสแตนซ์ของ ec2 และมีการกำหนดค่า nginx ที่นั่น ดังนั้นคำขอไปที่ไคลเอนต์ -> DNS -> EC2 -> S3 -> ไคลเอนต์
Andrew Arnautov

ใช่ฉันกำลังทำสิ่งที่คล้ายกันมาก ... ด้วยการกำหนดค่า nginx ที่นี่github.com/davezuko/react-redux-starter-kit/issues/1099 ... ขอบคุณสำหรับการโพสต์ไฟล์ conf ของคุณ .. ฉันเห็นว่าการพัฒนา EC2 นี้ -> การเชื่อมต่อ S3 ตอนนี้
user3124360

3

กำลังมองหาปัญหาแบบเดียวกัน ฉันลงเอยด้วยการใช้โซลูชันที่แนะนำที่อธิบายไว้ข้างต้น

ก่อนอื่นฉันมีที่เก็บข้อมูล s3 ที่มีหลาย ๆ โฟลเดอร์แต่ละโฟลเดอร์แสดงถึงเว็บไซต์ตอบสนอง / การเปลี่ยนเส้นทาง ฉันยังใช้ cloudfront สำหรับการทำให้แคชใช้ไม่ได้

ดังนั้นฉันจึงต้องใช้กฎการกำหนดเส้นทางเพื่อรองรับ 404 และเปลี่ยนเส้นทางให้เป็นแฮช config:

<RoutingRules>
    <RoutingRule>
        <Condition>
            <KeyPrefixEquals>website1/</KeyPrefixEquals>
            <HttpErrorCodeReturnedEquals>404</HttpErrorCodeReturnedEquals>
        </Condition>
        <Redirect>
            <Protocol>https</Protocol>
            <HostName>my.host.com</HostName>
            <ReplaceKeyPrefixWith>website1#</ReplaceKeyPrefixWith>
        </Redirect>
    </RoutingRule>
    <RoutingRule>
        <Condition>
            <KeyPrefixEquals>website2/</KeyPrefixEquals>
            <HttpErrorCodeReturnedEquals>404</HttpErrorCodeReturnedEquals>
        </Condition>
        <Redirect>
            <Protocol>https</Protocol>
            <HostName>my.host.com</HostName>
            <ReplaceKeyPrefixWith>website2#</ReplaceKeyPrefixWith>
        </Redirect>
    </RoutingRule>
    <RoutingRule>
        <Condition>
            <KeyPrefixEquals>website3/</KeyPrefixEquals>
            <HttpErrorCodeReturnedEquals>404</HttpErrorCodeReturnedEquals>
        </Condition>
        <Redirect>
            <Protocol>https</Protocol>
            <HostName>my.host.com</HostName>
            <ReplaceKeyPrefixWith>website3#</ReplaceKeyPrefixWith>
        </Redirect>
    </RoutingRule>
</RoutingRules>

ในรหัส js ของฉันฉันต้องจัดการมันด้วยbaseNameconfig สำหรับ react-router ครั้งแรกของทั้งหมดให้แน่ใจว่าการอ้างอิงของคุณจะทำงานร่วมกันผมได้ติดตั้งชก็ไม่เข้ากันกับhistory==4.0.0react-router==3.0.1

การพึ่งพาของฉันคือ:

  • "ประวัติ": "3.2.0",
  • "ตอบสนอง": "15.4.1",
  • "react-redux": "4.4.6",
  • "react-router": "3.0.1",
  • "react-router-redux": "4.0.7",

ฉันได้สร้างhistory.jsไฟล์สำหรับการโหลดประวัติ:

import {useRouterHistory} from 'react-router';
import createBrowserHistory from 'history/lib/createBrowserHistory';

export const browserHistory = useRouterHistory(createBrowserHistory)({
    basename: '/website1/',
});

browserHistory.listen((location) => {
    const path = (/#(.*)$/.exec(location.hash) || [])[1];
    if (path) {
        browserHistory.replace(path);
    }
});

export default browserHistory;

รหัสชิ้นนี้อนุญาตให้จัดการ 404 ที่ส่งโดยเซิร์ฟเวอร์ด้วยแฮชและแทนที่ในประวัติสำหรับการโหลดเส้นทางของเรา

ตอนนี้คุณสามารถใช้ไฟล์นี้เพื่อกำหนดค่าร้านค้าของคุณและไฟล์รูทของคุณ

import {routerMiddleware} from 'react-router-redux';
import {applyMiddleware, compose} from 'redux';

import rootSaga from '../sagas';
import rootReducer from '../reducers';

import {createInjectSagasStore, sagaMiddleware} from './redux-sagas-injector';

import {browserHistory} from '../history';

export default function configureStore(initialState) {
    const enhancers = [
        applyMiddleware(
            sagaMiddleware,
            routerMiddleware(browserHistory),
        )];

    return createInjectSagasStore(rootReducer, rootSaga, initialState, compose(...enhancers));
}
import React, {PropTypes} from 'react';
import {Provider} from 'react-redux';
import {Router} from 'react-router';
import {syncHistoryWithStore} from 'react-router-redux';
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider';
import getMuiTheme from 'material-ui/styles/getMuiTheme';
import variables from '!!sass-variable-loader!../../../css/variables/variables.prod.scss';
import routesFactory from '../routes';
import {browserHistory} from '../history';

const muiTheme = getMuiTheme({
    palette: {
        primary1Color: variables.baseColor,
    },
});

const Root = ({store}) => {
    const history = syncHistoryWithStore(browserHistory, store);
    const routes = routesFactory(store);

    return (
        <Provider {...{store}}>
            <MuiThemeProvider muiTheme={muiTheme}>
                <Router {...{history, routes}} />
            </MuiThemeProvider>
        </Provider>
    );
};

Root.propTypes = {
    store: PropTypes.shape({}).isRequired,
};

export default Root;

หวังว่ามันจะช่วย คุณจะสังเกตเห็นการกำหนดค่านี้ฉันใช้ redux injector และ homebrew sagas injector สำหรับการโหลด javascript asynchrounously ผ่านเส้นทาง ไม่เป็นไรกับบรรทัดเหล่านี้


3

ตอนนี้คุณสามารถทำได้ด้วย Lambda @ Edge เพื่อเขียนเส้นทางใหม่

นี่คือฟังก์ชั่น lambda @ Edge ที่ใช้งานได้:

  1. สร้างฟังก์ชั่น Lambda ใหม่ แต่ใช้หนึ่งในพิมพ์เขียวที่มีอยู่ล่วงหน้าแทนฟังก์ชั่นที่ว่างเปล่า
  2. ค้นหา“ cloudfront” และเลือก cloudfront-response-generation-generation จากผลการค้นหา
  3. หลังจากสร้างฟังก์ชั่นให้แทนที่เนื้อหาด้วยด้านล่าง ฉันต้องเปลี่ยนโหนดรันไทม์เป็น 10.x เนื่องจาก cloudfront ไม่รองรับโหนด 12 ในขณะที่เขียน
'use strict';
exports.handler = (event, context, callback) => {

    // Extract the request from the CloudFront event that is sent to Lambda@Edge 
    var request = event.Records[0].cf.request;

    // Extract the URI from the request
    var olduri = request.uri;

    // Match any '/' that occurs at the end of a URI. Replace it with a default index
    var newuri = olduri.replace(/\/$/, '\/index.html');

    // Log the URI as received by CloudFront and the new URI to be used to fetch from origin
    console.log("Old URI: " + olduri);
    console.log("New URI: " + newuri);

    // Replace the received URI with the URI that includes the index page
    request.uri = newuri;

    return callback(null, request);
};

ในพฤติกรรม Cloudfront ของคุณคุณจะแก้ไขพวกเขาเพื่อเพิ่มการเรียกไปยังฟังก์ชั่นแลมบ์ดาใน "คำขอดู" ป้อนคำอธิบายรูปภาพที่นี่

บทแนะนำแบบเต็ม: https://aws.amazon.com/blogs/compute/implementing-default-directory-indexes-in-amazon-s3-backed-amazon-cloudfront-origins-using-lambdaedge/


1
ตัวอย่างรหัสของคุณพลาดเพียงบรรทัด:return callback(null, request);
Pherrymason

2

หากคุณมาที่นี่เพื่อค้นหาโซลูชันที่ใช้งานได้กับ React Router และ AWS Amplify Console - คุณรู้อยู่แล้วว่าคุณไม่สามารถใช้กฎการเปลี่ยนเส้นทางของ CloudFront ได้โดยตรงเนื่องจาก Amplify Console ไม่เปิดเผย CloudFront Distribution สำหรับแอป

อย่างไรก็ตามโซลูชันนั้นง่ายมาก - คุณเพียงแค่ต้องเพิ่มกฎการเปลี่ยนเส้นทาง / เขียนใหม่ใน Amplify Console ดังนี้:

ขยายกฎการเขียนซ้ำสำหรับคอนโซลสำหรับทำปฏิกิริยาเราเตอร์

ดูลิงค์ต่อไปนี้สำหรับข้อมูลเพิ่มเติม (และกฎที่คัดลอกง่ายจากภาพหน้าจอ):


0

ฉันกำลังมองหาคำตอบนี้เอง S3 ดูเหมือนจะสนับสนุนการเปลี่ยนเส้นทางเท่านั้นคุณไม่สามารถเขียน URL ซ้ำและส่งคืนทรัพยากรอื่น ๆ โดยไม่แจ้งเตือน ฉันกำลังพิจารณาใช้สคริปต์สร้างของฉันเพื่อทำสำเนา index.html ของฉันในทุกตำแหน่งของเส้นทางที่ต้องการ บางทีนั่นอาจจะเหมาะกับคุณเช่นกัน


2
สร้างไฟล์ดัชนีแต่ละเส้นทางได้ข้ามใจของฉันเช่นกัน แต่มันจะเป็นเรื่องยากที่จะมีเส้นทางแบบไดนามิกเช่นexample.com/groups/5/show หากคุณเห็นคำตอบของฉันสำหรับคำถามนี้ฉันเชื่อว่าส่วนใหญ่จะแก้ปัญหาได้ มันเป็นบิตของการแฮ็ก แต่อย่างน้อยก็ใช้งานได้
Mark Nutter

ดีกว่าที่จะปรับใช้หลังเซิร์ฟเวอร์ nginx และส่งคืน index.html สำหรับ URL ที่เข้ามาทั้งหมด ฉันทำสิ่งนี้ได้สำเร็จด้วยการปรับใช้แอพ ember ของ heroku
moha297

-3

เพียงแค่ใส่คำตอบที่ง่ายมาก เพียงใช้กลยุทธ์ตำแหน่งแฮชสำหรับเราเตอร์หากคุณโฮสต์บน S3

ส่งออก const AppRoutingModule: ModuleWithProviders = RouterModule.forRoot (เส้นทาง {useHash: true, scrollPositionRestoration: 'เปิดใช้'});

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.