Python web框架fastapi中间件的使用,CORS跨域详解
作者:mmseoamin日期:2024-03-20

Python web框架fastapi中间件的使用,CORS跨域详解,在这里插入图片描述,第1张

✨✨ 欢迎大家来到景天科技苑✨✨

🎈🎈 养成好习惯,先赞后看哦~🎈🎈

所属专栏:Fastapi

景天的主页:景天科技苑

文章目录

  • fastapi中间件与CORS
  • 1、中间件
    • 1.创建中间件方法
    • 2.中间件里面添加响应头
    • 3.在请求处,设置拦截等等
    • 4.测试接口响应时间
    • 2、CORS
      • 1.同源策略带来的跨域问题
      • 2.跨域的解决方法
      • 3.CORS
        • 1.方式一
        • 2.方式二

          fastapi中间件与CORS

          1、中间件

          你可以向 FastAPI 应用添加中间件

          fastapi "中间件"是一个函数,它在每个请求被特定的路径操作处理之前,以及在每个响应之后工作.

          它接收你的应用程序的每一个请求.

          然后它可以对这个请求做一些事情或者执行任何需要的代码.

          然后它将请求传递给应用程序的其他部分 (通过某种路径操作).

          然后它获取应用程序生产的响应 (通过某种路径操作).

          它可以对该响应做些什么或者执行任何需要的代码.

          然后它返回这个 响应.

          Python web框架fastapi中间件的使用,CORS跨域详解,在这里插入图片描述,第2张

          请求与响应中间件,并不是需要每次都要写

          根据业务需求

          例如:如果向做个请求拦截中间件,拦截那些非法请求的ip,只需要在请求中间件中做限制即可,无需让该用户的请求到达业务逻辑层

          如果想做响应给每个用户的页面添加个作者信息的响应头,不需要在业务代码每个逻辑都做,只需要在响应中间件处做个响应中间件即可

          当然,也有两个中间件都用到的,例如测试请求的响应时间

          1.创建中间件方法

          要创建中间件你可以在函数的顶部使用装饰器 @app.middleware(“http”).

          中间件参数接收如下参数:

          • request.
          • 一个函数call_next,它将接收request,作为参数,然后执行下一个中间件.
            • 这个函数将 request 传递给相应的 路径操作.
            • 然后它将返回由相应的路径操作生成的 response.
            • 然后你可以在返回 response 前进一步修改它.

          请求中间件函数在最下面的最先执行

          案例:

          import time
          from fastapi import FastAPI  # FastAPI 是一个为你的 API 提供了所有功能的 Python 类。
          import uvicorn
          from fastapi import Request
          #创建应用程序,app是应用程序名
          app = FastAPI()  # 这个实例将是创建你所有 API 的主要交互对象。这个 app 同样在如下命令中被 uvicorn 所引用
          
          #定义中间件m2
          @app.middleware('http') #全局中间件
          async def m2(request:Request,call_next):
              #请求代码块
              print("m2 request")
              response = await call_next(request)
              #响应代码块
              print("m2 response")
              # 每个中间件的response,都是访问的逻辑函数的响应体
              return response
          #定义中间件m1
          @app.middleware('http') #全局中间件
          async def m1(request:Request,call_next):
              #请求代码块
              print("m1 request")
              response = await call_next(request)
              #响应代码块
              print("m1 response")
              #每个中间件的response,都是访问的逻辑函数的响应体
              return response
          
          @app.get("/user")
          def get_user():
              time.sleep(3)
              print("get_user函数执行")
              return {
                  "user": "current user"
              }
          @app.get("/item/{item_id}")
          def get_item(item_id: int):
              time.sleep(2)
              print("get_item函数执行")
              return {
                  "item_id": item_id
              }
          if __name__ == '__main__':
              #注意,run的第一个参数 必须是文件名:应用程序名
              uvicorn.run("main:app", port=8083,  reload=True,workers=1)
          

          我们测试接口/user,看下请求与响应顺序

          Python web框架fastapi中间件的使用,CORS跨域详解,在这里插入图片描述,第3张

          请求先走m1中间件,再走m2中间件。然后是逻辑函数响应,然后走走m2中间件响应,最后走m1中间件响应

          Python web框架fastapi中间件的使用,CORS跨域详解,在这里插入图片描述,第4张

          2.中间件里面添加响应头

          #定义中间件m2
          @app.middleware('http') #全局中间件
          async def m2(request:Request,call_next):
              #请求代码块
              print("m2 request")
              response = await call_next(request)
              #响应代码块
              print("m2 response")
              #添加响应头
              response.headers['author'] = 'jingtian'
              # 每个中间件的response,都是访问的逻辑函数的响应体
              return response
          

          Python web框架fastapi中间件的使用,CORS跨域详解,在这里插入图片描述,第5张

          测试,可以看到所有接口,都添加了个响应头

          Python web框架fastapi中间件的使用,CORS跨域详解,在这里插入图片描述,第6张

          Python web框架fastapi中间件的使用,CORS跨域详解,在这里插入图片描述,第7张

          3.在请求处,设置拦截等等

          if request.client.host in ['127.0.0.1']:
              return  Response(content='visit forbidden',status_code=403)
          

          Python web框架fastapi中间件的使用,CORS跨域详解,在这里插入图片描述,第8张

          访问接口

          Python web框架fastapi中间件的使用,CORS跨域详解,在这里插入图片描述,第9张

          也可以针对某个接口请求做限制

          if request.url.path in ["/user"]:
              return Response(content="visit forbidden",status_code=403)
          

          Python web框架fastapi中间件的使用,CORS跨域详解,在这里插入图片描述,第10张

          访问/user接口被拒绝

          Python web框架fastapi中间件的使用,CORS跨域详解,在这里插入图片描述,第11张

          访问其他接口正常

          Python web框架fastapi中间件的使用,CORS跨域详解,在这里插入图片描述,第12张

          4.测试接口响应时间

          可以在最后一个中间件做

          #定义中间件m1
          @app.middleware('http') #全局中间件
          async def m1(request:Request,call_next):
              #请求代码块
              print("m1 request")
              # if request.client.host in ['127.0.0.1']:
              #     return  Response(content='visit forbidden',status_code=403)
              start = time.time()
              if request.url.path in ["/user"]:
                  return Response(content="visit forbidden",status_code=403)
              response = await call_next(request)
              #响应代码块
              print("m1 response")
              #测试访问结束时间
              end = time.time()
              response.headers["ProcessTimer"] = str(end - start)
              #每个中间件的response,都是访问的逻辑函数的响应体
              return response
          我们针对每个接口做了响应时间阻塞
          @app.get("/user")
          def get_user():
              time.sleep(3)
              print("get_user函数执行")
              return {
                  "user": "current user"
              }
          @app.get("/item/{item_id}")
          def get_item(item_id: int):
              time.sleep(2)
              print("get_item函数执行")
              return {
                  "item_id": item_id
              }
          

          Python web框架fastapi中间件的使用,CORS跨域详解,在这里插入图片描述,第13张

          测试,/item接口响应时间为2秒多

          Python web框架fastapi中间件的使用,CORS跨域详解,在这里插入图片描述,第14张

          /user接口响应时间,响应3秒多

          Python web框架fastapi中间件的使用,CORS跨域详解,在这里插入图片描述,第15张

          2、CORS

          1.同源策略带来的跨域问题

          在前后端分离的项目中,前端和后端如果部署在同一个服务器,那么运行端口肯定不一样

          当前端发起请求到后端,这个时候发送的首先是 option 请求,而不是真正的请求

          后端拿到 option 请求后先判断有没有资格(权限),如果没有就会报错;如果有,则会继续请求你真正发起的请求

          一句话总结:在浏览器中运行的前端编写了和服务端通信的 JavaScript 代码,而服务端与前端处于不同“源”的情况

          协议相同+域名相同+端口号相同,浏览器才认为是同一个网站,才不会受到同源策略的影响,才可以正常的发送Ajax请求

          2.跨域的解决方法

          因为浏览器同源策略,也正是有了跨域限制,才使我们能安全的上网

          但是在实际开发中,有时候需要突破这样的限制,所以就诞生了 CORS

          3.CORS

          Cross-Origin Resource Sharing 跨域资源共享

          是一种基于 HTTP Headers 的机制,该机制通过允许服务器标示除了它自己以外的其它origin(域名,协议和端口),这样浏览器可以访问加载这些跨域资源

          CORS 还通过一种机制来检查服务器是否会允许要发送的真实请求,该机制通过浏览器发起一个到服务器托管的跨源资源的"预检"请求

          在预检中,浏览器发送的 Headers 中标示有 HTTP 方法和真实请求中会用到的头

          案例:

          后端代码:

          from fastapi import FastAPI  # FastAPI 是一个为你的 API 提供了所有功能的 Python 类。
          import uvicorn
          #创建应用程序,app是应用程序名
          app = FastAPI()  # 这个实例将是创建你所有 API 的主要交互对象。这个 app 同样在如下命令中被 uvicorn 所引用
          
          @app.get("/user")
          def get_user():
              print("user:jingtian", )
              return {
                  "user": "jingtian"
              }
          if __name__ == '__main__':
              #注意,run的第一个参数 必须是文件名:应用程序名
              uvicorn.run("CORS:app", port=8080,  reload=True)
          

          Python web框架fastapi中间件的使用,CORS跨域详解,在这里插入图片描述,第16张

          创建个前端页面

          
          
          
              
              Title
              
          
          
          

          click

          我们在本地用浏览器将html文件打开,可以看到协议,域名都与服务端不同

          Python web框架fastapi中间件的使用,CORS跨域详解,在这里插入图片描述,第17张

          此时,我们点击click,可以看到出现了同源跨域拦截

          Python web框架fastapi中间件的使用,CORS跨域详解,在这里插入图片描述,第18张

          后端改造,实现CORS,资源跨域共享

          添加个响应中间件

          1.方式一

          @app.middleware("http")
          async def CORSMiddleware(request: Request, call_next):
              response = await call_next(request)
              response.headers["Access-Control-Allow-Origin"] = "*"
              return response
          

          Python web框架fastapi中间件的使用,CORS跨域详解,在这里插入图片描述,第19张

          此时再在页面点击click,拿到数据

          Python web框架fastapi中间件的使用,CORS跨域详解,在这里插入图片描述,第20张

          看下响应头,就有了我们添加的响应头 Access-Control-Allow-Origin

          Python web框架fastapi中间件的使用,CORS跨域详解,在这里插入图片描述,第21张

          如果只允许部分网站来访问,那么就不要用*,使用允许访问的ip(域名)和端口

          2.方式二

          使用fastapi自带的中间件

          from fastapi.middleware.cors import CORSMiddleware
          #方式二
          origins = [
              "http://localhost:63342"
          ]
          app.add_middleware(
              CORSMiddleware,
              allow_origins="*",  # *:代表所有客户端
              allow_credentials=True,
              allow_methods=["GET", "POST"],
              allow_headers=["*"],
          )
          

          Python web框架fastapi中间件的使用,CORS跨域详解,在这里插入图片描述,第22张

          默认情况下,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。

          点击,也能实现跨域访问

          Python web框架fastapi中间件的使用,CORS跨域详解,在这里插入图片描述,第23张