在CPanel(Namecheap)部署的Flask API返回404错误:静态页面正常但API调用失败
看起来你遇到了Flask部署到CPanel子路径时的典型问题——静态页面能正常加载,但API请求全报404。我之前在Namecheap的CPanel上部署类似结构的Flask应用时也踩过几乎一模一样的坑,下面是几个最可能的原因和实际验证过的解决方法:
1. 先检查Passenger WSGI文件的核心配置
CPanel的Passenger完全靠passenger_wsgi.py来定位你的Flask应用,这个文件的路径和内容错了,API肯定找不到:
- 先去CPanel的应用管理器里确认:「应用根目录」选的是
backend,「应用启动文件」是src/passenger_wsgi.py(对应你的目录结构)。 - 然后打开
passenger_wsgi.py,确保内容是这样的(路径绝对不能错):
很多人在这里因为相对路径写错,导致Passenger根本找不到你的Flask实例,API自然就404了。import sys, os # 把当前文件所在的src目录加入Python的模块搜索路径 sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) # 从main.py导入application(你的main.py里已经把app赋值给application,这步是Passenger识别应用的关键) from main import application
2. 子路径导致API请求路径缺失前缀
你的应用部署在https://digitin.me/lawaibe/这个子路径下,但静态页面里的API请求大概率写成了/api/users这种根相对路径,浏览器会把它解析成https://digitin.me/api/users(少了/lawaibe前缀),直接就404了。
解决方法有两种,选一种就行:
方法一:让Flask自动处理子路径
在main.py里添加子路径配置,这样Flask会自动识别并处理前缀:
from flask import Flask, DispatcherMiddleware # ... 其他已有的代码 ... # 配置应用的子路径,和CPanel里的应用路径一致 app.config['APPLICATION_ROOT'] = '/lawaibe' # 用DispatcherMiddleware来包装WSGI应用,处理子路径路由 app.wsgi_app = DispatcherMiddleware(Flask('dummy'), { '/lawaibe': app.wsgi_app })
这样静态页面里的/api/users相对路径会被自动解析成/lawaibe/api/users,不用改前端代码。
方法二:修改前端的API请求路径
把静态页面里的API请求改成绝对路径(比如https://digitin.me/lawaibe/api/users),或者用页面相对路径./api/users(注意是点开头的相对路径,不是根路径)。
3. 静态路由通配符可能覆盖了API路由
你的serve函数用了通配符路由@app.route('/<path:path>'),会捕获所有路径。虽然你是先注册的API Blueprint,但在CPanel的子路径环境下,可能因为路径解析的优先级问题,静态路由先匹配到了API路径,导致API路由没被触发。
可以修改静态路由,让它只处理非API的路径:
from flask import abort, send_from_directory # ... 其他已有的代码 ... @app.route('/', defaults={'path': ''}) @app.route('/<path:path>') def serve(path): # 如果是API开头的路径,直接让Flask去匹配对应的Blueprint路由 if path.startswith('api/') or path == 'api': abort(404) # 触发404后,Flask会继续查找其他匹配的路由 # 原有的静态文件服务逻辑 static_folder_path = app.static_folder if static_folder_path is None: return "Static folder not configured", 404 # 处理静态文件或返回index.html(单页应用的SPA路由处理) if path != "" and os.path.exists(os.path.join(static_folder_path, path)): return send_from_directory(static_folder_path, path) else: return send_from_directory(static_folder_path, 'index.html')
另外要确保你的API Blueprint注册在静态路由之前(你的代码里已经这么做了,这步是对的)。
4. 查看CPanel的错误日志找细节
如果上面的方法都没用,一定要去CPanel的「错误日志」里看具体的报错信息——Passenger会把Flask的所有报错(比如模块导入失败、数据库连接错误、Blueprint注册失败)都写在这里,这些底层错误会导致API路由无法正常注册,表现出来就是404。比如如果你的src/models/user.py里有语法错误,那么user_bp这个Blueprint就注册失败,/api/users路径自然就不存在。
内容来源于stack exchange

