现代的接口路由处理方式

本文涉及的产品
容器服务 Serverless 版 ACK Serverless,317元额度 多规格
函数计算FC,每月15万CU 3个月
可观测可视化 Grafana 版,10个用户账号 1个月
简介: 【5月更文挑战第14天】FastAPI允许绑定路由到路由组,处理查询参数,如`skip`和`limit`,支持默认值和可选参数。查询参数自动转换并校验类型。路径装饰器用于配置操作,如添加元数据、响应模型和状态码。 通配符(*)可用于允许所有源,但处理凭据时需谨慎。FastAPI提供高性能和灵活性,适合特定业务场景。

1 绑定路由到路由组

2 处理路由URL中的查询参数

声明不属于路径参数的其他函数参数时,它们将被自动解释为"查询字符串"参数 如下skip limit都是查询参数。

参数解释:

    返回json 格式,原始值 为字符串
    http://127.0.0.1:1999/items/?skip=0&limit=1  # 限制查一个
    http://127.0.0.1:1999/items/?skip=0&limit=10 # 限制查10个

    :param skip: 对于的值为0
    :param limit: 对于的值 10
    参数原始值为 字符串,当你为它们声明一个Python类型时,
    它们将转换为该类型并针对该类型进行校验

    :return:

代码:

@app.get("/items/")
async def read_time(skip: int = 0, limit: int = 10):

    return fake_items_db[skip:skip + limit]

当你为它们声明了python类型,它们将转换为该类型并针对该类型进行校验。

应用于该路径参数的所有相同过程也适用于查询参数。

    编辑器支持
    数据解析
    数据校验
    自动生成文档
  • 默认值

    查询参数可以有默认值

      skip=0,limit=10 就是默认值
    
  • 可选参数

    使用设置None声明可选参数

  • 多个路径参数和 查询参数

    注意 如果 q 和 short 没有默认值 那就是必填查询参数
    在这个例子中,有2个查询参数:

      user_id: int,  user_id 必须的int类型 路径参数。
      item_id:str    item_id 必须的str 类型 路径参数
      q,一个必须的 没有默认值的str 类型参数。
      short,一个可选的 bool 类型参数。
    
      @app.get("/user/{user_id}/items/{item_id}")  # 多个路径参数 和 查询参数
      async def read_user_check(user_id: int, item_id:str, q: Optional[str], short:bool=False):
    

    q 是可选字符串参数 默认为 None
    FastAPI可以分辨 参数 item_id 是路径参数,而q不是,因此q是查询参数
    查询参数类型转换 声明不属于路径参数的其他函数参数时,它们将被自动解释为"查询字符串"参数

      short: 是否排序
      short=on 就是查询参数,FastAPI可以 识别 on,yes,True,true,1 为 python的True
      > http://127.0.0.1:1999/user/1/items/2?q=ok&short=false
      < response:
          {"item_id":"2","own_id":1,"q":"ok","description":"This is an amazing item that has a long description"}
    

3 路径装饰器

传递参数给路径操作装饰器 ,即可轻松地配置路径操作、添加元数据。

参数为:tags 和 status_code 和 response_model

@ 使用 status 快捷常量 HTTP_201_CREATED

@ 使用 tags 为路径操作 添加标签,tag一般由 str组成的 list构成, 可以用于 api 接口分组

@ response_model 定义返回数据结构模型

@app.post("/items/create", response_model=Item, status_code=status.HTTP_201_CREATED, tags=["items"])
async def create_item(item:Item):
    return item

@ summary 将在docs的 api右侧显示

@ description参数 与接口的docs 描述一样的效果

@ response_description 在docs中显示响应描述

@ , deprecated=True 可以将路径操作标记为弃用,无需直接删除,
docs中将显示 此接口为灰色

        POST  /items/create  Create an item

如果 description参数 与接口的docs 都设置了,那么只会显示一个描述 默认为路径中定义的,

  • 路径装饰器 的高级设置

    通过参数opeeration_id 设置 要使用的OpenAPO operationId

    ** 务必确保每个操作路径的 opeeration_id都是唯一的

    注释不输出到 api docs

    添加一个 \f (一个「换页」的转义字符)可以使 FastAPI 在那一位置截断用于 OpenAPI 的输出。

    剩余部分不会出现在文档中,但是其他工具(比如 Sphinx)可以使用剩余部分。

