python - Python Flask 服务器出现“代码 400”错误(从 Telegram-webhook 发送的 POST 请求)
问题描述
语境
我目前正在关注本教程。- Telegram Bot 与 Python 教程 #3:创建 Bot 和 Webhook | 项目
第一步
我已经使用以下 python 代码设置了一个 Flask 服务器:
from flask import Flask
from flask import request
from flask import Response
import json
app = Flask(__name__)
@app.route('/', methods=['POST', 'GET'])
def index():
if request.method == 'POST':
print(request)
message = request.json()
with open('telegram_request.json', 'w', encoding='utf-8') as filename:
json.dump(message, filename, ensure_ascii=False, indent=4)
# prevents telegram from spamming
return Response('Ok', status=200)
else:
return """
<h1> Flask Server </h1>
<h2> Up and running </h2>
"""
if __name__ == '__main__':
app.run(debug=True, host='0.0.0.0', port=8443)
第二步
我在路由器中端口转发端口8443以使服务器对外界可见(教程中的隧道步骤)。
域名“ myprivatedomain.com:8443 ”现在重定向/引用已设置的烧瓶服务器。
第三步
我正确设置了Telegram-API webhook,从 Telegram 获得以下响应代码:
{"ok":true,"result":true,"description":"Webhook 已设置"}
现在
在Telegram 聊天中发送消息之前:没有错误。
在聊天中发送消息后,弹出以下错误:
代码 400,消息错误 HTTP/0.9 请求类型('RANDOM BYTE VALUES like \x00\x03')
代码 400,消息错误请求语法('RANDOM BYTE VALUES like \x00\x03')
代码 400,消息错误请求版本('RANDOM BYTE VALUES like \x00\x03')
我想要的是
根据教程,您可以在 Telegram 发出 POST 请求时编写一个 .json 文件(参见示例:here)。我想保存 Telegram webhook 提供的消息对象(如教程视频中所示)。使用 webhook 获取更新比不断查询 getUpdates() 方法要好;该方法也返回旧消息。
我试过的
我试图添加:
ssl_context='adhoc'
至
app.run(debug=True, host='0.0.0.0', port=8443)
使连接HTTPS。
使用此 ssl_context 时,也无法加载主页..
优选输出
当用户在 Telegram 聊天中发送消息时 --> Python 保存消息对象的 .json 文件。
解决方案
您需要启用 SSL 才能正常工作。Telegram 正在尝试与您的服务器启动 SSL 会话,但您没有启用 SSL,因此您看到了错误的请求。
ssl_context='adhoc'
可能适用于测试应用程序,但我也有一种预感,电报需要有效的SSL 证书,而不仅仅是临时(或自签名)证书。请注意视频中 URL 左侧的锁,并且缺少安全警告,该警告将与无效或自签名证书一起出现。
为确保 SSL 正常工作,设置ssl_context
为adhoc
,启动应用程序,然后浏览至https://myprivatedomain.com:8443/index
. 如果你可以浏览到它,那么 Telegram 也可以在获得有效证书后浏览到它,当然。
接下来,要获得有效(且免费)的 SSL 证书,您可以使用LetsEncrypt。
拥有有效的 SSL 证书和密钥文件后,您可以将ssl_context
参数传递app.run
给证书文件的路径和密钥文件的路径的元组("/path/to/fullchain.pem", "/path/to/privkey.pem")
您的完整运行功能应如下所示
app.run(debug=True, host='0.0.0.0', port=8443, ssl_context=("/path/to/fullchain.pem", "/path/to/privkey.pem"))
或者,您可以使用 Apache 或 Nginx 使用 SSL 保护您的网站,并反向代理您的机器人。这些选项通常会在最终产品中使用,所以我理解你现在是否不想与它们一起进入杂草,但无论如何这是一个好习惯。
希望这会有所帮助。
推荐阅读
- python - 解析表格并将其重新组合在一起
- javascript - 即使使用javascript导航到其他页面,如何保留选定的引导卡边框?
- android - React Native auth flow 在登录前后隐藏/显示电子商务应用程序中的部分/组件
- java - 如何通过java代码更改android中的颜色值
- python - 在python中对函数进行采样
- snakemake - 如何在snakemake文件中添加sbatch选项,例如--wait
- sql - 将 GROUPED BY SUM 查询与其他查询链接(使用 JOIN 或子查询)
- java - Spring boot AMQP并发监听器顺序执行?
- java - 我在打印数组中的元素时遇到问题,以便任何两个重复的元素出现一次
- javascript - 将 JS Div 反应为 png 或捕获 Div