CORS คืออะไร สำคัญกับคนทำเว็บอย่างไร
ทำเว็บไซต์

ไขข้อข้องใจ สำหรับคนทำเว็บ CORS คืออะไร

CORS ย่อมาจาก Cross-Origin Resource Sharing ถ้าจะแปลตามตัวอักษรเป็นภาษาไทยแบบสั้นๆ ให้ได้ใจความ ก็น่าจะได้ความหมายประมาณว่า CORS คือ “การแบ่งปันทรัพยากรข้ามแหล่งที่มา” อ่านแล้วคงต้องแปลไทยเป็นไทยกันอีกรอบ แล้วตกลง CORS คืออะไร ทำงานอย่างไร มาดูกัน

หลักการทำงานคร่าวๆของ CORS คือการเพิ่ม Respond HTTP Header ที่แจ้งให้ web browser รู้ว่า server นี้อนุญาตให้ web page หรือ web application ที่มาจาก “แหล่ง” หรือ “origin” อื่นๆ สามารถนำไฟล์ หรือ ทรัพยากรชิ้นนี้ไปใช้งานได้ ส่วนใหญ่ก็จะเป็นการเรียกใช้งาน ไฟล์ หรือ ทรัพยากรอื่นผ่าน javascript

โดยปรกติแล้ว เพื่อความปลอดภัย browser จะปฏิบัติตามข้อตกลงที่ชื่อ same-origin policy ซึ่งใช้กำหนดนิยามของ origin ว่ากรณีไหนบ้างที่จะนับว่า request นั้นมาจาก origin เดียวกัน ยกตัวอย่างเช่น browser จะไม่อนุญาติให้ javascript เรียกใช้งาน API หรือไฟล์ที่มาจาก domain อื่น หรืออย่างการใช้งาน ajax ผ่าน XMLHttpRequest หรือ Fetch API หากทาง server เจ้าของไฟล์ไม่มีการกำหนด CORS Header ที่ถูกต้องมาด้วย browser จะบล็อกการเข้าถึง ไฟล์ หรือ ทรัพยากรนั้น โดยจะแจ้งข้อความ error ที่ console

ตัวอย่างการใช้งาน CORS

เรามาลองยกตัวอย่างการใช้งานจริงๆ กันดีกว่า สมมติว่าท่านผู้อ่านเข้ามาที่เว็บ www.phukettop.com โดยใช้ Chrome ทำหน้าที่เป็น web browser 

Chrome จะทำการส่งคำขอไปที่ server ของ phukettop โดยปรกติแล้วก็จะได้รับไฟล์ index.html กลับมาเพื่อทำการแสดงผล ในไฟล์นี้ก็จะมีการเขียน code เพื่อเรียกใช้งาน รูปภาพ font และ script ต่างๆ ส่วนใหญ่ก็จะต้องโหลดมาจาก server ของ phukettop เหมือนเดิม

แต่จะมีส่วนนึงที่เป็น javascript ซึ่งใช้งานอ็อปเจ็ค XMLHttpRequest เพื่อเรียกเอกสารจาก google.co.th ตาม code ต่อไปนี้

<script> 
const request = new XMLHttpRequest(); 
const url = 'https://www.google.co.th/';
  function CORSTesting() {   
    if(request) {
      request.open('GET', url, true);
      request.send();
     }
  }
 CORSTesting(); 
</script>

script ด้านบนนี้ไม่ได้ทำอะไรมาก เพียงแค่ทำการขอเอกสารจาก google.co.th แล้วก็จบการทำงาน แต่ code ชุดนี้จะโดนบล็อกโดย Chrome เนื่องจาก CORS policy ซึ่งจะแจ้งข้อความ error มาทาง console

สาเหตุเกิดจาก script จะเริ่มการทำงานจากไฟล์ index.html ซึ่งมาจาก phukettop.com แต่มีการร้องขอทรัพยากรจากโดนเมนอื่น โดย javascript ในกรณีนี้คือ เอกสารหน้าแรกของ google.co.th ซึ่งโดยปรกติแล้วทาง server ของ google จะไม่ส่ง CORS Header มาด้วย เลยทำให้ browser ซึ่งปฏิบัติตาม same-origin policy ไม่โหลดไฟล์นี้มา โดยจะแจ้งเป็น error แทน

เราจะใช้ script เดิมจากด้านบนมาทำการทดลอง เรียกไฟล์อื่นดูบ้าง คราวนี้จะเปลี่ยน ulr เป็น https://fonts.googleapis.com/css?family=Prompt เรามาลองดู Response HTTP Header ที่มาจาก googleapis.com กัน

