FastAPI 2 - URL 请求及参数

本文深入探讨了FastAPI中的URL请求及参数处理,包括路径参数、查询参数(枚举、数据类型、长度限制、正则、列表等)、查询参数验证、路径参数与数值验证、Cookie和Header参数的使用。通过实例展示了如何实现各种参数验证和请求处理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

路径参数


学习自 https://www.bilibili.com/video/BV1sE411x7bi

在教程基础上,增加了 requests 请求。


一、URL 请求

No.7

# -*- coding: UTF-8 -*-
from fastapi import FastAPI

app = FastAPI()

@app.get("/me/xx")
async def read_item_me():
    return {"me": 'me'}
'''
访问 http://127.0.0.1:8000/me/xx
返回 {"me":"me"}
'''

@app.get("/me/{item_id}")
async def read_item(item_id: str):
    return {"item_id": item_id}
'''
http://127.0.0.1:8000/me/123
{"item_id":"123"}
'''

@app.get("/")
async def main():
    return {"message": "Hello,FastAPI"}
    
'''
访问 http://127.0.0.1:8000/
返回 {"message":"Hello,FastAPI"}
'''
   
if __name__ == '__main__':
    import uvicorn
    uvicorn.run(app, host="127.0.0.1", port=8001)
 

使用枚举 Enum

from enum import Enum

class Name(str, Enum):
    Allan = '张三'
    Jon   = '李四'
    Bob   = '王五'

app = FastAPI()


@app.get("/{who}")
async def get_day(who: Name):
    if who == Name.Allan:
        return {"who": who, "message": "张三是德国人"}
    if who.value == '李四':
        return {"who": who, "message": "李四是英国人"}
    return {"who": who, "message": "王五是法国人"}

'''
访问 http://127.0.0.1:8001/%E5%BC%A0%E4%B8%89 (张三)
{"who":"张三","message":"张三是德国人"}


访问 http://127.0.0.1:8001/%E6%9D%8E%E5%9B%9B  ( http://127.0.0.1:8001/李四 )
返回 {"who":"李四","message":"李四是英国人"}

访问 http://127.0.0.1:8001/Allan
返回 {"detail":[{"loc":["path","who"],"msg":"value is not a valid enumeration member; permitted: '张三', '李四', '王五'","type":"type_error.enum","ctx":{"enum_values":["张三","李四","王五"]}}]}
'''

@app.get("/")
async def main():
    return {"message": "Hello,FastAPI2"}

'''
访问 http://127.0.0.1:8000/
返回 {"message":"Hello,FastAPI2"}
'''


二、查询参数 Query Parameters

No.8

传递不同数据类型

fake_items_db = [{"item_name": "Foo"}, {"item_name": "Bar"}, {"item_name": "Baz"}]

@app.get("/items/")
async def read_item(skip: int = 0, limit: int = 10):
    return fake_items_db[skip : skip + limit]

'''
访问 http://127.0.0.1:8000/items/  
页面显示 [{"item_name":"Foo"},{"item_name":"Bar"},{"item_name":"Baz"}]

访问 http://127.0.0.1:8000/items/?skip=1&limit=2
页面显示:[{"item_name":"Bar"},{"item_name":"Baz"}]
'''
   

@app.get("/i/")
async def i(A: str = 'HI..', B: str = 'Hello..', C: str = 'He..'):
    return {'cc': A+B+C},{'dd': B+C}

'''
http://127.0.0.1:8000/i/
[{"cc":"HI..Hello..He.."},{"dd":"Hello..He.."}]

http://127.0.0.1:8000/i/?A=Sun
[{"cc":"SunHello..He.."},{"dd":"Hello..He.."}]

http://127.0.0.1:8000/i/?A=Sun..&C=Rain...
[{"cc":"Sun..Hello..Rain..."},{"dd":"Hello..Rain..."}]
'''


    
@app.get("/ii/")
async def ii(A: int = 0, B: int = 10, C: int = 20):
    return {'cc': A+B+C},{'dd': B+C}

@app.get("/iii/")
async def iii(A: int = 0, B: int = 10, C: int = 20):
    return 'A+B+C',A+B+C

'''
http://127.0.0.1:8000/iii/
"A+B+C",30]
'''
   
# bool与类型转换
@app.get("/xxx/{item_id}")
async def xxx(item_id: str, QQ: str = None, SS: bool = False):
    item = {"item_id": item_id}
    if QQ:
        item.update({"QQ": QQ})
    if not SS:  # 如果SS是假
        item.update(
            {"item_id": "This is SSSSSSS"}
        )
    return item

'''
# 传入的是路径,而非参数,所以不使用 ? 
http://127.0.0.1:8000/xxx/123
{"item_id":"This is SSSSSSS"}

http://127.0.0.1:8000/xxx/123?QQ=SUN&SS=True
{"item_id":"123","QQ":"SUN"}
'''
 

多路径 和 查询参数 和 必填字段


 

