为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

胡说叔叔 2022-06-07 19:28:16
我有一个 nodejs 端点,它将由一个带有 POST HTTP 调用的作业调用,该调用包含 JSON 格式的作业数据的详细信息?如何从 python 客户端监听 webhook(https 地址)以获取作业数据?https://company/api/bats_pushapp.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_datatry:    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.urlexcept Exception as e:    print (e)错误:-HTTPConnectionPool(host='localhost', port=3000): Read timed out. (read timeout=10.0)
查看完整描述

3 回答

?
阿波罗的战车

TA贡献1862条经验 获得超6个赞

通常,“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,则实现可能如下所示:


// javascript

var 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

  }); 

});

# python

import redis


r = redis.Redis()

p = r.pubsub()

p.subscribe('bats hook channel')


# This blocks and reads any messages from the "bats hook channel" as they come in

for message in p.listen():

    print(message)

很大程度上取决于您的预期用途。如果 python 部分仅用于本地调试,您将做出与需要部署不同的选择。


查看完整回答
反对 回复 2022-06-07
?
HUH函数

TA贡献1836条经验 获得超4个赞

你描述的设置看起来有点奇怪,至少对我来说是这样。

澄清(主要是为了我自己):

  • 您确实有一个使用 HTTP 上的 POSTnode.js服务端点的服务器。/api/bats_hook

  • 有一些作业正在运行,该访问不时指向获取信息。

  • 您要求一种使用 Python 获得该响应(=作业数据)的方法。

仅当作业是向您的服务器发送 POST 请求并在 HTTP 200 上接收 JSON 的 Python 部分时,条件才能成立node.js。否则,您将尝试窃听以从node.js服务器获取外部请求及其相应的响应,而不是实际的通讯伙伴。

如果作业代码是 Python,并且您想正确发布node.js服务,请使用requestsPython 包。发送请求并获取 JSON 响应是两行代码。

如果作业代码不受您的控制,或者不是您希望 Python“钩子”处于活动状态的位置,那么要么闻起来像糟糕的架构,要么以非预期的方式滥用设置。请说清楚。


查看完整回答
反对 回复 2022-06-07
?
慕娘9325324

TA贡献1783条经验 获得超4个赞

您保存发布的数据并将其返回给感兴趣的消费者。这意味着您创建了一个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.client

import json


print('\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 请求按“原样”保存。不处理标题、查询和正文的内容。客户端应在拉取后相应地解析数据。


查看完整回答
反对 回复 2022-06-07
  • 3 回答
  • 0 关注
  • 570 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信