现代的接口路由处理方式

本文涉及的产品
服务治理 MSE Sentinel/OpenSergo,Agent数量 不受限
可观测可视化 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 小结

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

目录
相关文章
|
1月前
接口
使用使用接口的时候,需要注意: 1.接口是没有静态代码块或者构造方法的。 2,一个类只能继承一个,但是一个类可以同时实现多个接口。 格式: public class MyInterfaceImpl implements MyInterfaceA,MyInterfaceB {} 3.如果实现类所实现的多个接口当中,存在重复的抽象方法,那么只需要覆盖重写一次即可。 4、如果实现类没有覆盖重写所有接口当中的所有抽象方法,那么实现类就必须是一个抽象类。 5如果实现类锁实现的多个接口当中,存在重复的默认方法,那么实现类一定要对冲突的默认方法进 行覆善重写。 6.一个类如果直接父类当中的方法,和接口当中的
10 0
|
27天前
|
XML 前端开发 JavaScript
现代接口中的路由处理方式
【5月更文挑战第10天】本文介绍了FastAPI的路由和响应处理。它允许将查询参数如`skip`和`limit`用于URL,并自动进行类型转换和验证。路径装饰器允许配置操作,如添加元数据、响应模型和状态码。 介绍了使用通配符处理多种请求。I作为高性能接口框架的特点,还需根据需求评估其适用性。
93 10
现代接口中的路由处理方式
|
1月前
|
数据采集 存储 NoSQL
如何优雅实现接口防刷
一文讲清楚如何用redis实现接口防刷
35 0
如何优雅实现接口防刷
|
9月前
快速生成通用接口业务配置
快速生成通用接口业务配置
|
10月前
|
Java
接口1
接口1
37 0
|
10月前
|
Java
接口2
接口2
48 1
|
10月前
|
Java
|
12月前
接口的使用
接口的使用
59 0
|
Java Maven
一文了解ConfigurationConditon 接口
在了解ConfigurationCondition 接口之前,先通过一个示例来了解一下@Conditional 和 Condition。
44 0