4 路由响应

    https://fastapi.tiangolo.com/zh/advanced/custom-response/

FastAPI 默认会使用 JSONResponse 返回响应

FastAPI 默认帮你把这个 item 放到 JSONResponse 中,又默认将其转换成了 dict,可以使用 Response重载,因为 JSONResponse 本身是一个 Response 的子类。

对于这些情况,在将数据传递给响应之前,你可以使用 jsonable_encoder 来转换你的数据。

使用api route的名称作为 operation_id

from controlers.apiroute import use_route_names_as_operation_ids   
from fastapi.responses import JSONResponse
from fastapi.encoders import jsonable_encoder
# from starlette import status   

技术细节 于 从fastapi 导入 status是一样的

你也可以使用 from starlette.responses import JSONResponse。

出于方便,FastAPI 会提供与 starlette.responses 相同的 fastapi.responses 给开发者。
但是大多数可用的响应都直接来自 Starlette。

  • 返回自定义response

    return Response(content=data, media_type="application/xml")

    XML响应
    HTML响应
    文档和重载Response
    直接返回 HTMLResponse

      def generate_html_response():
                  html_content = """
                  <html>
                      Look
                  </html>
                  """
                  return HTMLResponse(content=html_content, status_code=200)
    
                  @app.get("/items/", response_class=HTMLResponse)
                  async def read_items():
                      return generate_html_response()
    

    response_class 中也传入了 HTMLResponse,FastAPI 会知道如何在 OpenAPI 和交互式文档中使用 text/html 将其文档化为 HTML。

    通过返回函数 generate_html_response() 的调用结果,你已经返回一个重载 FastAPI 默认行为的 Response 对象

5 可用响应及自定义响应

使用 Response 来返回任何其他东西,甚至创建一个自定义的子类:

    content - 一个 str 或者 bytes。
    status_code - 一个 int 类型的 HTTP 状态码。
    headers - 一个由字符串组成的 dict。
    media_type - 一个给出媒体类型的 str,比如 "text/html"。

纯文本响应

     PlainTextResponse

UJSONResponse

     response_class=UJSONResponse

在处理某些边缘情况时,ujson 不如 Python 的内置实现那么谨慎。

    UJSONResponse 是一个使用 ujson 的可选 JSON 响应

重定向 RedirectResponse ,返回 HTTP 重定向。默认情况下使用 307 状态代码(临时重定向)。
return RedirectResponse("https://typer.tiangolo.com")

响应流 StreamingResponse 采用异步生成器或普通生成器/迭代器,然后流式传输响应主体

    return StreamingResponse(fake_video_streamer())

对类似文件的对象使用 StreamingResponse,如果您有类似文件的对象(例如,由 open() 返回的对象),则可以在 StreamingResponse 中将其返回。

包括许多与云存储,视频处理等交互的库。

        @app.get("/")
        def main():
            def iterfile():  # (1)
                with open(some_file_path, mode="rb") as file_like:  # (2)
                    yield from file_like  # (3)

            return StreamingResponse(iterfile(), media_type="video/mp4")

文件流FileResponse,异步传输文件作为响应。

与其他响应类型相比,接受不同的参数集进行实例化:

path - 要流式传输的文件的文件路径。
headers - 任何自定义响应头,传入字典类型。
media_type - 给出媒体类型的字符串。如果未设置,则文件名或路径将用于推断媒体类型。
filename - 如果给出,它将包含在响应的 Content-Disposition 中。

文件响应将包含适当的响应头,包含适当的 Content-Length,Last-Modified 和 ETag 的响应头。

        @app.get("/")
        async def main():
            return FileResponse(some_file_path)

响应的其他文档:

    https://fastapi.tiangolo.com/zh/advanced/additional-responses/

指浏览器中运行的前端拥有与后端通信的 JavaScript 代码,而后端处于与前端不同的「源」的情况

 源是协议 http,https
 域是 localhost,localhost.tiangolo.com 及端口 80 443 8080 的组合

因此 这些都是不同的源 因为协议和端口不同

     http://localhost
     https://localhost
     http://localhost:8080

假设浏览器有一个前端运行在http://localhost:8080

js 正在尝试与 http://localhost 后端通信,因为我们没有指定端口默认为80

然后 浏览器向后端发送一个 http OPTIONS请求。

如果后端发送适当的 headers 来授权来着这个不同源 8080 端口的通信。

浏览器将允许前端 js向后端发送请求。

