导航菜单

  • 1.什么是MCP
  • 2.MCP架构
  • 3.MCP服务器
  • 4.MCP客户端
  • 5.版本控制
  • 6.连接MCP服务器
  • 7.SDKs
  • 8.Inspector
  • 9.规范
  • 10.架构
  • 11.协议
  • 12.生命周期
  • 13.工具
  • 14.资源
  • 15.提示
  • 16.日志
  • 17.进度
  • 18.传输
  • 19.补全
  • 20.引导
  • 21.采样
  • 22.任务
  • 23.取消
  • 24.Ping
  • 25.根
  • 26.分页
  • 27.授权
  • 28.初始化
  • 29.工具
  • 30.资源
  • 31.结构化输出
  • 32.提示词
  • 33.上下文
  • 34.StreamableHTTP
  • 35.参数补全
  • 36.引导
  • 37.采样
  • 38.LowLevel
  • 39.任务
  • 40.取消
  • 41.ping
  • 42.根
  • 43.分页
  • 44.授权
  • 45.授权
  • Keycloak
  • asyncio
  • contextlib
  • httpx
  • pathlib
  • pydantic
  • queue
  • starlette
  • subprocess
  • threading
  • uvicorn
  • JSON-RPC
  • z
  • 1. 什么是 Starlette?
  • 2. 前置知识
  • 3. 安装
  • 4. 第一个应用
  • 5. 用装饰器定义路由
  • 6. 请求对象(request)常用属性
  • 7. 路径参数
  • 8. 查询参数与请求体
  • 9. 常用响应类型
  • 10. 添加 CORS 中间件
  • 11. 可独立运行的项目
  • 12. 与 FastAPI 的关系
  • 13. 常见问题
    • 13.1 如何只允许 POST 请求?
    • 13.2 如何返回 404 或 500?
    • 13.3 如何获取请求头?
  • 14. 总结

1. 什么是 Starlette? #

Starlette 是一个用来写 Web 接口的 Python 框架。你可以用它定义路由(如 /hello)、处理 HTTP 请求、返回 JSON 或 HTML 等响应。它轻量、支持异步,是 FastAPI 的底层框架。

为什么学 Starlette?

  • 想用 Python 写 Web API,又不想用 FastAPI 那么「重」的框架
  • 需要理解 FastAPI 的底层原理
  • 喜欢自己组合组件、控制细节

2. 前置知识 #

Web 框架与路由

  • Web 框架:帮你处理 HTTP 请求、组织代码、返回响应的工具库
  • 路由:把「URL 路径 + 请求方法」映射到具体的处理函数,例如 /hello → hello_handler

ASGI 是什么?

  • ASGI 是 Python 异步 Web 应用的接口规范
  • Starlette 是 ASGI 框架,必须通过 uvicorn 等 ASGI 服务器运行
  • 可以理解为:Starlette 写应用,uvicorn 负责接收请求并调用你的应用

异步(async/await)

  • Starlette 的路由处理函数通常是 async def
  • 在异步函数里可以 await 其他异步操作(如读数据库、调接口),不会阻塞整个程序

3. 安装 #

在命令行中执行:

pip install starlette uvicorn
  • starlette:Web 框架
  • uvicorn:用来运行 Starlette 的 ASGI 服务器

如需解析表单数据(如 application/x-www-form-urlencoded),可额外安装:

pip install python-multipart

4. 第一个应用 #

下面是一个完整的 Starlette 应用,定义了一个根路径 /,返回 JSON。

步骤 1:新建 app.py,写入:

# 导入 Starlette 应用类、路由、JSON 响应
from starlette.applications import Starlette
from starlette.responses import JSONResponse
from starlette.routing import Route


# 处理根路径 / 的请求,接收 request 参数
async def homepage(request):
    # 返回 JSON 响应,自动设置 Content-Type 为 application/json
    return JSONResponse({"message": "Hello, Starlette!"})


# 定义路由列表:路径 / 对应 homepage 函数
routes = [
    Route("/", endpoint=homepage),
]

# 创建 Starlette 应用,传入路由
app = Starlette(routes=routes)

步骤 2:在终端执行:

uvicorn app:app

步骤 3:浏览器访问 http://127.0.0.1:8000,会看到 {"message":"Hello, Starlette!"}。

5. 用装饰器定义路由 #

