🐍 Advanced Python Programming — NetworkingFastAPI · HTTP Methods · JSON · Real Colab Service
SINGLE HTML · REAL HTTP GUIDE
EXERCISE 2 · COLAB PATCH v2

REST Service & API Client

Run FastAPI as a real background HTTP service inside Google Colab, then call it from later notebook cells with requests.

Colab-native REST Service

เหมือน Exercise 1: ให้ FastAPI ทำงานอยู่ใน background thread แล้วใช้ Colab cell ถัดไปเป็น API Client โดยตรง

FastAPI← HTTP →requests→JSON
ไม่ต้องใช้ ngrok สำหรับ Exercise นี้ เพราะ Service และ Client อยู่ใน Colab runtime เดียวกัน จึงเรียก http://127.0.0.1:8000 ได้โดยตรง

Notebook Flow

Cell 1 Install packages
Cell 2 Build FastAPI endpoints
Cell 3 Start service in background
Cell 4 API Client calls GET / POST / DELETE
Cell 5 Test 404
Cell 6 Stop service

Prepare Colab

Run once at the beginning of the notebook.

เราไม่ต้องติดตั้ง pyngrok เพราะ Client อยู่ใน runtime เดียวกับ Server

Cell 1 · Install

!pip -q install fastapi uvicorn requests

print("Packages ready ✓")

REST Endpoints

GET /students
GET /students/{id}
POST /students
DELETE /students/{id}
Cell นี้สร้าง app และข้อมูลจำลอง แต่ยังไม่ได้เปิด HTTP Server

Cell 2 · FastAPI App

from fastapi import FastAPI, HTTPException
from pydantic import BaseModel

app = FastAPI(title="KASA Student Service")

students = {
    1: {"id": 1, "name": "Mina", "score": 88},
    2: {"id": 2, "name": "Narin", "score": 76},
}

class Student(BaseModel):
    id: int
    name: str
    score: int

@app.get("/students")
def list_students():
    return list(students.values())

@app.get("/students/{student_id}")
def get_student(student_id: int):
    if student_id not in students:
        raise HTTPException(status_code=404, detail="Student not found")
    return students[student_id]

@app.post("/students", status_code=201)
def create_student(student: Student):
    students[student.id] = student.model_dump()
    return students[student.id]

@app.delete("/students/{student_id}")
def delete_student(student_id: int):
    if student_id not in students:
        raise HTTPException(status_code=404, detail="Student not found")
    return students.pop(student_id)

print("FastAPI app ready ✓")

Background Service

Start Uvicorn in a daemon thread so the Colab cell can finish while the API keeps listening.

Colab→Thread→Uvicorn :8000
หลังรันจะได้ BASE_URL = http://127.0.0.1:8000 โดยอัตโนมัติ ไม่ต้อง copy URL จากที่อื่น

Cell 3 · Start API

import threading
import time
import uvicorn

HOST = "127.0.0.1"
PORT = 8000
BASE_URL = f"http://{HOST}:{PORT}"

config = uvicorn.Config(
    app,
    host=HOST,
    port=PORT,
    log_level="warning"
)

api_server = uvicorn.Server(config)

server_thread = threading.Thread(
    target=api_server.run,
    daemon=True
)
server_thread.start()

# Wait briefly for the background server to start
for _ in range(20):
    if api_server.started:
        break
    time.sleep(0.25)

print("FastAPI running ✓")
print("BASE_URL =", BASE_URL)

Postman-style Python Client

ใช้ requests เรียก API จริงผ่าน HTTP ภายใน Colab runtime เดียวกัน

GET collection
GET resource
POST JSON
GET เพื่อ verify
DELETE resource

Cell 4 · Call API

import requests

print("Using API:", BASE_URL)

# 1) GET all students
r = requests.get(f"{BASE_URL}/students", timeout=10)
print("\nGET /students")
print("Status:", r.status_code)
print("JSON  :", r.json())

# 2) GET one student
r = requests.get(f"{BASE_URL}/students/1", timeout=10)
print("\nGET /students/1")
print("Status:", r.status_code)
print("JSON  :", r.json())

# 3) POST new student
payload = {
    "id": 3,
    "name": "Kasa",
    "score": 91
}

r = requests.post(
    f"{BASE_URL}/students",
    json=payload,
    timeout=10
)
print("\nPOST /students")
print("Status:", r.status_code)
print("JSON  :", r.json())

# 4) Verify student 3 exists
r = requests.get(f"{BASE_URL}/students/3", timeout=10)
print("\nGET /students/3")
print("Status:", r.status_code)
print("JSON  :", r.json())

# 5) DELETE student 3
r = requests.delete(f"{BASE_URL}/students/3", timeout=10)
print("\nDELETE /students/3")
print("Status:", r.status_code)
print("JSON  :", r.json())

Cell 5 · Test HTTP 404

import requests

r = requests.get(
    f"{BASE_URL}/students/999",
    timeout=10
)

print("GET /students/999")
print("Status:", r.status_code)
print("JSON  :", r.json())

# Expected:
# Status: 404
# JSON: {'detail': 'Student not found'}
Expected: GET /students/999 Status: 404 JSON : {'detail': 'Student not found'}

Challenge · PUT Endpoint

เพิ่ม endpoint สำหรับ update student แล้วทดสอบด้วย Client

# Challenge: add an update endpoint to the FastAPI app.
# IMPORTANT:
# After changing routes, stop the server and rerun
# the Build Service + Start Service cells.

@app.put("/students/{student_id}")
def update_student(student_id: int, student: Student):
    if student_id not in students:
        raise HTTPException(status_code=404, detail="Student not found")

    students[student_id] = student.model_dump()
    return students[student_id]
payload = {
    "id": 1,
    "name": "Mina",
    "score": 95
}

r = requests.put(
    f"{BASE_URL}/students/1",
    json=payload,
    timeout=10
)

print("PUT /students/1")
print("Status:", r.status_code)
print("JSON  :", r.json())

Stop the API Server

เมื่อจบ Exercise ให้ปิด background Uvicorn server อย่างถูกต้อง

ถ้าต้องการแก้ route แล้วเริ่มใหม่ ให้ Stop ก่อน จากนั้นรัน Build Service และ Start Service ใหม่

Cell 6 · Stop Service

api_server.should_exit = True
server_thread.join(timeout=5)

print("FastAPI server stopped ✓")