FastAPI 后端和 Next.js 前端都在 localost 上运行。在同一台计算机上,前端使用 fetch 进行 API 调用没有任何问题。然而,在另一台计算机上...
FastAPI 后端和 Next.js 前端都在 上运行 localost
。在同一台计算机上,前端使用 进行 API 调用 fetch
同一 上的另一台计算机 (例如 )上 192.168.x.x
,前端可以运行,但其 API 调用不再起作用。
我曾尝试使用代理作为 next.js,但仍然不起作用。
前端:
export default function People({setPerson}:PeopleProps) {
const fetcher = async (url:string) => await axios.get(url).then((res) => res.data);
const { data, error, isLoading } = useSWR(`${process.env.NEXT_PUBLIC_API}/people`, fetcher);
if (error) return <div>"Failed to load..."</div>;
return (
<>
{isLoading? "Loading..." :data.map((person: Person) =>
<div key={person.id}> {person.name} </div>)}
</>
)
}
Next.js 应用 env.local
在启动时加载该文件,其中包含: NEXT_PUBLIC_API=http://locahost:20002
后端:
rom typing import List
from fastapi import APIRouter, Depends
from ..utils.db import get_session as db
from sqlmodel import Session, select
from ..schemas.person import Person, PersonRead
router = APIRouter()
@router.get("/people", response_model = List[PersonRead])
async def get_people(sess: Session = Depends(db)):
res = sess.exec(select(Person)).all()
return res
前端运行: npm run dev
,并输出
ready - started server on 0.0.0.0:3000, url: http://localhost:3000
后端运行: uvicorn hogar_api.main:app --port=20002 --host=0.0.0.0 --reload
,并输出:
INFO: Uvicorn running on http://0.0.0.0:20002 (Press CTRL+C to quit)
同一台机器上 http://localhost:3000
打开浏览器时, 列表 Person
就会显示在屏幕上。
在同一网络上的另一台机器上 http://192.168.x.x:3000
on another machine on the same network ,出现“无法加载...”消息。
当我在任一机器上打开 FastAPI swagger 文档时,文档都正确显示,并且所有端点都按预期工作。
CORS 如下所示:
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
app = FastAPI()
origins = [
"http://localhost:3000",
]
app.add_middleware(
CORSMiddleware,
allow_origins=origins,
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
host
为 0.0.0.0
要从同一网络上的其他计算机/IP(而不是 运行服务器 )访问 FastAPI 后端,您需要确保将标志 host
设置为 0.0.0.0
。 IP 地址 0.0.0.0
表示 本地计算机上的 所有 host
有两个 IP 地址,例如 和 192.168.10.2
, 10.1.2.5
并且 上运行的服务器在 上 host
侦听 0.0.0.0
,则可以通过这两个 IP 访问它。 例如,通过命令行界面:
uvicorn main:app --host 0.0.0.0 --port 8000
或者,以编程方式:
if __name__ == '__main__':
uvicorn.run(app, host='0.0.0.0', port=8000)
请注意 , RFC 1122 prohibits 0.0.0.0
as a destination address in IPv4 ,而仅允许将其作为源地址,这意味着您不能 http://0.0.0.0:8000
在浏览器的地址栏中键入地址并期望它能正常工作。您应该改用本地计算机的 IPv4 地址之一,例如 http://192.168.10.2:8000
(或者,如果您在运行服务器的同一台本地计算机上测试 API,则可以使用 http://127.0.0.1:8000
or http://localhost:8000
)。
您可能还 需要 调整 防火墙 以 允许 外部访问 port
您指定的网络,方法是为 Python 创建入站防火墙规则。在 Windows 上,当允许程序(在本例中为 Python)通过 Windows 防火墙进行通信时,通常会自动创建此规则,默认情况下,这将允许 Any port
(对于 TCP 和 UDP 连接)。
此外,如果您的前端正在监听 单独 IP 地址和/或端口号,请确保已 CORS 并正确配置,如此 答案 和 此答案 。例如:
origins = ['http://localhost:3000','http://192.168.178.23:3000']
app.add_middleware(
CORSMiddleware,
allow_origins=origins,
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
最后,请查看 此答案 和 此答案 从前端 fetch
发出 JavaScript 请求时使用正确的来源/URL 与在浏览器地址栏中输入的域名 相同的 port
使用后端服务器正在监听的号码)。例如,如果后端和前端服务器都在监听相同的 IP 地址和端口号,例如 — 192.168.178.23:8000
时就是这种情况 Jinja2Templates
— 您可以通过在浏览器的地址栏中输入指向前端页面的 URL 来访问前端,例如 http://192.168.178.23:8000/
,请求 fetch
应如下所示:
fetch('http://192.168.178.23:8000/people', {...
为方便起见,在上述情况下(即后端和前端都在同一台计算机上运行并在同一台计算机上监听 p或t
),您可以使用相对路径,如上面链接的答案中建议的那样。 请注意 ,如果您在同一台计算机上本地测试应用程序,而不是在 LAN 上的另一台计算机上测试应用程序,而是使用 127.0.0.1
or localhost
访问前端/后端,则这两个是 不同的 域/来源。因此,如果您在浏览器的地址栏中输入 http://127.0.0.1:8000/
以访问前端页面,则不应 fetch
使用例如发出请求 fetch('http://localhost:8000/people'
,因为您会收到 CORS 错误(例如 Access to fetch at [...] from origin [...] has been blocked by CORS policy...
)。您应该使用 fetch('http://127.0.0.1:8000/people'
,反之亦然。
否则,如果前端 origin
与后端 不同 有关更多详细信息, 此答案 origin
),则应将其添加到后端 CORS 设置中的来源列表中(请参阅上面的示例)。