Heroku是否拦截HTTP请求?Flask部署接口POST返回404排查
问题结论
这个404问题和Heroku平台拦截请求、选择PostgreSQL还是MySQL数据库没有任何关系,纯粹是Flask路由注册的代码位置写错了。
你把api.add_resource(WaifuList, "/waifulist")这段注册路由的代码,还有db.create_all()的初始化代码,全写在了if __name__ == "__main__":判断块里。这个判断块只有当你直接执行python 启动脚本名.py本地运行项目的时候才会触发。
Heroku部署时是用Gunicorn这类WSGI服务器直接导入代码里的app实例启动服务的,根本不会执行if __name__ == "__main__":块里的代码。也就是说你部署到Heroku上的服务,从启动开始就压根没注册/waifulist这个接口,请求打过来自然返回404。你本地测试能正常跑,就是因为本地直接运行脚本触发了这个判断块里的路由注册逻辑。
修复步骤
- 把路由注册、数据库绑定的逻辑全部挪到
if __name__ == "__main__":块的外面,保证WSGI服务导入app实例的时候,这些逻辑就已经执行完成,参考代码结构如下:
from flask import Flask from flask_restful import Api from flask_sqlalchemy import SQLAlchemy app = Flask(__name__) # 配置数据库连接参数 app.config["SQLALCHEMY_DATABASE_URI"] = "你的数据库连接地址" app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False db = SQLAlchemy(app) api = Api(app) # 所有路由注册必须放在判断块外面 api.add_resource(WaifuList, "/waifulist") # 建表逻辑放在应用上下文里,启动时自动检查创建 with app.app_context(): db.create_all() if __name__ == "__main__": # 这里只留本地开发用的启动代码即可 app.run(debug=True)
- 不需要每次部署后手动进Heroku环境执行
db.create_all(),把建表逻辑放到全局应用上下文后,服务启动时会自动检查并创建不存在的表,不会覆盖已有数据,能避免漏执行初始化的问题。 - 你本地请求脚本里用HTTPS地址访问Heroku是正确配置,Heroku不会拦截正常的POST请求,路由注册完成后接口就能正常响应。
内容的提问来源于stack exchange,提问作者Chubbyman
相关产品推荐
相关产品推荐

