如何从 python 客户端收听 webhook(https 地址端点)?

我有一个 nodejs 端点,它将由一个带有 POST HTTP 调用的作业调用,该调用包含 JSON 格式的作业数据的详细信息?如何从 python 客户端监听 webhook(https 地址)以获取作业数据?


https://company/api/bats_push


app.post("/api/bats_push",(req, res) => {

        //console.log("Calling bats_push...")

        const d = {

            method: req.method,

            headers: req.headers,

            query: req.query,

            body: ''

        }


        req.on('data', (c) => {

            d.body = d.body + c

        });



        req.on('end', () => {

            DATA.push(d);

            res.end('Saved');

        });

});

蟒蛇客户端:


data = {'name': 'joe', 'age': 20}

webhook_url = 'http://localhost:3000/api/bats_push'

json_data = json.dumps(data)

print json_data

try:

    r = requests.post(webhook_url,data=json_data.encode("utf8"),verify=False,headers={"Content-Type": "application/json"},timeout=10.0)

    print "posted"

    print(r.status_code, r.reason)

    print r.url

except Exception as e:

    print (e)

错误:-


HTTPConnectionPool(host='localhost', port=3000): Read timed out. (read timeout=10.0)



胡说叔叔
浏览 571回答 3
3回答

阿波罗的战车

通常,“webhook”是在线服务的一项功能,它在您部署了 HTTP 服务器的公共 URL 上向您的应用发送请求,以响应服务中的某些事件。需要在发送请求的任何内容中配置 url,它没有在接收代码中明确设置。监听 webhook 的是一个定义了合适端点的 HTTP 服务器。要创建服务器,您可以使用许多不同的包,但像Flask这样简单的东西是一个不错的起点。最小的视图代码看起来像:@app.route('/api/bats_hook')def bats_hook():    data = request.get_json()    print(data)    return 'OK'如果发送 POST(您的 nodejs 服务?)的任何东西都需要能够向您的服务器发送请求,那么您要么需要部署服务器以使其可公开访问,要么将服务设置为将请求发送到您的公共 IP . 如果它在同一台机器上,您可以使用私有 IP,或者localhost.另一方面,如果一个节点进程当前正在接收POST 请求https://company/api/bats_hook/,并且您想在有作业时通知 python 进程,这是一个不同的问题。您可以通过或类似方式将该信息发送到单独的 python 服务器axios.post(这可能是最简单的选择),或者将数据存储在 python 进程可以访问它的位置。Redis将是一个不错的选择,因为您可以轻松设置发布/订阅系统,并且 node 和 python 进程可以在同一台机器上,也可以在不同的机器上。如果它们在同一台机器上,您也可以将数据转储到日志文件并将其读入 python。从一个进程向另一个进程发送数据称为进程间通信,并且它很快变得复杂。如果您要使用 redis,使用node_redis和redis-py,则实现可能如下所示:// javascriptvar redis = require("redis"),    redisClient = redis.createClient();app.post("/api/bats_hook", (req, res, next) => {  console.log(req.query.params)  console.log(req.body)  console.log(req.body.name)  // This publishes a message to the "bats hook channel"  redisClient.publish("bats hook channel", JSON.stringify({    params: req.query.params,    body: req.body,  }));  res.status(200).json({    message: "BATS object",    posts: req.body  }); });# pythonimport redisr = redis.Redis()p = r.pubsub()p.subscribe('bats hook channel')# This blocks and reads any messages from the "bats hook channel" as they come infor message in p.listen():    print(message)很大程度上取决于您的预期用途。如果 python 部分仅用于本地调试,您将做出与需要部署不同的选择。

HUH函数

你描述的设置看起来有点奇怪,至少对我来说是这样。澄清(主要是为了我自己):您确实有一个使用 HTTP 上的 POSTnode.js服务端点的服务器。/api/bats_hook有一些作业正在运行,该访问不时指向获取信息。您要求一种使用 Python 获得该响应(=作业数据)的方法。仅当作业是向您的服务器发送 POST 请求并在 HTTP 200 上接收 JSON 的 Python 部分时,条件才能成立node.js。否则,您将尝试窃听以从node.js服务器获取外部请求及其相应的响应,而不是实际的通讯伙伴。如果作业代码是 Python,并且您想正确发布node.js服务,请使用requestsPython 包。发送请求并获取 JSON 响应是两行代码。如果作业代码不受您的控制,或者不是您希望 Python“钩子”处于活动状态的位置,那么要么闻起来像糟糕的架构,要么以非预期的方式滥用设置。请说清楚。

慕娘9325324

您保存发布的数据并将其返回给感兴趣的消费者。这意味着您创建了一个webhook 桥接器。示例节点脚本:const http = require('http');const URL = require('url');const DATA = [];const routes = {    '/api/bats_push': (req, res) => {        const d = {            method: req.method,            headers: req.headers,            query: req.query,            body: ''        }        req.on('data', (c) => {            d.body = d.body + c        });        req.on('end', () => {            DATA.push(d);            res.end('Saved');        });    },    '/api/bats_pull': (req, res) => {        const json = JSON.stringify(DATA, true);         DATA.length = 0;        res.statusCode = 200;        res.setHeader('content-type','application/json');        res.end(json);    }};const server = http.createServer((req, res) => {    const reqUrl = URL.parse(req.url);    const route = routes[reqUrl.pathname];    if (route) {         req.query = reqUrl.query;        route(req, res);    } else {        res.statusCode = 404;        res.end('Not found');    }})server.listen(8080,() => console.info('Server started'));并且,一个 python 客户端脚本来测试它:import http.clientimport jsonprint('\nPosting data...')conn1 = http.client.HTTPConnection('localhost', 8080)headers1 = {'content-type': 'application/json'}body1 = {'name': 'joe', 'age': 20}conn1.request('POST', '/api/bats_push?q=100', json.dumps(body1), headers1)resp1 = conn1.getresponse()print(resp1.status,resp1.reason, resp1.read())conn1.close()print('\nRetrieving data...')conn2 = http.client.HTTPConnection('localhost', 8080)headers2 = {'accept': '*'}conn2.request('POST', '/api/bats_pull', None, headers1)resp2 = conn2.getresponse()resp2Json = json.loads(resp2.read())print(resp2.status,resp2.reason, resp2Json)输出:Posting data...200 OK b'Saved'Retrieving data...200 OK [{'method': 'POST', 'headers': {'host': 'localhost:8080', 'accept-encoding': 'identity', 'content-length': '26', 'content-type': 'application/json'}, 'query': 'q=100', 'body': '{"name": "joe", "age": 20}'}]此外,HTTP 请求按“原样”保存。不处理标题、查询和正文的内容。客户端应在拉取后相应地解析数据。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Python