response header จาก google font

จะเห็นได้ว่ามีการส่ง Header ที่ชื่อ access-control-allow-origin ที่มีค่าเป็น * หมายถึง ทาง server อนุญาติให้ใช้งานไฟล์นี้ได้จากทุกที่ ทุกโดเมน

รายละเอียดของ CORS 

เวลาเรานำ CORS ไปใช้ในงานของเรา ซึ่งหากต้องการความชัดเจน เราสามารถระบุลงไปเลยก็ได้ว่าจะยอมให้ domain ไหนบ้างที่สามารถโหลดทรัพยากรนี้ไปใช้งานได้ โดยระบุใน Response Header แบบนี้

access-control-allow-origin: https://example.com

ไฟล์นี้ก็จะสามารถโหลดไปใช้งานผ่าน browser ได้จากการทำงานของไฟล์ที่มาจาก example.com เท่านั้น

ในการทำงานของ web browser บางตัวจะมีการส่ง OPTIONS Request เพื่อตรวจสอบในส่วนของ CORS โดยเฉพาะ เราจะเรียกขั้นตอนนี้ว่า preflight request หากเราเป็น developer ที่ดูแลการทำงานของ API server เราควรจัดการกับ ขั้นตอนนี้อย่างเหมาะสม โดยสามารถเลือกใช้งานตามสถานการณ์ดังนี้

Access-Control-Allow-Origin: *
ยอมให้ใช้งานจากทุกที่
Access-Control-Allow-Origin: https://example.com
ยอมให้ใช้งานจาก โดเมน example.com เท่านั้น
Access-Control-Allow-Methods: GET, POST
ยอมให้ใช้งานผ่าน GET และ POST method เท่านั้น
Access-Control-Allow-Headers: Content-Type, Accept
header ที่สามารถส่งมาพร้อมกับ request ได้
Access-Control-Max-Age: 600
เวลาสูงสุดที่ browser สามารถเก็บผลของ OPTIONS request โดยไม่ต้องส่ง request มาใหม่ หน่วยเป็นวินาที

Express Server กับการใช้งาน CORS

เราจะมาลองดูตัวอย่างการใช้งาน CORS กับ Express Server แบบง่ายๆกันนะครับ 

const express = require("express"); 
const app = express();
const port = process.env.SERVER_PORT || 3000;
app.use(function(req, res, next) {
   res.header("Access-Control-Allow-Origin", "*");
   res.header(     "Access-Control-Allow-Headers",
     "Origin, X-Requested-With, Content-Type, Accept"
   );
   next();
 });
app.get("/api/ping", (req, res) => {
   res.send({
     msg: "Hello, World"
   }); });
app.listen(port, () => console.log(`Listening on port ${port}`));

จาก code ด้านบน express จะทำการเพิ่ม Access-Control-Allow-Origin และ Access-Control-Allow-Headers กับทุก request ที่ส่งเข้ามา 

หลังจากเริ่มการทำงานของ server แล้วเราจะทดลองเรียก /api/ping/ จาก localhost ดูนะครับโดยใช้ผู้ช่วยอย่าง curl

$ curl -i localhost:3000/api/ping
HTTP/1.1 200 OK
Access-Control-Allow-Origin: *
Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept
Content-Type: application/json; charset=utf-8
Content-Length: 22
ETag: W/"16-IP+nb8Blfh+WTVdL6Lq1eXiDJXg"
Date: Thu, 02 May 2019 09:13:53 GMT
Connection: keep-alive
{"msg":"Hello, World"}

อาจจะหายสงสัยกันแล้วนะครับ ว่า CORS คืออะไร มีประโยชน์อย่างไร หากใครเจอปัญหา แก้ไม่ได้ซักที ลองเปิด console ดูครับ อาจจะพบว่าปัญหานั้นมาจาก CORS นี่ก็ได้ สำหรับท่านที่ต้องการศึกษาเพิ่มเติมเกี่ยวกับ CORS แนะนำให้เข้าไปอ่านบทความนี้ต่อนะครับ

ทุกวันนี้มีการใช้งาน javascript library กันอย่างแพร่หลาย ทั้ง react และ vue การแยกกันระหว่าง API Server และ Static file server ทำให้ full stack dev ต้องทำความเข้ากับ CORS อย่างถ่องแท้ ว่ามันคืออะไร และ ทำงานอย่างไร

แขร์บทความ:

Comments Off on ไขข้อข้องใจ สำหรับคนทำเว็บ CORS คืออะไร