5

轻量的 WebHook 工具:歪脖虎克

 2 months ago
source link: https://soulteary.com/2024/04/06/lightweight-webhook-tool.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

轻量的 WebHook 工具:歪脖虎克

2024年04月06日阅读Markdown格式7550字16分钟阅读

本篇文章聊聊轻量的网络钩子(WebHook)工具:歪脖虎克。

这是一篇迟到很久的文章,在 21 年和 22 年的时候,我分享过两篇关于轻量的计划任务工具 Cronicle 的文章:《轻量的定时任务工具 Cronicle:前篇》、《使用 Docker 和 Traefik 搭建轻量美观的计划任务工具》。随后在文章的评论区和聊天群里,以及一些关联的开源项目 issue 区里,我总是能够收到关于最佳使用实践的问题。

开源项目 WebHook 的新版本:歪脖虎克

开源项目 WebHook 的新版本:歪脖虎克

我一般都会推荐将 Cron 工具和 WebHook 工具结合使用,说到具体的 WebHook 的时候,我当时一般都推荐“GitHub 上我 fork 的那个开源软件”:soulteary/webhook

自 2020 年,项目就陷入停滞状态

自 2020 年,项目就陷入停滞状态

四年前,在我 fork 的软件仓库几乎不在更新后,原始项目的技术债务堆积越来越严重。

最近正好在折腾异步流程比较多的模型应用,正好把这个项目也顺带做一个翻新(开源分叉)。关于项目具体分叉的原因,我会在文末再做详细展开。

好啦,让我们开始折腾。

鉴于文章的读者可能是新用户,那么让我们从前置知识的展开开始吧。

什么是 WebHook

WebHook 是一种常见的网络软件功能,通常用于连接异步的处理过程。直接介绍 WebHook 是什么会比较无趣,我们不妨参考 zapier 的 “WebHook 和 API 的异同” 来更直观的了解下 WebHook 的工作模式。

WebHook 和 API 的异同

WebHook 和 API 的异同

相比较我们熟悉的 API 调用,尽管他们都能够将数据从一个地方发送到另外一个地方,完成数据的交互,但是通常 WebHook 都是异步、单向的,不强制要求即刻返回数据结果。

通常情况下,支持 WebHook 的功能的软件中能够定义一些自定义回调函数(Custom Callback Function),来让其他的外部程序在合适的时候调用这些函数,让一些被预先定义好的程序被调用,特别适合一些场景:

  • 比如,常见的耗时比较久的程序执行完毕,推送信息到用户,可以回调一个通知接口。
  • 比如,常见的多次跳转的支付过程,当用户扫码授权后,银行接口会回调我们购买商品的平台,告诉平台用户付款了。

歪脖虎克(soulteary/WebHook)是什么

歪脖虎克(WebHook)是一个用 Go 语言编写的轻量可配置的实用工具,它允许你轻松、快速的创建 HTTP 服务(钩子)。

“歪脖虎克”
“歪脖虎克”

你可以使用它来执行配置好的命令。并且还能够将 HTTP 请求中的数据(如请求头内容、请求体以及请求参数)灵活的传递给你配置好的命令、程序。当然,它也允许根据具体的条件规则来便触发钩子。

举个例子,如果你使用的是 GitHub 或 Gitea,可以使用歪脖虎克设置一个钩子,在每次你推送更改到项目的某个分支时,这个钩子会在你运行服务的设备上运行一个“更新程序部署内容”的脚本。

如果你使用飞书、钉钉、企业微信或者 Slack,你也可以设置一个“传出 Webhook 集成”或“斜杠命令”,来在你的服务器上运行各种命令。我们可以通过聊天工具的“传入 Webhook 集成”功能处理接口的响应内容,直接向你或你的 IM 会话或频道报告执行结果。

歪脖虎克(WebHook)的项目目标非常简单,只做它应该做的事情

  • 解析请求头、请求体和请求参数
  • 检查钩子指定的运行规则是否得到满足
  • 最后,通过命令行参数或环境变量将指定的参数传递给指定的命令

至于具体的命令,从处理数据、存储数据到用远程命令打开空调、关闭电脑,一些都由你做主,你可以实现任何你想要的事情,它只负责在合适的时间点,接受执行指令。

开始实战之前,需要先获取程序文件。

下载“歪脖虎克”程序

目前下载程序有两个方法,下载在 GitHub 上通过自动化构建工具构建完毕的内容。

GitHub 程序发布页面

GitHub 程序发布页面

或者,使用 Docker 来快速下载程序。