为此后端必须有一个 允许的源 列表 并且包括 8080 端口。

6 通配符

也可以使用 * 声明这个列表,表示全部都允许。

但这仅允许某些类型通信,不包括所有涉及凭据的内容。

如Cookies 以及那些使用Bearer令牌授权 headers,所以最好显式设置指定允许的源。

使用 CORSMiddlewware 步骤:

    导入
    创建一个允许的源列表
    将其作为 中间件添加到 FastAPI

也可以指定后端是否允许:

    凭证 授权headers cookies等
    特定的HTTP方法
    特定的HTTP headers 或使用通配符 * 允许所有headers

这个 CORSMiddleware 实现所使用的默认参数较为保守,所以你需要显式地启用特定的源、方法或者 headers,以便浏览器能够在跨域上下文中使用它们。

支持以下参数:

    allow_origins - 一个允许跨域请求的源列表。例如 ['https://example.org', 'https://www.example.org']。你可以使用 ['*'] 允许任何源。
    allow_origin_regex - 一个正则表达式字符串,匹配的源允许跨域请求。例如 'https://.*\.example\.org'。
    allow_methods - 一个允许跨域请求的 HTTP 方法列表。默认为 ['GET']。你可以使用 ['*'] 来允许所有标准方法。
    allow_headers - 一个允许跨域请求的 HTTP 请求头列表。默认为 []。你可以使用 ['*'] 允许所有的请求头。Accept、Accept-Language、Content-Language 以及 Content-Type 请求头总是允许 CORS 请求。
    allow_credentials - 指示跨域请求支持 cookies。默认是 False。另外,允许凭证时 allow_origins 不能设定为 ['*'],必须指定源。
    expose_headers - 指示可以被浏览器访问的响应头。默认为 []。
    max_age - 设定浏览器缓存 CORS 响应的最长时间,单位是秒。默认为 600。

中间件响应两种特定类型的 HTTP 请求……

  • CORS预检请求

     带有 Origin 和 Access-Control-Request-Method请求头的OPTIONS请求
     这时,中间件将拦截传入的请求并进行响应
     出于提供信息的目的返回一个使用了适当CORS headers的200 或 400 响应
    
  • 简单请求

     任何带有Origin请求头的请求。这时 中间件将像平常一样传递请求
     在响应中包含适当的CORS headers
    

7 小结

我们在两个章节中,介绍这种新的业务提供框架,它的性能比流行框架更高,但是功能和稳定性稍差,依据业务选择可以分别考量。

目录
相关文章
Yii2.0框架中如何进行路由设置?它支持哪些路由规则?
Yii2.0框架中如何进行路由设置?它支持哪些路由规则?
442 0
|
5月前
如何实现嵌套路由
如何实现嵌套路由
28 1
|
24天前
|
JavaScript 容器
子路由的配置方法?
子路由的配置方法?
|
3月前
|
网络协议 网络虚拟化
如何对接收和发布的路由进行过滤?
如何对接收和发布的路由进行过滤?
|
6月前
|
XML 前端开发 JavaScript
现代接口中的路由处理方式
【5月更文挑战第10天】本文介绍了FastAPI的路由和响应处理。它允许将查询参数如`skip`和`limit`用于URL,并自动进行类型转换和验证。路径装饰器允许配置操作,如添加元数据、响应模型和状态码。 介绍了使用通配符处理多种请求。I作为高性能接口框架的特点,还需根据需求评估其适用性。
122 10
现代接口中的路由处理方式
|
6月前
|
前端开发
子路由的配置方法
子路由的配置方法
42 0
|
安全 API
路由的作用
路由的作用
57 1
|
网络协议 数据库 数据安全/隐私保护
路由控制概述
为了保证网络的高效运行以及在路由重分布的时候避免次优路由或者路由环路,有必要 对路由更新进行控制,常用的方法有被动接口、默认路由、静态路由、路由映射表、分布列 表、前缀列表、偏移列表、Cisco IOS IP服务等级协议(SLA)和策略路由。在进行路径控制 时,可能是多种方法的组合。
265 0
路由控制概述
|
前端开发 JavaScript
怎样实现路由封装
怎样实现路由封装
|
负载均衡 前端开发 Java
统一网关Gateway、路由断言工厂、路由过滤器及跨域问题处理
统一网关Gateway、路由断言工厂、路由过滤器及跨域问题处理
255 0