如何从同一本地网络上的不同机器/IP 访问 FastAPI 后端?

Fed*_*lac 3 python ip localhost next.js fastapi

FastAPI 后端和 Next.js 前端都在localost. 在同一台计算机上,前端可以fetch毫无问题地进行 API 调用。然而,在同一网络上的另一台计算机上,例如,在 上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>)}
     </> 
  )
 }
Run Code Online (Sandbox Code Playgroud)

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 
Run Code Online (Sandbox Code Playgroud)

前端运行:npm run dev,并输出

ready - started server on 0.0.0.0:3000, url: http://localhost:3000
Run Code Online (Sandbox Code Playgroud)

后端运行: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)
Run Code Online (Sandbox Code Playgroud)

http://localhost:3000 当我在同一台计算机上打开浏览器时,Person屏幕上会显示列表。

当我在同一网络http://192.168.x.x:3000 上的另一台计算机上打开浏览器时,我收到“加载失败...”消息。

当我在任一计算机上打开 FastAPI swagger 文档时,文档会正确显示,并且所有端点都按预期工作。

CORS 看起来像这样:

ready - started server on 0.0.0.0:3000, url: http://localhost:3000
Run Code Online (Sandbox Code Playgroud)

Chr*_*ris 16

host标志设置为0.0.0.0

\n

要从同一网络上的不同计算机/IP(而不是运行服务器的本地计算机)访问 FastAPI 后端,您需要确保该host标志设置为0.0.0.0。IP地址0.0.0.0是指本机上的所有IPv4地址。如果 ahost有两个 IP 地址,例如192.168.10.210.1.2.5,并且在 上运行的服务器侦听host0.0.0.0则可以通过这两个 IP 地址访问它。例如,通过命令行界面:

\n
uvicorn main:app --host 0.0.0.0 --port 8000\n
Run Code Online (Sandbox Code Playgroud)\n

或者,以编程方式:

\n
if __name__ == \'__main__\':\n    uvicorn.run(app, host=\'0.0.0.0\', port=8000)\n
Run Code Online (Sandbox Code Playgroud)\n

请注意RFC 1122 禁止将0.0.0.0其作为 IPv4 中的目标地址,只允许将其作为源地址,这意味着您无法http://0.0.0.0:8000在浏览器的地址栏中键入并期望它能够正常工作。您应该使用本地计算机的 IPv4 地址之一,例如http://192.168.10.2:8000(或者,如果您在运行服务器的同一台本地计算机上测试 API,则可以使用http://127.0.0.1:8000http://localhost:8000)。

\n

调整防火墙设置

\n

您可能还需要通过为 Python 创建入站防火墙规则来调整防火墙允许外部访问您指定的内容。port在 Windows 上,当允许程序\xe2\x80\x94Python(在本例中为 \xe2\x80\x94)通过 Windows 防火墙进行通信时,这通常是自动创建的,默认情况下,这允许Any上的流量 port上的流量(对于 TCP 和 UDP 连接) 。

\n

调整 CORS 设置

\n

此外,如果您的前端正在侦听来自后端的单独IP 地址和/或端口号,请确保启用并正确配置了CORS,如本答案本答案中所述。例如:

\n
origins = [\'http://localhost:3000\',\'http://192.168.178.23:3000\']\n\napp.add_middleware(\n    CORSMiddleware,\n    allow_origins=origins,\n    allow_credentials=True,\n    allow_methods=["*"],\n    allow_headers=["*"],\n)\n
Run Code Online (Sandbox Code Playgroud)\n

在 JavaScript 中发出 HTTP 请求

\n

最后,请看一下这个答案这个关于fetch在从前端发出 JavaScript 请求时使用正确的来源/URL 的答案。简而言之,在 JavaScript 异步请求中,您应该使用在浏览器地址栏中输入的相同port域名(但使用后端服务器正在侦听的号码)。例如,如果后端和前端服务器都侦听相同的 IP 地址和端口号,例如\xe2\x80\x94 ,例如192.168.178.23:8000使用 \xe2\x80\x94 时就会出现这种情况,您可以通过以下方式访问前端Jinja2Templates在浏览器的地址栏中输入指向前端页面的 url,例如 ,http://192.168.178.23:8000/请求fetch应如下所示:

\n
fetch(\'http://192.168.178.23:8000/people\', {...\n
Run Code Online (Sandbox Code Playgroud)\n

为了方便起见,在上述情况下\xe2\x80\x94,即,当后端和前端都在同一台计算机上运行并在同一台port\xe2\x80\x94上侦听时,您可以使用相对路径,如上面链接的答案。请注意,如果您在同一台计算机上本地测试应用程序,而不是从 LAN 上的另一台计算机测试应用程序,而是使用127.0.0.1localhost访问前端/后端,则这两个是不同的域/源。因此,如果您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\',反之亦然。

\n

否则,如果前端与后端origin 不同(有关更多详细信息,请参阅此答案origin,则应将其添加到后端 CORS 设置中的来源列表中(请参阅上面的示例)。

\n