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

2024-12-23 08:43:00
admin
原创
94
摘要:问题描述:FastAPI 后端和 Next.js 前端都在 上运行localost。在同一台计算机上,前端使用 进行 API 调用没有任何问题。但是,在同一fetch网络上的另一台计算机(例如 )上,前端可以运行,但其 API 调用不再起作用。192.168.x.x我曾尝试使用代理作为 next.js,但仍然...

问题描述:

FastAPI 后端和 Next.js 前端都在 上运行localost。在同一台计算机上,前端使用 进行 API 调用没有任何问题。但是,在同一fetch网络上的另一台计算机(例如 )上,前端可以运行,但其 API 调用不再起作用。192.168.x.x

我曾尝试使用代理作为 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 上的另一台机器上打开浏览器时,收到“无法加载...”消息。

当我在任一机器上打开 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=["*"],
)

解决方案 1:

host标志设置为0.0.0.0

要从同一网络上的不同机器/IP(而不是运行服务器的本地机器)访问 FastAPI 后端,您需要确保将host标志设置为0.0.0.0。IP 地址0.0.0.0表示本地机器上的所有hostIPv4 地址。如果有两个 IP 地址,例如192.168.10.210.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 禁止0.0.0.0将其用作 IPv4 中的目标地址,而仅允许将其用作源地址,这意味着您不能http://0.0.0.0:8000在 Web 浏览器的地址栏中键入地址并期望它能正常工作。您应该改用本地计算机的 IPv4 地址之一,例如http://192.168.10.2:8000(或者,如果您在运行服务器的同一台本地计算机上测试 API,则可以使用http://127.0.0.1:8000http://localhost:8000)。

调整防火墙设置

您可能还需要调整防火墙允许外部访问您指定的网络port,方法是为 Python 创建入站防火墙规则。在 Windows 上,当允许程序(在本例中为 Python)通过 Windows 防火墙进行通信时,通常会自动创建此规则,默认情况下,这将允许任何 port网络上的流量(对于 TCP 和 UDP 连接)。

调整 CORS 设置

此外,如果您的前端正在监听来自后端的单独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=["*"],
)

使用 JavaScript 发出 HTTP 请求

最后,请查看此答案和此答案fetch,了解如何在从前端发出 JavaScript 请求时使用正确的来源/URL 。简而言之,在您的 JavaScript 异步请求中,您应该使用您在 Web 浏览器地址栏中输入的相同port域名(但使用后端服务器正在监听的号码)。例如,如果后端和前端服务器都在监听相同的 IP 地址和端口号,例如 — 例如192.168.178.23:8000使用时就是这种情况Jinja2Templates— 您可以通过在浏览器的地址栏中输入指向前端页面的 URL 来访问前端,例如http://192.168.178.23:8000/fetch请求应如下所示:

fetch('http://192.168.178.23:8000/people', {...

为方便起见,在上述情况下(即,当后端和前端都在同一台计算机上运行并在同一台计算机上监听时port),您可以使用相对路径,如上面链接的答案中所建议的那样。请注意,如果您在同一台计算机上本地测试应用程序,而不是在 LAN 上的另一台计算机上测试应用程序,而是使用或访问前端/后端,则这两个是不同的域/来源。因此,如果您在浏览器的地址栏中输入以访问前端页面,则不应使用例如发出请求,因为您会收到 CORS 错误(例如)。您应该使用,反之亦然。127.0.0.1`localhosthttp://127.0.0.1:8000/fetchfetch('http://localhost:8000/people'Access to fetch at [...] from origin [...] has been blocked by CORS policy...`fetch('http://127.0.0.1:8000/people'

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

解决方案 2:

这个问题困扰了我好几天 - 我在 Mac 上使用 fastapi/uvicorn,使用 Python 3.9。

当将 uvicorn 主机设置为 0.0.0.0 时,启动后我检查发现它只绑定到 TCP 127.0.0.1:

sudo lsof -PiTCP -sTCP:LISTEN

所以我深入研究了 uvicorn 代码,解决方案在这个文件中:/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/uvicorn/config.py

只需将其:sock.bind((self.host, self.port)) 更改为:sock.bind(('0.0.0.0', self.port))

完成此项更改后,我重新启动了 uvicorn,并且可以从网络上的任何机器访问该页面。

希望这对某人有帮助!

相关推荐
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1120  
  IPD(Integrated Product Development,集成产品开发)流程是一种广泛应用于高科技和制造业的产品开发方法论。它通过跨职能团队的紧密协作,将产品开发周期缩短,同时提高产品质量和市场成功率。在IPD流程中,CDCP(Concept Decision Checkpoint,概念决策检查点)是一个关...
IPD培训课程   75  
  研发IPD(集成产品开发)流程作为一种系统化的产品开发方法,已经在许多行业中得到广泛应用。它不仅能够提升产品开发的效率和质量,还能够通过优化流程和资源分配,显著提高客户满意度。客户满意度是企业长期成功的关键因素之一,而IPD流程通过其独特的结构和机制,能够确保产品从概念到市场交付的每个环节都围绕客户需求展开。本文将深入...
IPD流程   66  
  IPD(Integrated Product Development,集成产品开发)流程是一种以跨职能团队协作为核心的产品开发方法,旨在通过优化资源分配、提高沟通效率以及减少返工,从而缩短项目周期并提升产品质量。随着企业对产品上市速度的要求越来越高,IPD流程的应用价值愈发凸显。通过整合产品开发过程中的各个环节,IPD...
IPD项目管理咨询   76  
  跨部门沟通是企业运营中不可或缺的一环,尤其在复杂的产品开发过程中,不同部门之间的协作效率直接影响项目的成败。集成产品开发(IPD)作为一种系统化的项目管理方法,旨在通过优化流程和增强团队协作来提升产品开发的效率和质量。然而,跨部门沟通的复杂性往往成为IPD实施中的一大挑战。部门之间的目标差异、信息不对称以及沟通渠道不畅...
IPD是什么意思   70  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用