我有一个nodejs端点,该作业将通过POST HTTP调用由作业调用,该POST包含JSON格式的作业数据的详细信息?如何从python客户端监听webhook(https地址)以获取工作数据?
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');
});
});
python客户端:
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)
答案 0 :(得分:2)
通常,“ 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
。
另一方面,如果节点进程当前正在https://company/api/bats_hook/
处接收 POST请求,而您想在作业进入时通知python进程,那就是另一个问题。您可以通过axios.post
或类似的方法将信息发送到单独的python服务器上(这可能是最简单的选择),也可以将数据存储在python进程可以访问它的位置。 Redis是一个不错的选择,因为您可以轻松地设置发布/订阅系统,并且节点和python进程可以在同一台计算机上,也可以在不同的计算机上。如果它们在同一台计算机上,则还可以将数据转储到日志文件中,然后将其读入python。将数据从一个进程发送到另一个进程称为inter-process communication,并且变得很快。
如果要对node_redis和redis-py使用redis,则实现可能类似于:
// 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部分将仅用于本地调试,则与需要部署时会做出不同的选择。
答案 1 :(得分:1)
至少对我来说,您描述的设置看起来有些奇怪。
要澄清(主要是为我自己):
node.js
服务器,该服务器使用HTTP上的POST服务/api/bats_hook
端点。仅当 job 是将POST请求发送到您的node.js
服务器并在HTTP 200上接收JSON的Python部分时,条件才能成立。否则,您将尝试窃听从node.js
服务器获取外部请求及其相应的响应,而无需成为实际的通信伙伴。
如果 job 代码是Python,并且您想正确地发布node.js
服务,请使用requests
Python软件包。发送请求并获取JSON响应是两行代码。
如果 job 代码不在您的控制之下,或者您不希望Python“ hook”处于活动状态的位置,则可能是闻到了糟糕的体系结构或滥用了一种不希望使用的设置。请澄清。
答案 2 :(得分:0)
如果您尝试收听webhooks(http),则可以通过在python中创建一个http服务器来实现。 https://www.acmesystems.it/python_http
但是,如果您要查找网络套接字,则应使用@Thom建议的以ws://
开头的网址。
答案 3 :(得分:0)
您保存发布的数据并将其返回给感兴趣的消费者。这意味着您创建了一个网络挂钩网桥。
示例节点脚本:
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请求按“原样”保存。标头,查询和正文的内容未处理。提取后,客户端应相应地解析数据。
答案 4 :(得分:0)
在我的职业生涯中使用与付款相关的系统;通常,webhooks是您为启动的进程而获得的回调,但它与主流分开,因此不会无故保留内存。
按照你说的去做
[Webhook] => Python => Node.js
,我无法理解调用该过程的确切原因,该过程在整个周期中都增加了Webhook流。无论如何,都不应更改答案。
因此,基本上,您需要一个API端点,该端点将从此第三方Webhook调用。您决定如何使用python促进这一点完全是您的要求。使用诸如Django,性能等框架的API系统运行起来并不会那么复杂。与之相关的问题是我不愿赘述的。
让我知道您是否清楚。