ขนมปังกลมต้นฉบับผลักแฟ้มผ่านวงแหวน URL ให้ลงรางโฟลเดอร์ครีมโดยชื่อยังครบ

Bun.fileURLToPath: แปลง file URL เป็นพาธโดยไม่พังช่องว่างและอักขระ escape

พี่โชว์Engineering

new URL("data file.json", import.meta.url).pathname ดูเหมือนพาธ แต่ยังเป็นรูปแบบ URL ครับ ช่องว่างอาจอยู่เป็น %20 และกติกา Windows drive/UNC ต่างจากพาธ POSIX Bun.fileURLToPath แปลงตาม semantics ของระบบไฟล์ให้

WHY: URL กับ filesystem path เป็นคนละภาษา

เหมือนที่อยู่บนซองพัสดุกับทางเดินจริงในคลัง ทั้งสองชี้จุดเดียวกันแต่ใช้กฎ escape และตัวคั่นต่างกัน การหยิบ pathname ตรง ๆ คือเอาที่อยู่บนซองไปใช้เป็นทางเดิน อาจผ่านบนชื่อธรรมดาแล้วพังเมื่อเจอช่องว่างหรือ platform อื่น

HOW: ประกอบ URL ก่อน แล้วค่อยแปลงครั้งเดียว

const url = new URL("file:///tmp/showkhun%20notes/data.json");
const path = Bun.fileURLToPath(url);

if (path !== "/tmp/showkhun notes/data.json") {
  throw new Error(`unexpected path: ${path}`);
}

const roundTrip = Bun.pathToFileURL(path);
if (!roundTrip.href.endsWith("showkhun%20notes/data.json")) {
  throw new Error(`unexpected URL: ${roundTrip.href}`);
}

ในโมดูลจริงให้สร้าง new URL("./data.json", import.meta.url) ก่อน จึงค่อยแปลงเป็น path ตอน API ปลายทางต้องการ string path หาก API รับ URL ได้อยู่แล้ว ส่ง URL โดยตรงจะลดการแปลงไปกลับ

อย่ารับ file: URL จากผู้ใช้แล้วเปิดทันที การแปลงถูกต้องไม่ได้แปลว่าปลายทางอยู่ใน directory ที่อนุญาต ต้อง resolve, canonicalize เท่าที่ platform รองรับ และตรวจ boundary แยกต่างหาก โดยเฉพาะ service ที่ถือ secret

Recap

  • อย่าใช้ .pathname เป็นพาธโดยตรง
  • ใช้ Bun.fileURLToPath เพื่อ decode และจัดรูปแบบตาม platform
  • ใช้ Bun.pathToFileURL เมื่อต้องย้อนกลับ
  • ตรวจ allowed directory แยกจากการแปลงรูปแบบ