第4.2章:发送 GET 请求
学习时间: 45 分钟
1. GET:从太空舰队请求遥测数据
GET 请求 是获取数据的基本命令。在我们的任务控制中心,这相当于发出请求:“舰队控制中心,报告当前情况!”
我们将使用 fetch
向我们的 FastAPI 服务器发送两种类型的 GET 请求:
- 获取整个集合: “给我看我的整个舰队。”
- 获取单个资源: “给我 ID 为 2 的飞船的详细信息。”
💡 太空类比:
GET /spaceships
是向整个舰队发出的广播请求,要求它们报告自己的呼号。
GET /spaceships/3
是向特定飞船(国际空间站)发出的定向请求,要求它传输其系统的完整数据。
2. CORS 问题:“行星际干扰”
在我们发送请求之前,需要解决一个重要问题。默认情况下,出于安全考虑,浏览器禁止从一个“域” (file:///...
或 http://localhost:5500
) 加载的网页(我们的任务控制中心)向另一个“域” (http://127.0.0.1:8000
) 上的 API 发出请求。
此策略称为 CORS (跨域资源共享)。
为了允许我们的前端与后端通信,需要配置 FastAPI 服务器,使其告诉浏览器:“没问题,我信任来自该地址的请求。”
步骤 1:安装 python-multipart
这对于中间件的正常运行是必需的。
步骤 2:在 main.py
中配置 CORS
打开您的 FastAPI 项目中的 main.py
文件,并添加以下代码:
# main.py
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware # <-- 导入中间件
# ... 您的其余代码(模型、db_spaceships) ...
app = FastAPI(
title="Fleet Management API",
# ...
)
# --- CORS 配置 ---
# 指定哪些“域”(origins)可以发送请求
origins = [
"http://localhost",
"http://localhost:8080",
"http://127.0.0.1:5500", # VS Code 中 Live Server 的地址
"null" # 用于来自本地文件 file:/// 的请求
]
app.add_middleware(
CORSMiddleware,
allow_origins=origins, # 允许指定的源
allow_credentials=True,
allow_methods=["*"], # 允许所有方法(GET、POST 等)
allow_headers=["*"], # 允许所有头部
)
# --- 您的端点在下方 ---
@app.get("/")
# ...
uvicorn
,以使更改生效!
3. 获取所有飞船列表
我们将创建一个接口来显示我们的舰队。
步骤 1:更新 index.html
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title>任务控制中心 - 舰队管理</title>
<style>
body { font-family: sans-serif; }
.ship-list { list-style: none; padding: 0; }
.ship-list li { border: 1px solid #ccc; margin-bottom: 10px; padding: 15px; border-radius: 5px; }
</style>
</head>
<body>
<h1>太空舰队控制面板</h1>
<button id="load-fleet-btn">请求舰队数据</button>
<h2>飞行器列表:</h2>
<ul id="fleet-list" class="ship-list">
<li>等待命令...</li>
</ul>
<script src="app.js"></script> <!-- 连接外部脚本 -->
</body>
</html>
步骤 2:创建 app.js
在 index.html
旁边创建一个 app.js
文件。我们将所有逻辑都放在其中。
// app.js
const API_BASE_URL = 'http://127.0.0.1:8000'; // 我们的 FastAPI 服务器的 URL
const loadFleetBtn = document.getElementById('load-fleet-btn');
const fleetList = document.getElementById('fleet-list');
// 加载和显示舰队的函数
async function fetchAndDisplayFleet() {
try {
fleetList.innerHTML = '<li>正在加载遥测数据...</li>';
// 向 /spaceships 发送 GET 请求
const response = await fetch(`${API_BASE_URL}/spaceships`);
if (!response.ok) {
throw new Error(`网络错误:${response.status}`);
}
const ships = await response.json(); // 获取飞船数组
// 清空列表并显示数据
fleetList.innerHTML = '';
if (ships.length === 0) {
fleetList.innerHTML = '<li>注册表中没有任何飞行器。</li>';
return;
}
ships.forEach(ship => {
const listItem = document.createElement('li');
listItem.innerHTML = `
<strong>${ship.name} (ID: ${ship.id})</strong><br>
类型:${ship.type}<br>
发射年份:${ship.launch_year}<br>
状态:${ship.status}
`;
fleetList.appendChild(listItem);
});
} catch (error) {
console.error('无法加载舰队数据:', error);
fleetList.innerHTML = `<li>错误:${error.message}</li>`;
}
}
// 为按钮添加事件处理程序
loadFleetBtn.addEventListener('click', fetchAndDisplayFleet);
- async/await: 我们使用了处理 Promise 的新且更便捷的语法。我们将在第 4.5 章中详细探讨它。现在您只需知道
await
会“等待” Promise 的完成,而不会阻塞页面。 try...catch
:处理async
函数中错误的好方法。
步骤 3:测试
在浏览器中打开 index.html
(最好通过 VS Code 中的 Live Server 扩展,它会将其运行在 http://127.0.0.1:5500
)。点击“请求舰队数据”按钮。您来自 FastAPI 的飞船列表应该会显示在页面上!
4. 获取单个飞船的数据
现在,我们将添加一个表单,用于按特定 ID 请求信息。
步骤 1:在 index.html
中添加表单
<!-- index.html,在列表之后 -->
<hr>
<h2>按 ID 请求</h2>
<form id="ship-form">
<input type="number" id="ship-id-input" placeholder="请输入飞行器 ID" required>
<button type="submit">查找飞行器</button>
</form>
<div id="ship-details" class="ship-list"></div>
步骤 2:在 app.js
中添加逻辑
// app.js,文件末尾
const shipForm = document.getElementById('ship-form');
const shipIdInput = document.getElementById('ship-id-input');
const shipDetails = document.getElementById('ship-details');
async function fetchShipById(event) {
event.preventDefault(); // 阻止页面重新加载
const shipId = shipIdInput.value;
if (!shipId) {
alert('请输入 ID。');
return;
}
try {
shipDetails.innerHTML = '<li>正在搜索飞行器...</li>';
// 向 /spaceships/{id} 发送 GET 请求
const response = await fetch(`${API_BASE_URL}/spaceships/${shipId}`);
if (response.status === 404) {
throw new Error('注册表中未找到 ID 为此的飞行器。');
}
if (!response.ok) {
throw new Error(`网络错误:${response.status}`);
}
const ship = await response.json();
shipDetails.innerHTML = `
<li>
<strong>${ship.name} (ID: ${ship.id})</strong><br>
类型:${ship.type}<br>
发射年份:${ship.launch_year}<br>
状态:${ship.status}
</li>
`;
} catch (error) {
console.error(`搜索飞行器时出错 ${shipId}:`, error);
shipDetails.innerHTML = `<li>错误:${error.message}</li>`;
}
}
shipForm.addEventListener('submit', fetchShipById);
- 我们添加了对
404
状态码的单独处理,以便为用户提供更清晰的错误消息。
步骤 3:测试 刷新页面,输入现有飞船的 ID(例如,1),然后点击“查找飞行器”。您应该能看到它的数据。尝试输入一个不存在的 ID(例如,99)——您将看到错误消息。
巩固测验
🚀 本章总结:
您已成功设置“地球”与“太空”之间的通信信道,并学会了请求遥测数据!
- 🛡️ 您通过在 FastAPI 服务器上配置 CORS 解决了“行星际干扰”问题。
- 🛰️ 实现了一个函数,用于获取和显示所有航天器的完整列表。
- 🔭 创建了一个界面,用于通过 ID 请求特定航天器的数据。
任务控制中心正在接收数据! 在下一章中,我们将进入实战环节:发送命令来创建、更新和删除我们的宇宙飞船。
📌 检查:
- 确保您的 FastAPI 服务器已启动并配置了
CORSMiddleware
。- 检查在页面上点击“请求数据”按钮时是否出现飞船列表。
- 确保按 ID 搜索的表单能正确找到现有设备,并对不存在的设备报告错误。
⚠️ 如果出现错误:
- 浏览器控制台中出现 CORS 错误: 您可能在添加
CORSMiddleware
后未重新启动uvicorn
,或者您的前端地址(例如http://127.0.0.1:5500
)未添加到origins
列表中。- Failed to fetch: 检查您的 FastAPI 服务器是否已启动并可通过
API_BASE_URL
中指定的地址访问。