除了用 Route 列表,也可以用装饰器 `@app.route()` 添加路由,写法更简洁。

# 导入 Starlette 和 JSONResponse
from starlette.applications import Starlette
from starlette.responses import JSONResponse

# 先创建应用(此时没有路由)
app = Starlette()

# 用装饰器把路径 / 绑定到 homepage 函数
@app.route("/")
async def homepage(request):
    return JSONResponse({"message": "Hello, World!"})

注意:装饰器方式需要先 app = Starlette(),再写 `@app.route()`。两种方式可以混用。

6. 请求对象(request)常用属性 #

路由处理函数会收到一个 request 参数,通过它可以获取请求信息。

属性/方法 说明
request.method HTTP 方法,如 GET、POST
request.url 请求的完整 URL
request.headers 请求头(类似字典)
request.query_params 查询参数,如 ?name=张三
request.path_params 路径参数,如 /user/123 中的 123
await request.json() 解析 JSON 请求体
await request.body() 原始请求体(bytes)

7. 路径参数 #

路径参数是 URL 中的变量,例如 /user/张三 中的 张三。用 {name} 定义,在 request.path_params 中获取。

# 导入 Starlette 和 JSONResponse
from starlette.applications import Starlette
from starlette.responses import JSONResponse

app = Starlette()


# 根路径
@app.route("/")
async def index(request):
    return JSONResponse({"message": "欢迎"})


# 路径 /hello/xxx,xxx 会存入 path_params["name"]
@app.route("/hello/{name}")
async def greet(request):
    # 从路径参数中取出 name
    name = request.path_params["name"]
    return JSONResponse({"greeting": f"你好, {name}!"})


# 路径 /user/{user_id}/post/{post_id},多个路径参数
@app.route("/user/{user_id}/post/{post_id}")
async def user_post(request):
    user_id = request.path_params["user_id"]
    post_id = request.path_params["post_id"]
    return JSONResponse({"user_id": user_id, "post_id": post_id})

运行:uvicorn app:app,然后访问 http://127.0.0.1:8000/hello/张三。

8. 查询参数与请求体 #

查询参数:URL 中 ? 后面的部分,如 ?page=1&size=10。

请求体:POST 等请求携带的数据,常见格式为 JSON。

# 导入 Starlette 和 JSONResponse
from starlette.applications import Starlette
from starlette.responses import JSONResponse

app = Starlette()


# 获取查询参数,例如 /search?q=python&page=1
@app.route("/search")
async def search(request):
    # query_params 类似字典,支持 .get() 避免 KeyError
    q = request.query_params.get("q", "")
    page = request.query_params.get("page", "1")
    return JSONResponse({"q": q, "page": page})


# 接收 JSON 请求体,例如 POST /api/user,body: {"name":"小明","age":18}
@app.route("/api/user", methods=["POST"])
async def create_user(request):
    # 解析 JSON 请求体为字典
    data = await request.json()
    name = data.get("name", "")
    age = data.get("age", 0)
    return JSONResponse({"created": True, "name": name, "age": age})

注意:methods=["POST"] 表示只接受 POST 请求,不写则默认接受所有方法。

9. 常用响应类型 #

Starlette 提供多种响应类,常用如下:

类 说明
JSONResponse 返回 JSON
HTMLResponse 返回 HTML
PlainTextResponse 返回纯文本
Response 通用响应,可自定义状态码、头部
# 导入多种响应类型
from starlette.applications import Starlette
from starlette.responses import JSONResponse, HTMLResponse, PlainTextResponse, Response

app = Starlette()


# 返回 JSON
@app.route("/json")
async def json_view(request):
    return JSONResponse({"key": "value"})


# 返回 HTML
@app.route("/html")
async def html_view(request):
    return HTMLResponse("<h1>Hello</h1><p>这是 HTML</p>")


# 返回纯文本
@app.route("/text")
async def text_view(request):
    return PlainTextResponse("纯文本内容")


# 自定义状态码和响应头
@app.route("/custom")
async def custom_view(request):
    return Response(
        content="自定义响应",
        status_code=201,
        headers={"X-Custom": "my-header"},
    )

10. 添加 CORS 中间件 #

当前端(如浏览器中的 JavaScript)请求你的 API 时,浏览器会做「跨域」检查。若接口未设置 CORS,可能被浏览器拦截。通过 CORS 中间件可以允许指定来源的跨域请求。

