如何读取Slack Webhook请求中的自定义请求头与查询参数
问题:Slack Bolt框架无法读取Webhook请求的自定义请求头和查询参数
使用curl向Slack频道的Webhook URL发送请求时携带了自定义请求头,但无法通过Slack Bolt框架读取这些自定义请求头及查询参数,尝试多种方式均未成功,求可行的读取方法。
相关代码
Python(Slack Bolt应用)
from typing import Optional import slack_sdk import os import logging from pathlib import Path from dotenv import load_dotenv from slack_bolt import App from slack_bolt.adapter.socket_mode import SocketModeHandler logging.basicConfig(level=logging.DEBUG) env_path = Path('.') / '.env' load_dotenv(dotenv_path=env_path) SLACK_VERIFICATION_TOKEN = os.environ['SLACK_VERIFICATION_TOKEN'] SLACK_SIGNING_SECRET = os.environ['SLACK_SIGNING_SECRET'] SLACK_BOT_TOKEN = os.environ['SLACK_BOT_TOKEN'] SLACK_APP_TOKEN = os.environ['SLACK_APP_TOKEN'] # Install the Slack app and get xoxb- token in advance app = App(token=SLACK_BOT_TOKEN, signing_secret=SLACK_SIGNING_SECRET) @app.event("message") def handle_message(event, say, context): text = event["text"] channel = event["channel"] target_channel='#slave2_public' # Access query parameters # query_params = context.request.query # print("Query Parameters:", query_params) # Access headers from the event headers = event.get("headers") print("Headers:", headers) # Access headers # headers = context.request.headers # print("Headers:", headers) if __name__ == "__main__": # export SLACK_APP_TOKEN=xapp-*** # export SLACK_BOT_TOKEN=xoxb-*** handler = SocketModeHandler(app, SLACK_APP_TOKEN) handler.start()
curl请求示例
curl -X POST -H 'Content-type: application/json' --data '{"text":"Hello, World!"}' -H "Channel_Name:slave1_private" <webhook URL>
解决方案
核心原因
Slack的Incoming Webhook机制是作为中间层转发消息:它接收你的curl请求后,仅提取消息内容(如text字段)转发到目标频道,不会保留自定义请求头、查询参数等元数据,因此你的Bolt应用无法从message事件中获取这些信息。同时,Socket Mode的Bolt应用通过WebSocket接收Slack格式化后的事件数据,本身也不包含原始请求的头和参数。
方案1:将自定义数据嵌入请求体
既然Webhook不传递头和参数,直接把自定义数据放到JSON请求体中,就能在Bolt的message事件里读取:
修改后的curl请求
curl -X POST -H 'Content-type: application/json' \ --data '{"text":"Hello, World!", "Channel_Name": "slave1_private"}' \ <webhook URL>
修改后的Bolt代码
@app.event("message") def handle_message(event, say, context): text = event["text"] # 读取自定义字段 channel_name = event.get("Channel_Name") print("Channel Name:", channel_name) # 其他业务逻辑...
如果Slack自动过滤了顶层自定义字段,可以用attachments字段携带:
curl -X POST -H 'Content-type: application/json' \ --data '{ "text":"Hello, World!", "attachments": [ {"text": "", "fields": [{"title": "Channel_Name", "value": "slave1_private", "short": true}]} ] }' \ <webhook URL>
对应读取代码:
@app.event("message") def handle_message(event, say, context): attachments = event.get("attachments", []) for att in attachments: for field in att.get("fields", []): if field["title"] == "Channel_Name": print("Channel Name:", field["value"]) # 其他业务逻辑...
方案2:改用Slack API直接发送(弃用Webhook)
如果必须使用请求头或查询参数,直接通过Slack API的chat.postMessage接口发送消息,同时将Bolt应用改为HTTP适配器模式,这样就能直接读取请求头和参数:
修改后的Bolt应用(HTTP适配器+Flask)
from typing import Optional import slack_sdk import os import logging from pathlib import Path from dotenv import load_dotenv from slack_bolt import App from slack_bolt.adapter.flask import SlackRequestHandler from flask import Flask, request logging.basicConfig(level=logging.DEBUG) env_path = Path('.') / '.env' load_dotenv(dotenv_path=env_path) SLACK_SIGNING_SECRET = os.environ['SLACK_SIGNING_SECRET'] SLACK_BOT_TOKEN = os.environ['SLACK_BOT_TOKEN'] # 初始化Bolt应用 bolt_app = App(token=SLACK_BOT_TOKEN, signing_secret=SLACK_SIGNING_SECRET) # 初始化Flask应用和请求处理器 flask_app = Flask(__name__) handler = SlackRequestHandler(bolt_app) # 自定义路由处理请求 @flask_app.route("/send-message", methods=["POST"]) def send_message(): # 直接读取请求头和查询参数 headers = request.headers query_params = request.args print("Headers:", headers) print("Query Parameters:", query_params) # 获取请求体中的消息内容和频道 req_body = request.get_json() text = req_body.get("text") channel = req_body.get("channel", "#slave1_private") # 调用Slack API发送消息 with bolt_app.client.chat_postMessage(channel=channel, text=text) as resp: return {"status": "ok", "message": "sent"} if __name__ == "__main__": flask_app.run(port=3000)
对应的curl请求
curl -X POST http://localhost:3000/send-message \ -H 'Content-type: application/json' \ -H "Channel_Name:slave1_private" \ --data '{"text":"Hello, World!", "channel": "#slave1_private"}'
内容的提问来源于stack exchange,提问作者vinod827
相关产品推荐
相关产品推荐