#多路径 和 查询参数 和 必填字段
@app.get("/user/{user_id}/item/{item_id}")
async def read_user_item(
    user_id: int, item_id: str, q: str = None, short: bool = False
):
    item = {"item_id": item_id, "owner_id": user_id}
    if q:
        item.update({"q": q})
    if not short:
        item.update(
            {"description": "This is an amazing item that has a long description"}
        )
    return item
'''
http://127.0.0.1:8000/user/1/item/2
{"item_id":"2","owner_id":1,"description":"This is an amazing item that has a long description"}

? 接参数,应该放最后面,而不是放在 user_id 之后 中间的位置
比如 http://127.0.0.1:8000/user/1?q=1/item/2  不对

http://127.0.0.1:8000/user/1/item/2?q=2 正确
返回  {"item_id":"2","owner_id":1,"q":"2","description":"This is an amazing item that has a long description"}
 
'''
 

三、查询参数和字符验证 Query Validations

No.10

1、长度限制


from fastapi import FastAPI, Query
from typing import List


# 限制长度
@app.get("/items/")
async def read_items(q: str = Query(..., min_length=3, max_length=50)):    
    #填None就是默认值   填 ...则是必填项 
    results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
    if q:
        results.update({"q": q})
    return results

'''
... 代表什么都没有,None 代表这里有东西,只是是 None
q: str = Query(..., min_length=3, max_length=50) 这样写,q 不是必填项
q: str = Query(None, min_length=3, max_length=50) 这样写,q 是必填项
 
'''

测试请求


import requests

def test1():
    
    item_id = 5
    q = 'qaqa'
    url = f'http://127.0.0.1:8000/items/?q={q}'
    # url = f'http://127.0.0.1:8000/items/'  
    ret = requests.get(url=url, timeout=10)
    print('ret 0 : ', ret)  # ret 0 :  <Response [200]>
    print('ret 1 : ', ret.text)
    # {"items":[{"item_id":"Foo"},{"item_id":"Bar"}],"q":"qaqa"}

    # 
    '''
    q 是必填项
    如果请求 http://127.0.0.1:8000/items/,返回 {"detail":[{"loc":["query","q"],"msg":"field required","type":"value_error.missing"}]}  

    如果 q = 'qa', 小于三位,则返回:
    {"detail":[{"loc":["query","q"],"msg":"ensure this value has at least 3 characters","type":"value_error.any_str.min_length","ctx":{"limit_value":3}}]}

    '''
 

2、正则


#正则表达式
@app.get("/items2/")
async def read_items2(
                        q: str = Query(None, min_length=3, max_length=50, regex="^nice")
                     ):
    results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
    if q:
        results.update({"q": q})
    return results

'''
q = 'nice to meet you'
url = f'http://127.0.0.1:8000/items2/?q={q}'
#  {"items":[{"item_id":"Foo"},{"item_id":"Bar"}],"q":"nice to meet you"}

q 需要匹配正则 ^nice
'''

3、列表

#列表
@app.get("/items3/")
async def read_items3(q: List[str] = Query(["foo", "bar"])):
    query_items = {"q": q}
    return query_items

'''
列表的默认值为 ["foo", "bar"]

request :  http://127.0.0.1:8002/items3/?q=foo&q=bar 
ret 1 :  {"q":["foo","bar"]}


request :  http://127.0.0.1:8002/items3/?q=foo 
ret 1 :  {"q":["foo"]}


request :  http://127.0.0.1:8000/items3/?q=['foo', 'bar']
Read timed out.


'''

请求

def test3():
    
    item_id = 5
    q = ['1', 'a']
    q = [ "foo", "bar" ]
    url = f'http://127.0.0.1:8000/items3/?q={q}'
    # url = f'http://127.0.0.1:8000/items/' 
    print('request : ', url) 
    ret = requests.get(url=url, timeout=10)
    print('ret 0 : ', ret)  # ret 0 :  <Response [200]>
    print('ret 1 : ', ret.text)
    # {"q":["['1', 'a']"]}
    # {"q":["['foo', 'bar']"]}
    # 如果不输入q,返回 {"q":["foo","bar"]}
 

4、别名参数

#别名参数
@app.get("/items4/")
async def read_items4(q: str = Query(None, alias="item-query")):
    results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
    if q:
        results.update({"q": q})
    return results

'''
使用别名 alias 查询
request :  http://127.0.0.1:8002/items4/?item-query=fish 
ret 1 :  {"items":[{"item_id":"Foo"},{"item_id":"Bar"}],"q":"fish"}

# 使用 q 来查询,没有效果;
request :  http://127.0.0.1:8002/items4/?q=fish 
ret 1 :  {"items":[{"item_id":"Foo"},{"item_id":"Bar"}]}
'''  

5、弃用参数

#弃用参数
@app.get("/items5/")
async def read_items5(
    q: str = Query(
        None,
        alias="item-query",
        title="Query string",
        description="Query string for the items to search in the database that have a good match",
        min_length=3,
        max_length=50,
        regex="^fixedquery$",
        deprecated=True,
    )
):
    results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
    if q:
        results.update({"q": q})
    return results