# 导入 Starlette、路由、响应、中间件
from starlette.applications import Starlette
from starlette.responses import JSONResponse
from starlette.routing import Route
from starlette.middleware import Middleware
from starlette.middleware.cors import CORSMiddleware


async def api_handler(request):
    return JSONResponse({"data": "ok"})


# 路由列表
routes = [
    Route("/api", endpoint=api_handler),
]

# 中间件列表:允许所有来源(开发时常用,生产环境建议指定具体域名)
middleware = [
    Middleware(CORSMiddleware, allow_origins=["*"]),
]

# 创建应用时传入 middleware,注意顺序:后添加的先执行
app = Starlette(routes=routes, middleware=middleware)

11. 可独立运行的项目 #

下面是一个包含多个路由、路径参数、查询参数、JSON 请求体和 CORS 的项目。

文件:demo_app.py

# 导入 Starlette 相关组件
from starlette.applications import Starlette
from starlette.responses import JSONResponse
from starlette.routing import Route
from starlette.middleware import Middleware
from starlette.middleware.cors import CORSMiddleware


# 根路径
async def index(request):
    return JSONResponse({"message": "Starlette 入门示例", "docs": "/hello/{name}, /search?q=xxx, POST /api/echo"})


# 路径参数示例
async def greet(request):
    name = request.path_params.get("name", "访客")
    return JSONResponse({"greeting": f"你好, {name}!"})


# 查询参数示例
async def search(request):
    q = request.query_params.get("q", "")
    return JSONResponse({"query": q, "results": []})


# POST JSON 示例
async def echo(request):
    data = await request.json()
    return JSONResponse({"echo": data})


# 路由定义
routes = [
    Route("/", endpoint=index),
    Route("/hello/{name}", endpoint=greet),
    Route("/search", endpoint=search),
    Route("/api/echo", endpoint=echo, methods=["POST"]),
]

# CORS 中间件
middleware = [
    Middleware(CORSMiddleware, allow_origins=["*"]),
]

# 创建应用
app = Starlette(routes=routes, middleware=middleware)

运行:uvicorn demo_app:app --reload

测试:

  • GET http://127.0.0.1:8000/
  • GET http://127.0.0.1:8000/hello/张三
  • GET http://127.0.0.1:8000/search?q=python
  • POST http://127.0.0.1:8000/api/echo,Body 选 JSON:{"test": 123}

12. 与 FastAPI 的关系 #

FastAPI 基于 Starlette 构建,在 Starlette 之上增加了:

  • 基于类型提示的请求验证(Pydantic)
  • 自动生成 API 文档(Swagger、ReDoc)
  • 更丰富的依赖注入

如何选择?

  • 需要自动文档、强类型验证 → 用 FastAPI
  • 需要轻量、自己控制细节、写中间件或底层工具 → 用 Starlette

13. 常见问题 #

13.1 如何只允许 POST 请求? #

在 Route 中指定 methods:

# 导入路由和响应
from starlette.routing import Route
from starlette.responses import JSONResponse

# 只接受 POST
Route("/submit", endpoint=submit_handler, methods=["POST"])

13.2 如何返回 404 或 500? #

使用 HTTPException 或自定义 Response 的状态码:

# 导入 HTTPException
from starlette.exceptions import HTTPException

@app.route("/notfound")
async def notfound(request):
    # 抛出 404,Starlette 会转换为响应
    raise HTTPException(status_code=404, detail="未找到")

13.3 如何获取请求头? #

通过 request.headers,类似字典:

# 获取 User-Agent
user_agent = request.headers.get("user-agent", "")

# 获取 Authorization
auth = request.headers.get("authorization", "")

14. 总结 #

  • Starlette 是轻量级 ASGI 框架,适合写 Web API
  • 用 Route 或 `@app.route()定义路由,处理函数为async def xxx(request)`
  • 通过 request.path_params、request.query_params、await request.json() 获取请求数据
  • 用 JSONResponse、HTMLResponse 等返回响应
  • 用 Middleware(CORSMiddleware, ...) 处理跨域
  • 通过 uvicorn app:app 运行应用
← 上一节 queue 下一节 subprocess →

访问验证

请输入访问令牌

Token不正确,请重新输入