# 下载最新的版本
docker pull soulteary/webhook:latest
# 下载指定版本的镜像
docker pull soulteary/webhook:3.4.5
# 下载包含了常用工具的镜像
docker pull soulteary/webhook:extend-3.4.5

当我们完成程序下载后,就可以开始使用啦。

查看软件文档(可选)

你可以在开源代码仓库的 docs 目录找到软件的中文使用文档,里面记录了:钩子的定义方法、具体的配置参数、如何解析和对请求参数进行调用命令参数绑定、各种常见的调用示例方法。

接下来,我们以一个简单的日常场景进行配置说明:使用 WebHook 和聊天工具进行联动,推送通知信息。

设置飞书的 WebHook 功能

其实我们日常使用的各种聊天工具,基本都支持使用 WebHook 方式进行交互。

嘿,你好呀👋

嘿,你好呀👋

我这里以飞书为例,来实现一个能够从外部调用飞书 WebHook 发送消息的机器人。

和其他的聊天软件类似,在飞书里创建机器人的最简方案是先创建一个“聊天群组”。

创建一个飞书群

创建一个飞书群

创建完毕后,戳开右上角的下拉菜单,找到“设置”选项。

找到设置菜单

找到设置菜单

进入设置选项后,能够看到群组的详细设置。

找到“机器人”菜单
找到“机器人”菜单

点击“机器人”设置,能够看到一个新的弹出框,包含了许多不同类型的机器人。

添加一个“WebHook”机器人

添加一个“WebHook”机器人

这里,我们选择自定义机器人(WebHook)。

在机器人配置界面

在机器人配置界面

在机器人配置界面中进行详细的自定义配置,比如可以设置个好看的头像,或者起个有趣的名字。

获得 WebHook 调用接口

获得 WebHook 调用接口

点击确定,我们就能够得到 WebHook 程序调用所需要的接口地址啦。保存好地址,我们一会要用到。

获得 WebHook 调用接口

获得 WebHook 调用接口

点击完成,机器人就被添加到群组中啦。

添加一个“WebHook”机器人

添加一个“WebHook”机器人

到这里为止,飞书的配置就完啦。

我们可以使用下面的命令,来验证接口是否能够被正确调用。

curl -X POST -H "Content-Type: application/json" --data '{"msg_type":"text","content":{"text":"嘿,你好呀👋"}}' \
    https://open.feishu.cn/open-apis/bot/v2/hook/6dca9854-381a-4bb9-a87b-33a222833e04

调用完毕,会出现类似下面的返回结果:

{"StatusCode":0,"StatusMessage":"success","code":0,"data":{},"msg":"success"}

在飞书的界面中,我们能够看到新出现的消息内容。

嘿,你好呀👋

嘿,你好呀👋

接下来,我们来把“歪脖虎克”和飞书连接在一起,让程序内容能够动态化。

在本文中,歪脖虎克可以将上面我们调用飞书 WebHook 接口的命令,赋予动态化调用的能力,并且提供更简单的调用接口,甚至提供额外的“接口验证”、关联的自动化处理信息能力。比如,当程序被调用的时候,能够根据具体的输入信息,结合上下文相关的资料,调用大模型接口,发送一段有趣的故事到群里。

考虑到复现的方便,我使用 Docker 环境的 “歪脖虎克”,直接使用二进制文件类似,只需要调整命令,在次不做赘述。

编写调用程序

我们先实现一个简单的程序,能够接收来自环境变量中的参数 $TEXT,并将参数中的内容传递到上面的飞书调用命令中(soulteary/webhook/example/lark/send-lark-message.sh):

#!/bin/sh