'''


'''  

四、路径参数与数值验证

No.11


from fastapi import FastAPI, Path, Query

app = FastAPI() 

@app.get("/items/{item_id}")
async def read_items(
    item_id: int = Path(..., title="The ID of the item to get", ge=50, le=100),#ge 大于等于 gt是大于 le是小于等于
    q: str       = Query(None, alias="item-query"),
    size: float  = Query(1, gt=0, lt=10.5)
                    ):
    results = {"item_id": item_id}
    if q:
        results.update({"q": q})
    return results
'''
request :  http://127.0.0.1:8004/items/12
ret 0 :  <Response [422]>
ret 1 :  {"detail":[{"loc":["path","item_id"],"msg":"ensure this value is greater than or equal to 50","type":"value_error.number.not_ge","ctx":{"limit_value":50}}]}

request :  http://127.0.0.1:8004/items/65 
ret 1 :  {"item_id":65}
'''


五、Cookie Parameters

No.16

# -*- coding: UTF-8 -*-
from fastapi import Cookie, FastAPI

app = FastAPI()


@app.get("/items/")
async def read_items(*, ads_id: str = Cookie(None)):
    return {"ads_id": ads_id}
 
if __name__ == '__main__':
    import uvicorn
    uvicorn.run(app, host="127.0.0.1", port=8000)

def test1():
     
    url = 'http://127.0.0.1:8000/items/' 

    headers = {'Cookie':'ads_id=100'}     
    headers = {'Cookie':'ads_id=100;ads_id=199'}  # 多个赋值之间用分号;而非逗号隔开;相同键取最后一个赋值。

    print('request : ', url) 
    ret = requests.get(url=url, headers=headers, timeout=10)
    print('ret 0 : ', ret)  
    print('ret 1 : ', ret.text) # {"ads_id":"199"}

六、Head Patameters

No.17

from fastapi import FastAPI, Header
from typing import List
app = FastAPI()


@app.get("/items/")
async def read_items(*, user_agent: str = Header(None), users_agent: str = Header(None)):
    return  {"User-Agent": user_agent},{"AAAAA": user_agent},{'ABCD': users_agent}
            
@app.get("/items2/")
async def read_items2(x_token: List[str] = Header(None)):
    return {"X-Token values": x_token}
    

def test2():
     
    url = 'http://127.0.0.1:8000/items/' 

    headers = {'user_agent':'a1', 
                'User-Agent':'a2', 
                'users_agent':'a3'}     

    print('request : ', url) 
    ret = requests.get(url=url, headers=headers, timeout=10)
    print('ret 0 : ', ret)  
    print('ret 1 : ', ret.text)  #  [{"User-Agent":"a2"},{"AAAAA":"a2"},{"ABCD":null}]

def test2(): 
    url = 'http://127.0.0.1:8000/items2/'  
    headers = {'x-token':['b1', 'b2', 'b3'] } # 报错  Value for header {x-token: ['b1', 'b2', 'b3']} must be of type str or bytes, not <class 'list'> 
    headers = {'x-token':'b1,b2,b3' }     
    print('request : ', url) 
    ret = requests.get(url=url, headers=headers, timeout=10)
    print('ret 0 : ', ret)  
    print('ret 1 : ', ret.text) #  {"X-Token values":["b1,b2,b3"]}

伊织 2021-11-28

### 配置 FastAPI 中的 `strict-origin-when-cross-origin` CORS 设置 为了配置 FastAPI 应用程序中的 `strict-origin-when-cross-origin` 跨域资源共享 (CORS),可以利用 FastAPI 提供的强大中间件功能来实现这一点。具体来说,通过自定义 `CORSMiddleware` 的参数能够满足这一需求。 下面是一个具体的例子展示如何设置: ```python from fastapi import FastAPI from fastapi.middleware.cors import CORSMiddleware app = FastAPI() origins = [ "http://localhost", "http://localhost:8080", ] app.add_middleware( CORSMiddleware, allow_origins=origins, allow_credentials=True, allow_methods=["*"], allow_headers=["*"], expose_headers=['Content-Type', 'Authorization'], ) @app.get("/") async def main(): return {"message": "Hello World"} ``` 上述代码片段展示了基本的 CORS 配置方法[^1]。然而要特别针对 `strict-origin-when-cross-origin` 进行配置,则需要进一步调整响应头以确保当请求来自不同源时只返回原始站点地址作为Referer值;而同源情况下则保持完整的URL路径不变。这可以通过修改服务器端发送给客户端的特定HTTP头部字段完成,在FastAPI中可通过扩展现有的中间件逻辑或创建新的依赖项注入器来达成目的。 对于更复杂的场景,如果希望严格控制跨站请求的安全策略并遵循 `strict-origin-when-cross-origin` 行为模式,建议深入研究官方文档以及相关RFC标准文件获取更多信息[^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值