Python Flask 服务器收到 'code 400' 错误(POST 请求从 Telegram-webhook 发送)

Python Flask server getting 'code 400' errors (POST request sent from Telegram-webhook)

上下文

我目前正在关注 this tutorial。 - 使用 Python 教程 #3 的 Telegram Bot:创建 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”现在redirects/refers到正在设置的flask服务器


第三步

我正确设置了 Telegram-API webhook,从 Telegram 获得了以下响应代码:

{"ok":true,"result":true,"description":"Webhook was set"}


现在

在 Telegram 聊天中发送消息之前:没有错误

在聊天中发送消息后,弹出如下错误:

code 400, message Bad HTTP/0.9 request type ('RANDOM BYTE VALUES like \x00\x03')

code 400, message Bad request syntax ('RANDOM BYTE VALUES like \x00\x03')

code 400, message Bad request version ('RANDOM BYTE VALUES like \x00\x03')


我想要什么

根据教程,您可以在 Telegram 发出 POST 请求时编写一个 .json 文件(参见示例:here ).我想保存 Telegram webhook 提供的消息对象(如教程视频中所示)。使用 webhook 获取更新比不断查询 getUpdates() 方法要好;该方法 returns 旧消息也。


我试过什么

我尝试添加:

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' 可能适用于测试应用程序,但我也有预感电报需要 VALID 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 和反向代理来保护您的网站。这些选项通常会在最终产品中使用,所以我理解如果您现在不想与它们纠缠不清,但无论如何这都是很好的做法。

希望对您有所帮助。