【问题标题】:Python Flask server getting 'code 400' errors (POST request sent from Telegram-webhook)Python Flask 服务器出现“代码 400”错误(从 Telegram-webhook 发送的 POST 请求)
【发布时间】:2020-04-10 12:29:07
【问题描述】:

上下文

我目前正在关注this tutorial。 - 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 V​​ALUES like \x00\x03')

代码 400,消息错误请求语法 ('RANDOM BYTE V​​ALUES like \x00\x03')

代码 400,消息错误请求版本 ('RANDOM BYTE V​​ALUES 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 文件。

【问题讨论】:

    标签: python flask bad-request


    【解决方案1】:

    您需要启用 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 保护您的网站,并反向代理您的机器人。这些选项通常会在最终产品中使用,所以我理解你现在是否不想与它们一起陷入困境,但无论如何这都是一种很好的做法。

    希望对您有所帮助。

    【讨论】:

    • 感谢您的回答! Telegram 确实期待 SSL 证书。我玩过 certbot、let'sEncrypt 和 sslforfree 与 Flask,但没有任何效果。最后,我选择使用 PHP 设置 webhook(这更容易,因为我已经在其上运行了 PHP 共享主机)。使用反向代理设置 nginx 或 apache 可能会在以后进行:D ...现在,我正在收到我的消息 :)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-12-21
    • 1970-01-01
    • 1970-01-01
    • 2016-10-30
    • 2016-08-25
    • 2020-03-05
    • 1970-01-01
    相关资源
    最近更新 更多