
กำลังโหลด...

กำลังโหลด...

จำตาราง REST ที่ให้ถ่ายรูปเก็บไว้เมื่อกี้ได้ไหม? วันนี้เอามาทำเป็นโค้ดจริง
ยังไม่ต้องมีข้อมูลจริงนะ ตอบเป็นข้อความไปก่อนว่า route ไหนถูกเรียก ขอแค่โครงครบ 5 เส้น แล้วทดสอบให้ครบทุกเส้นด้วย Thunder Client
เป้าหมายของ Mission นี้: เข้าใจว่า Express จับคู่ Request กับ Route ยังไง และลำดับ ของ route สำคัญอย่างไร
จบ Mission นี้คุณจะ
Route = คู่ของ (Method + Path) ที่ผูกกับฟังก์ชันหนึ่งตัว
app.METHOD(PATH, HANDLER)
| | |
| | +--> ทำอะไรเมื่อ Request ตรงเงื่อนไข
| +----------> ทำกับอะไร เช่น "/books"
+-----------------> ทำแบบไหน เช่น get, post, put, delete
นี่คือจุดที่ตาราง REST จาก Chapter 1 กลายเป็นโค้ดจริง
app.get("/books", ...) // ดูทั้งหมด
app.get("/books/:id", ...) // ดูตัวเดียว
app.post("/books", ...) // เพิ่ม
app.put("/books/:id", ...) // แก้
app.delete("/books/:id", ...) // ลบ
สังเกตว่า "/books" โผล่ 2 ครั้ง แต่คนละ Method — Express ถือว่าเป็นคนละ route กันโดย
สิ้นเชิง ไม่ตีกัน
Express ไล่เช็ก จากบนลงล่าง และ หยุดที่ตัวแรกที่ตรง
flowchart TD
A["GET /books เข้ามา"] --> B{"route 1: GET / ?"}
B -->|"ไม่ตรง"| C{"route 2: GET /about ?"}
C -->|"ไม่ตรง"| D{"route 3: GET /books ?"}
D -->|"ตรง!"| E["รัน handler แล้วจบ<br/>ไม่ดู route ที่เหลือเลย"]
D -->|"ถ้าไม่ตรง"| F["...ไล่ต่อจนหมดไฟล์"]
F --> G["ไม่เจอเลย -> 404"]
style E fill:#14532d,stroke:#22c55e,color:#fff
style G fill:#5c2d2d,stroke:#ef4444,color:#fff
ทำไมเรื่องนี้สำคัญ? ดูตัวอย่างกับดักคลาสสิกนี้
app.get("/books/:id", (req, res) => res.send("หนังสือรายเล่ม"));
app.get("/books/popular", (req, res) => res.send("หนังสือยอดนิยม")); // ❌ ไม่มีวันถูกเรียก
เพราะ /books/popular ตรงกับ /books/:id ก่อน (Express มองว่า :id = "popular")
Express หยุดที่ตัวแรกที่ตรง จึงไม่มีทางไปถึงบรรทัดล่าง
แก้โดยเอาตัวที่เฉพาะเจาะจงกว่าขึ้นก่อน
app.get("/books/popular", ...); // ✅ เฉพาะเจาะจง อยู่บน
app.get("/books/:id", ...); // ✅ กว้าง อยู่ล่าง
กฎทอง: route ที่เจาะจงกว่า ต้องอยู่เหนือ route ที่กว้างกว่าเสมอ
import express from "express";
const app = express();
const PORT = 3000;
// -- Collection: /books ------------------------------------
app.get("/books", (req, res) => {
res.json({ message: "ดูหนังสือทั้งหมด" });
});
app.post("/books", (req, res) => {
res.status(201).json({ message: "เพิ่มหนังสือใหม่" });
});
// -- Single resource: /books/:id ---------------------------
app.get("/books/:id", (req, res) => {
res.json({ message: `ดูหนังสือเล่มที่ ${req.params.id}` });
});
app.put("/books/:id", (req, res) => {
res.json({ message: `แก้ไขหนังสือเล่มที่ ${req.params.id}` });
});
app.delete("/books/:id", (req, res) => {
res.json({ message: `ลบหนังสือเล่มที่ ${req.params.id}` });
});
app.listen(PORT, () => {
console.log(`Server running on http://localhost:${PORT}`);
});
:id คือ ตัวแปรใน path — อะไรก็ตามที่มาตรงตำแหน่งนั้นจะถูกเก็บไว้ใน req.params.id
(Chapter 4 จะเจาะลึกเรื่องนี้ ตอนนี้แค่รู้ว่ามันคืออะไรพอ)
เบราว์เซอร์พิมพ์ URL ได้แค่ GET เท่านั้น — จะยิง POST/PUT/DELETE ต้องใช้เครื่องมือช่วย
วิธีทดสอบ API
+---------------------------------------------------+
| เบราว์เซอร์ -> ได้เฉพาะ GET |
| Postman -> ครบทุก Method (แอปแยก) |
| Thunder Client -> ครบทุก Method (extension |
| ใน VS Code เบากว่า แนะนำ) |
| curl -> ครบทุก Method (command line)|
+---------------------------------------------------+
ติดตั้ง Thunder Client: เปิด VS Code → Extensions → ค้นหา "Thunder Client" → Install → จะมีไอคอนสายฟ้าโผล่ที่แถบซ้าย → New Request → เลือก Method → ใส่ URL → Send
หรือใช้ curl ใน terminal ก็ได้ (ไม่ต้องลงอะไรเพิ่ม)
curl http://localhost:3000/books
curl -X POST http://localhost:3000/books
curl -X DELETE http://localhost:3000/books/3
| ปัญหา | สาเหตุ / วิธีแก้ |
|---|---|
/books/popular ไม่ทำงาน ได้ผลของ /books/:id แทน |
ลำดับผิด → ย้าย route ที่เจาะจงขึ้นไปข้างบน |
| ยิง POST จากเบราว์เซอร์ไม่ได้ | เบราว์เซอร์ทำได้แค่ GET → ใช้ Thunder Client / Postman / curl |
Cannot POST /books |
ยังไม่ได้เขียน app.post("/books", ...) — เขียนแต่ app.get |
เขียน app.get("books") ไม่มี / นำหน้า |
ต้องมี / เสมอ → app.get("/books") |
| ประกาศ route ซ้ำ path+method เดียวกัน 2 ครั้ง | ตัวล่างจะไม่ถูกเรียกเลย (แต่ไม่มี error เตือน) — ต้องไล่หาเอง |
:id = ตัวแปรใน path เก็บไว้ที่ req.params.id
Workshop — โครง REST ครบ 5 เส้น + กับดักลำดับ
เขียน route ให้ครบ 5 เส้นใน index.js โดยแต่ละเส้นตอบ JSON บอกว่าตัวเองถูกเรียก
| Method | Path | ตอบกลับ |
|---|---|---|
| GET | /books |
{ "message": "ดูหนังสือทั้งหมด" } |
| GET | /books/:id |
{ "message": "ดูหนังสือเล่มที่ 5" } (ตามเลขที่ส่งมา) |
| POST | /books |
{ "message": "เพิ่มหนังสือใหม่" } + Status 201 |
| PUT | /books/:id |
{ "message": "แก้ไขหนังสือเล่มที่ 5" } |
| DELETE | /books/:id |
{ "message": "ลบหนังสือเล่มที่ 5" } |
ติดตั้ง Thunder Client ใน VS Code (หรือ Postman) แล้วยิงทดสอบ ให้ครบทั้ง 5 เส้น จดไว้ว่าแต่ละเส้นได้ Status Code อะไร
เพิ่ม route GET /books/popular ที่ตอบ { "message": "หนังสือยอดนิยม" }
โดยวางไว้ ใต้ GET /books/:id
GET /books/popular แล้วดูว่าได้อะไร — ตรงกับที่คาดไว้ไหม?
ข้อ 1. Express เลือก route ที่จะทำงานอย่างไร
ข้อ 2. app.get("/books") กับ app.post("/books") ตีกันหรือไม่
ข้อ 3. ทำไม /books/popular ที่วางใต้ /books/:id ถึงไม่ทำงาน
ข้อ 4. ทำไมทดสอบ POST ด้วยการพิมพ์ URL ในเบราว์เซอร์ไม่ได้
ข้อ 5. ถ้าประกาศ app.get("/books") ซ้ำ 2 ครั้งในไฟล์เดียวกัน จะเกิดอะไรขึ้น