if [ -n "$TEXT" ]; then
    curl -X POST -H "Content-Type: application/json" --data {\"msg_type\":\"text\",\"content\":{\"text\":\"$TEXT\"}} \
        https://open.feishu.cn/open-apis/bot/v2/hook/6dca9854-381a-4bb9-a87b-33a222833e04
    echo "Send message successfully".
else
  echo "TEXT is empty"
fi

将上面的程序保存为 send-lark-message.sh (替换为你自己的飞书 API 地址)。然后我们对这个脚本赋予可执行权限:

chmod +x send-lark-message.sh

这里,我们也可以将上面的脚本程序替换成某些具备特定功能的程序,比如进行数据处理的程序,查询或者导出数据库文件的程序,调用大模型的能力等等。

编写配置文件

接下来,我们来编写一个让“歪脖虎克”来调用这个脚本的程序(soulteary/webhook/example/lark/hook-lark.yaml):

- id: lark
  execute-command: ./send-lark-message.sh
  command-working-directory: /app
  include-command-output-in-response: true
  include-command-out-in-response-on-error: true
  pass-environment-to-command:
    - source: url
      name: text
      envname: TEXT

我们将上面的内容保存为 hook-lark.yaml,“歪脖虎克” 的基本配置就准备完毕啦。

在上面的程序配置中,我们做了两件事,分别是:

  • 创建一个用于触发远程接口(飞书API)的脚本程序 send-lark-message.sh,能够在用户设置环境变量 TEXT 的时候,将环境变量内容传递到飞书发送消息参数中。
  • 创建了一个 id` 是 `lark 的 WebHook 配置,当 WebHook 被调用时,会自动调用位于 /app 目录的 send-lark-message.sh 脚本程序,将 URL 请求参数中的 text 内容转换为环境变量,传递给脚本程序,然后将脚本程序的执行结果展示给调用的用户。

编写容器配置文件或直接调用程序

为了稳定复现,我们再编写一个 docker-compose.yml 配置文件:

version: '2'

services:

  webhook:
    image: soulteary/webhook:extend-3.4.5
    ports:
      - 9000:9000
    environment:
      HOST: "0.0.0.0"
      PORT: 9000
      VERBOSE: true
      HOOKS: "/app/hook-lark.yaml"
    volumes:
      - ./hook-lark.yaml:/app/hook-lark.yaml
      - ./send-lark-message.sh:/app/send-lark-message.sh

保存这个配置文件和上面的两个配置到相同的目录后,我们执行 docker compose up,程序将运行在本机的 9000 端口。

如果你想直接运行程序,可以使用下面的命令:

./webhook --hooks ./example/lark/hook-lark.yaml --verbose 

一切顺利,你将看到类似下面的日志内容:

lark-webhook-1  | [webhook] 2024/04/06 07:52:11 version [3.4.5] starting
lark-webhook-1  | [webhook] 2024/04/06 07:52:11 setting up os signal watcher
lark-webhook-1  | [webhook] 2024/04/06 07:52:11 attempting to load hooks from /app/hook-lark.yaml
lark-webhook-1  | [webhook] 2024/04/06 07:52:11 os signal watcher ready
lark-webhook-1  | [webhook] 2024/04/06 07:52:11 found 1 hook(s) in file
lark-webhook-1  | [webhook] 2024/04/06 07:52:11 	loaded: lark
lark-webhook-1  | [webhook] 2024/04/06 07:52:11 serving hooks on http://0.0.0.0:9000/hooks/{id}

我们打开浏览器,访问 http://0.0.0.0:9000/hooks/lark?text=hey,将会很快得到下面的内容(命令行执行返回):

浏览器访问结果示意

浏览器访问结果示意

当我们再次打开飞书的界面,能够看到消息已经发送到飞书中啦。当然,这个工具并非只能连接一个 API ,你可以通过它将一堆服务都关联起来,进行一些自动化操作,或者做一些需要定时、被动触发自动化处理的工作。

飞书中出现的“歪脖虎克”发送的消息

飞书中出现的“歪脖虎克”发送的消息

还记得之前文章提到的实现“计划任务”的 Cronicle 小工具吗?你可以通过类似这样的方法,将计划任务中的具体实现,都使用“歪脖虎克”来实现,而将任务调度和编排交给 Cronicle,这样的话,你可以分别维护不同的程序,甚至在合适的情况下,灵活的切换程序为其他的组件。

其他:为什么要进行开源分叉

在项目的文档中,我提到了主要有两个原因:

第一个是,原作者维护的 webhook 程序版本,是从比较陈旧的 Go 程序版本慢慢升级上来的。

其中,包含了许多不再被需要的内容,以及非常多的安全问题亟待修正。

第二个是,我在几年前曾经提交过一个改进版本的 PR,但是因为种种原因被作者忽略,与其继续使用明知道不可靠的程序,不如将它变的可靠。

这样,除了更容易从社区合并未被原始仓库作者合并的社区功能外,还可以快速对有安全风险的依赖作更新。除此之外,我希望这个程序接下来能够中文更加友好,包括文档。

开源项目贡献
开源项目贡献

当然,开源软件世界里,talk is cheap, code is everything.,目前看来,这个硬分叉项目应该是及格的吧 :D

好啦,这篇文章就先写到这里,后面相关的文章中,我会试着分享一些更有趣的具体(偷懒)实践。

下篇文章再见。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK