Angular Service Worker ngsw-config.json S3 / Cloudflare Image Caching CORS Error

Sep 10 2020

ในแอพ Angular 9 เมื่อฉันเพิ่มข้อมูลโค้ดการแคชรูปภาพนี้ลงใน ngsw-config.json ฉันได้รับข้อผิดพลาด CORS และรูปภาพไม่แสดง หากฉันลบข้อมูลโค้ดนี้ออกแสดงว่าแอปทำงานได้อย่างถูกต้อง (โดยไม่มีข้อผิดพลาด)

การเข้าถึงเพื่อดึงข้อมูลที่ 'https://assets.myurl.net/images/banner.jpg' จากต้นทาง 'https: // localhost: 8100' ถูกบล็อกโดยนโยบาย CORS: ไม่มีส่วนหัว 'Access-Control-Allow-Origin' มีอยู่ในทรัพยากรที่ร้องขอ หากการตอบกลับแบบทึบตอบสนองความต้องการของคุณให้ตั้งค่าโหมดของคำขอเป็น "no-cors" เพื่อดึงทรัพยากรโดยปิดใช้งาน CORS

ngsw-config.json (ข้อมูลโค้ด):

"assetGroups": [{
    "name": "cdn",
    "installMode": "lazy",
    "updateMode": "lazy",
    "resources": {
        "urls": [
            "https://assets.myurl.net/**"
        ]
    }
}]

รูปภาพจะถูกเก็บไว้ในที่เก็บข้อมูล AWS S3 พร้อมการกำหนดค่า CORS:

<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<CORSRule>
    <AllowedOrigin>*</AllowedOrigin>
    <AllowedMethod>GET</AllowedMethod>
</CORSRule>
</CORSConfiguration>
  • Cloudflare ถูกใช้เป็น CDN (และ DNS)
  • แอปนี้เป็นเวอร์ชัน 9.x ล่าสุด: @angular 9.2.1, @ angular / service-worker 9.1.12
  • การเพิ่ม crossorigin = "anonymous" ลงใน img และแท็กรูปภาพดูเหมือนจะไม่ช่วยอะไร

ขั้นตอนในการทำให้เกิดข้อผิดพลาดอย่างต่อเนื่องใน Chrome / PC:

  1. ล้างแคชของเบราว์เซอร์
  2. เปิดเบราว์เซอร์ส่วนตัว / ไม่ระบุตัวตน
  3. ไปที่เว็บไซต์ - ภาพแสดงว่าโอเค
  4. คลิกรีเฟรช - รูปภาพไม่แสดงอีกต่อไป - ข้อผิดพลาด CORS ในคอนโซลเบราว์เซอร์

อัปเดต

จากโพสต์นี้ ( S3 ไม่ส่งคืนส่วนหัว Access-Control-Allow-Origin? ) ปัญหาดูเหมือนว่าผู้ให้บริการไม่ได้ส่ง Origin ในส่วนหัวของคำขอ (ดังนั้น S3 จึงไม่ส่งส่วนหัวการควบคุมการเข้าถึง)

คำขอพนักงานบริการ (คัดลอกจากคอนโซล Chrome):

Request URL: https://assets.myurl.net/images/banner.jpg
Referrer Policy: strict-origin-when-cross-origin
Provisional headers are shown
Referer: https://localhost:8100/
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.83 Safari/537.36

ก่อนอื่นตรวจสอบให้แน่ใจว่าส่วนหัว Origin พร้อมทุกคำขอ หากไม่มีการส่งส่วนหัว Origin S3 จะไม่ส่งส่วนหัวการควบคุมการเข้าถึงเนื่องจาก S3 เห็นว่าไม่เกี่ยวข้อง (และโดยทั่วไปจะเป็น) เบราว์เซอร์ (ซึ่งหมายถึงกลไก CORS) จะส่งส่วนหัว Origin โดยอัตโนมัติเมื่อส่งคำขอ HTTP ข้ามต้นทางผ่าน XMLHTTPRequest

ตามโพสต์นี้ ( S3 - Access-Control-Allow-Origin Header ) สคริปต์ S3 cors ได้รับการอัปเดตเพื่อรวม:

<AllowedMethod>HEAD</AllowedMethod>
<AllowedHeader>*</AllowedHeader>

การเพิ่ม crossorigin = "anonymous" ลงในแท็ก img จะไม่เปลี่ยนส่วนหัวคำขอของผู้ปฏิบัติงานบริการ นี่จึงไม่สามารถแก้ไขปัญหาได้

แคช Cloudflare ถูกล้าง

โพสต์ที่คลุมเครือนี้ (https://community.cloudflare.com/t/access-control-allow-origin-headers-stripped/158102/2) รวมถึง:

หากคุณเพิ่มหรือเปลี่ยนการกำหนดค่า CORS ที่เว็บเซิร์ฟเวอร์ต้นทางการล้างแคช Cloudflare ด้วย URL จะไม่อัปเดตส่วนหัว CORS

ฉันแคชจับภาพ banner.jpg โดยการเพิ่มสตริงการสืบค้นแบบสุ่ม (เช่น banner.jpg? q = abc) รูปภาพแบนเนอร์จะแสดงอย่างถูกต้องเสมอ (ในขณะที่รูปภาพอื่น ๆ ยังคงแสดงข้อผิดพลาดของคอร์) แคชของผู้ให้บริการในคอนโซล Chrome แท็บแอปพลิเคชัน> ที่เก็บแคชแสดงว่ารูปภาพถูกแคชไว้ การกำหนดค่าการแคช Cloudflare "ระดับการแคช" = มาตรฐาน "ส่งทรัพยากรที่แตกต่างกันทุกครั้งที่สตริงการสืบค้นเปลี่ยนแปลง"

อย่างไรก็ตามหากฉันอัปโหลดภาพใหม่ไปยัง S3 banner01.jpg (เช่น Cloudflare ยังไม่ได้แคชไว้) ฉันได้รับข้อผิดพลาด cors ที่แสดงภาพนี้ ฉันลองทำอีกสามครั้งโดยอัปโหลดชื่อรูปภาพที่แตกต่างกันและไม่ได้รับข้อผิดพลาด cors ที่น่าสนใจคือหนึ่งชั่วโมงต่อมาแม้แต่ภาพใหม่ก็แสดงข้อผิดพลาด

คำสั่ง curl (ที่ไม่ได้ระบุ Origin ในส่วนหัว) ทำงานบนพีซีภายในของฉันได้สำเร็จ การตอบสนองไม่มีส่วนหัว CORS เช่น

curl -v "https://assets.myurl.net/images/banner.jpg"

การเพิ่มจุดเริ่มต้นไปยังคำสั่ง curl จะส่งคืนส่วนหัว CORS เช่น

curl -v --header "Origin: https://www.example.com" "https://assets.myurl.net/images/banner.jpg"

access-control-allow-origin: https://www.example.com
access-control-allow-methods: GET, HEAD
access-control-allow-credentials: true

อัปเดต 2

ฉันไม่สามารถอธิบายได้ว่าทำไม แต่ตอนนี้ Chrome ส่งคืนส่วนหัวของ cors ในการตอบสนองการดึงข้อมูล Angular Service Worker คำขอไม่มีส่วนหัว Origin

accept-ranges: bytes
access-control-allow-methods: GET, HEAD
access-control-allow-origin: *

อย่างไรก็ตาม Safari ไม่ ดูเหมือนว่าเบราว์เซอร์ทั้งหมดจะใช้งานได้ปกติ แต่ Safari ยังคงแสดงข้อผิดพลาด cors

คำตอบ

LeonGrin Sep 19 2020 at 20:50

ไปที่ถัง S3 ของคุณ คลิกที่สิทธิ์จากนั้นคลิกที่การกำหนดค่า CORS หากคุณมีการกำหนดค่า CORS ให้เปลี่ยนจุดเริ่มต้นที่อนุญาตจากสิ่งนี้:

<AllowedOrigin>*</AllowedOrigin>

ถึง

<AllowedOrigin>http://*</AllowedOrigin>
<AllowedOrigin>https://*</AllowedOrigin>

หากคุณไม่มีการกำหนดค่า CORS ให้เพิ่มการกำหนดค่าดังนี้:

<CORSConfiguration>
<CORSRule>
    <AllowedOrigin>http://*</AllowedOrigin>
    <AllowedOrigin>https://*</AllowedOrigin>
    <AllowedMethod>PUT</AllowedMethod>
    <AllowedMethod>POST</AllowedMethod>
    <AllowedMethod>DELETE</AllowedMethod>
    <AllowedMethod>GET</AllowedMethod>
    <AllowedHeader>*</AllowedHeader>
</CORSRule>
<CORSRule>
    <AllowedOrigin>*</AllowedOrigin>
    <AllowedMethod>GET</AllowedMethod>
</CORSRule>
</CORSConfiguration>