採点されません。匿名です。 間違えることは学習の一部です。読むだけでもかまいません。

L14 ch01 — CORS Middleware

テクノロジ系 / L14 middleware — ミドルウェア

L14 ch01 — CORS Middleware

フロント (別ポート) からの fetch を許可する

ゴール

  • CORS の仕組みを理解
  • CORSMiddleware の設定
  • Vue + FastAPI 連携で必須

CORS とは

Cross-Origin Resource Sharing

ブラウザのセキュリティ機能:

  • ページのオリジン (http://localhost:5173) と
  • API のオリジン (http://localhost:8000) が違う
  • → デフォルトで ブロック

→ サーバー側で「許可」を明示する必要

設定 (最小)

from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware

app = FastAPI()

app.add_middleware(
    CORSMiddleware,
    allow_origins=["http://localhost:5173"],
    allow_methods=["*"],
    allow_headers=["*"],
)

各設定の意味

設定内容
allow_origins許可するフロント URL
allow_methods許可する HTTP メソッド (["GET", "POST", ...] or ["*"])
allow_headers許可するリクエストヘッダ
allow_credentialsCookie 送信を許可 (True にする場合 origins は ["*"] 不可)

本番設定

app.add_middleware(
    CORSMiddleware,
    allow_origins=[
        "https://my-app.example.com",   # ← 具体的に指定
    ],
    allow_credentials=True,
    allow_methods=["GET", "POST", "PATCH", "DELETE"],
    allow_headers=["Content-Type", "Authorization"],
)

→ 本番では allow_origins=["*"] 禁止 (セキュリティ)

preflight (OPTIONS)

ブラウザは POST 前に OPTIONS リクエストを送って確認:

  • サーバーが OPTIONS を許可するか
  • 許可レスポンスを受けてから本番 POST 実行

CORSMiddleware が自動処理してくれる。

エラー時の確認方法

ブラウザ DevTools → Network タブ:

  • ステータスコード
  • Response Headers の Access-Control-Allow-*

Console:

  • Blocked by CORS policy メッセージ

drill

drill/ — fill-middleware

ハンズオン

ch01-cors 演習ガイド

受講生向け演習問題集

採点の仕組み (読んでから始めてください)

採点テストは 「お題の通りに動くか」 を機械的にチェックします。

ドリルごとに 3つのタイプ があるので、各ドリル冒頭の 【タイプ】 を確認してください。

タイプ fill (穴埋め問題) — 文法・APIを知っているか

  • ___ (3個並んだアンダースコア) の空欄を埋める
  • 既存の構造は そのまま
  • ロジック自由度: 低 (お題どおりに直す)

タイプ add (機能追加問題) — 既存コードに機能を足せるか

  • 既存コードを残したまま、新しいエンドポイント/機能を 追加 する
  • 実装方法は自由 (関数名・変数名・内部ロジックは好きに)
  • ただしテストが要求する I/F (URL・HTTPメソッド・レスポンスのキー名) は守る
  • 既存テストを壊さないこと

タイプ build (ゼロベース実装問題) — 仕様から実装を組み立てられるか

  • ほぼ空の main.py から 自力で全部書く
  • ファイル構造・関数分割・命名・内部ロジック: 完全に自由
  • 守るのはインターフェースだけ: URL・HTTP メソッド・レスポンス JSON 形式
  • 一番ハードだが、実装力が一番つくタイプ

3タイプ共通で守ること

  • ファイル名 (main.py) は変えない
  • tests/ フォルダは触らない (採点ロジック)

このガイドのドリル一覧

#ドリル名タイトルタイプ難易度
101-fill-middlewareCORSMiddleware - クロスオリジンを許可する🔧 穴埋め

> 詰まったら ヒント ページを開く。それでも分からなければ講師に質問。

ドリル 1: CORSMiddleware - クロスオリジンを許可する

ドリル名: 01-fill-middleware

> 🔧 【タイプ: 穴埋め問題】 ___ の部分を埋めて完成させてください。既存のコード構造は変えないこと。

問題

___ を埋めて、Vue(http://localhost:5173)からのリクエストを許可する設定を完成させよ。

from fastapi.middleware.cors import ___   # クラス名を埋める

app = FastAPI()
app.add_middleware(
    ___,                                   # クラス名を埋める
    allow_origins=["http://localhost:5173"],
    allow_methods=["*"],
    allow_headers=["*"],
)

確認方法

  1. FastAPI を起動して http://localhost:8000/docs が開くこと
  2. Vue(:5173)から fetch('http://localhost:8000/tasks') を実行してブラウザコンソールに CORS エラーが出ないこと

ドリル 1: ヒント

ドリル名: 01-fill-middleware

> ⚠️ 自力で考えてから読んでください

> FastAPI の CORS ミドルウェアのクラス名は CORSMiddlewareimportadd_middleware の両方に同じクラス名を書く。

考えてみよう

既定では正解・不正解の判定はしません。自分のペースで「答えを見る」を。採点してほしい場合だけ「採点してほしい」を押してください。

ch01-cors 演習ガイド

受講生向け演習問題集

採点の仕組み (読んでから始めてください)

採点テストは 「お題の通りに動くか」 を機械的にチェックします。

ドリルごとに 3つのタイプ があるので、各ドリル冒頭の 【タイプ】 を確認してください。

タイプ fill (穴埋め問題) — 文法・APIを知っているか

  • ___ (3個並んだアンダースコア) の空欄を埋める
  • 既存の構造は そのまま
  • ロジック自由度: 低 (お題どおりに直す)

タイプ add (機能追加問題) — 既存コードに機能を足せるか

  • 既存コードを残したまま、新しいエンドポイント/機能を 追加 する
  • 実装方法は自由 (関数名・変数名・内部ロジックは好きに)
  • ただしテストが要求する I/F (URL・HTTPメソッド・レスポンスのキー名) は守る
  • 既存テストを壊さないこと

タイプ build (ゼロベース実装問題) — 仕様から実装を組み立てられるか

  • ほぼ空の main.py から 自力で全部書く
  • ファイル構造・関数分割・命名・内部ロジック: 完全に自由
  • 守るのはインターフェースだけ: URL・HTTP メソッド・レスポンス JSON 形式
  • 一番ハードだが、実装力が一番つくタイプ

3タイプ共通で守ること

  • ファイル名 (main.py) は変えない
  • tests/ フォルダは触らない (採点ロジック)

このガイドのドリル一覧

#ドリル名タイトルタイプ難易度
101-fill-middlewareCORSMiddleware - クロスオリジンを許可する🔧 穴埋め

> 詰まったら ヒント ページを開く。それでも分からなければ講師に質問。

ドリル 1: CORSMiddleware - クロスオリジンを許可する

ドリル名: 01-fill-middleware

> 🔧 【タイプ: 穴埋め問題】 ___ の部分を埋めて完成させてください。既存のコード構造は変えないこと。

問題

___ を埋めて、Vue(http://localhost:5173)からのリクエストを許可する設定を完成させよ。

from fastapi.middleware.cors import ___   # クラス名を埋める

app = FastAPI()
app.add_middleware(
    ___,                                   # クラス名を埋める
    allow_origins=["http://localhost:5173"],
    allow_methods=["*"],
    allow_headers=["*"],
)

確認方法

  1. FastAPI を起動して http://localhost:8000/docs が開くこと
  2. Vue(:5173)から fetch('http://localhost:8000/tasks') を実行してブラウザコンソールに CORS エラーが出ないこと

ドリル 1: ヒント

ドリル名: 01-fill-middleware

> ⚠️ 自力で考えてから読んでください

> FastAPI の CORS ミドルウェアのクラス名は CORSMiddlewareimportadd_middleware の両方に同じクラス名を書く。

ch01-cors 演習解説

⚠️ 自力でドリルを解いてから読んでください

ドリル 1: CORSMiddleware - クロスオリジンを許可する — 模範解答

ドリル名: 01-fill-middleware

import json
from pathlib import Path
from fastapi import FastAPI, HTTPException
from fastapi.middleware.cors import CORSMiddleware
from pydantic import BaseModel

app = FastAPI()
app.add_middleware(
    CORSMiddleware,
    allow_origins=["http://localhost:5173"],
    allow_methods=["*"],
    allow_headers=["*"],
)

DB_FILE = Path("tasks.json")

class Task(BaseModel):
    title: str
    done: bool = False

def load() -> list[dict]:
    if not DB_FILE.exists():
        return []
    return json.loads(DB_FILE.read_text(encoding="utf-8"))

def save(tasks: list[dict]) -> None:
    DB_FILE.write_text(
        json.dumps(tasks, ensure_ascii=False, indent=2),
        encoding="utf-8"
    )

@app.get("/tasks")
def get_tasks():
    return load()

@app.get("/tasks/{task_id}")
def get_task(task_id: int):
    tasks = load()
    for task in tasks:
        if task["id"] == task_id:
            return task
    raise HTTPException(status_code=404, detail="Task not found")

@app.post("/tasks", status_code=201)
def create_task(task: Task):
    tasks = load()
    new_task = {"id": len(tasks) + 1, **task.model_dump()}
    tasks.append(new_task)
    save(tasks)
    return new_task

@app.patch("/tasks/{task_id}")
def update_task(task_id: int, task: Task):
    tasks = load()
    for t in tasks:
        if t["id"] == task_id:
            t.update(task.model_dump())
            save(tasks)
            return t
    raise HTTPException(status_code=404, detail="Task not found")

@app.delete("/tasks/{task_id}", status_code=204)
def delete_task(task_id: int):
    tasks = load()
    tasks = [t for t in tasks if t["id"] != task_id]
    save(tasks)

ドリル 1: CORSMiddleware - クロスオリジンを許可する — 解説

ドリル名: 01-fill-middleware

from fastapi.middleware.cors import CORSMiddleware

app = FastAPI()
app.add_middleware(
    CORSMiddleware,
    allow_origins=["http://localhost:5173"],
    allow_methods=["*"],
    allow_headers=["*"],
)

> ポイント: add_middlewareapp = FastAPI()直後に書く。後ろに書いても動くが、エンドポイント定義より前に設定するのが慣例。allow_origins に指定するのは Vue の開発サーバーのオリジン(スキーム+ホスト+ポート)。

力試ししたい方は クイズ形式の演習(任意) もあります。読むだけでも十分です。