【问题标题】:Sending POST request to FastAPI app running on localhost向托管在 FastAPI 上的本地服务器发送 POST 请求
【发布时间】:2022-10-25 23:01:23
【问题描述】:

我有一个使用以下 Python 代码在 FastAPI 上运行的本地服务器:

from typing import Union
from fastapi import FastAPI
from pydantic import BaseModel
from fastapi.middleware.cors import CORSMiddleware

app = FastAPI()

origins = [
    "*"
    '''
    "http://localhost:8000/add_points/",
    "http://localhost:8000/check_points/",
    "http://localhost:8000/check_item_points/",
    "http://localhost:8000/redeem_points/"
    '''
]

app.add_middleware(
    CORSMiddleware,
    allow_origins=origins,
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

users = {"matt": 0}
items = {"ticket": 7}


class User(BaseModel):
    name: str
    points: float
    item: str


class AddTransaction(BaseModel):
    name: str
    points: float


class UserPoints(BaseModel):  # anything that extnds this base model is a pyantic model
    name: str
    points: float


class Item(BaseModel):
    name: str
    points: float


# -----Post Requests-----
@app.post("/add_points/")
def add_points(add_transaction: AddTransaction):
    global users
    user_id = add_transaction.name
    points = add_transaction.points
    users[user_id] = users.get(user_id, 0) + points
    return users[user_id]


@app.post("/check_points/")
def check_points(user_points: UserPoints):
    global users
    user_id = user_points.name
    points = user_points.points
    return users[user_id], points


@app.post("/check_item_points/")
def check_item_points(item: Item):
    global items
    item_id = item.name
    points = item.points
    return item[item_id], points


@app.post("/redeem_points/")  # user spends points (they lose points) gain an item
def redeem_points(add_transaction: AddTransaction, user_points: UserPoints, item: Item, user: User):
    global users
    global items
    user_id = add_transaction.name
    user_points = user_points.points
    item_points = item.points
    item_pre = item.name
    item_post = user.item
    if user_points >= item_points:
        user_points == user_points - item_points
        item_post == item_pre
        return users[user_id], users[user_points], users[item_post]
    else:
        return "insufficient funds"


# -----Get Requests-----
@app.get("/")
def read_root():
    return {"Hello": "World"}


# -----Put Requests-----
""""
@app.put("/items/{item_id}")
def update_item(item_id: int, item:Item):
    return {"item_name": item.name, "item_id": item_id}
"""

if __name__ == "__main__":
    import uvicorn

    uvicorn.run(app, host="0.0.0.0", port=8000)

我还有一个 HTML 脚本,只需单击按钮即可将发布请求发送到http://localhost:8000/add_points/。这是代码:

<!DOCTYPE html>
<html>

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>

<body>
<br><br><br><span style="text-align: center;"><button id="send">Send Request</button></span>
</body>

<script>
$("#send").on("click", evt => {
    $.post("http://localhost:8000/add_points/",
  {
    name: "string",
    points: 5.0
  },
  function(data, status){
    alert("Data: " + data + "\nStatus: " + status);
  });
});
</script>

</html>

但是,当我尝试发送 POST 请求时,我在 PyCharm 中收到以下错误:

信息:127.0.0.1:49413 - “OPTIONS /add_points/ HTTP/1.1” 400 错误请求

信息:127.0.0.1:49413 -“POST /add_points/ HTTP/1.1”422 无法处理的实体

我知道这些错误中至少有一个源于 CORS 政策限制,但是,这个项目是针对那些应该不是必须安装任何浏览器扩展来覆盖该策略。任何有关如何解决这些错误的建议将不胜感激!

编辑更新:

const url = new URL('localhost:8000/add_points/');
$("#send").on("click", evt => { fetch(url, 
      { 
        method: 'POST', 
       headers: {'Accept': 'application/json', 'Content-Type': 'application/json'}, 
          body: JSON.stringify({"name":"John", "points":50.0}) 
      }).then().catch((error) => { console.log(error.message); }); }); 

我仍然收到400 Bad Request 错误。

【问题讨论】:

  • 请确保在请求标头中包含'Content-Type': 'application/json'。相关答案也可以在hereherehere找到。至于 CORS,请参阅 thisthis
  • ..你永远不必覆盖 CORS 策略.但是,这似乎不是 CORS 问题。
  • 我在我的 HTML 中做了一些编辑,我的点击现在是这样的: const url = new URL('localhost:8000/add_points/'); $("#send").on("click", evt => { fetch(url, { method: 'POST', headers: {'Accept': 'application/json', 'Content-Type': 'application /json'},正文:JSON.stringify({"name":"John", "points":50.0}) }).then().catch((error) => { console.log(error.message) ; }); });我仍然收到 400 错误(错误请求)。我确定 Python 代码是正确的,因此非常感谢任何建议。
  • @mattsap 请查看answer below

标签: python html post fastapi


【解决方案1】:

如果您从Jinja2 templateHTMLResponse 访问前端,似乎是这种情况,如您的应用程序正在侦听的port 所示,以及您在@ 中定义的origins 987654323@——您不需要为您的应用程序启用CORS。如this answerthis answer 中所述,两个对象具有相同的原点只要protocoldomainport 全部匹配时。

请注意localhost127.0.0.1 被认为是不同的起源。因此,如果您从浏览器(通过在地址栏中输入 URL)http://127.0.0.1:8000/ 访问您的前端,那么您的异步 JS 请求(例如使用fetch)应该使用该域;例如:

fetch('http://127.0.0.1:8000/add',...

不是

fetch('http://localhost:8000/add',...

反之亦然。您可以随时使用相对的fetch 请求的路径(如下所示),因此,无论您使用什么域名(localhost127.0.0.1)从浏览器访问前端,您的应用程序都将正常工作。

工作示例:

请参阅相关答案hereherehere

应用程序.py

from fastapi import FastAPI, Request
from fastapi.templating import Jinja2Templates
from pydantic import BaseModel

app = FastAPI()
templates = Jinja2Templates(directory="templates")

class Item(BaseModel):
    name: str
    points: float

@app.post("/add")
def add_points(item: Item):
    return item
    
@app.get("/")
def index(request: Request):
    return templates.TemplateResponse("index.html", {"request": request})

模板/索引.html

<!DOCTYPE html>
<html>
   <body>
      <input type="button" value="Submit" onclick="submit()">
      <div id="responseArea"></div>
      <script>
         function submit() {
            fetch('/add', {
                 method: 'POST',
                 headers: {
                    'Accept': 'application/json',
                    'Content-Type': 'application/json'
                 },
                 body: JSON.stringify({'name': 'John', 'points': 50.0})
              })
              .then(resp => resp.text()) // or, resp.json(), etc.
              .then(data => {
                 document.getElementById("responseArea").innerHTML = data;
              })
              .catch(error => {
                 console.error(error);
              });
         }
      </script>
   </body>
</html>

【讨论】:

    猜你喜欢
    • 2022-11-07
    • 2020-09-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-12
    • 2016-08-01
    • 2018-10-31
    • 1970-01-01
    相关资源
    最近更新 更多