slackapi / bolt-python

A framework to build Slack apps using Python

Home Page:https://slack.dev/bolt-python/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

How to read custom headers or query string sent through webhook curl request using Python bolt SDK?

vinod827 opened this issue · comments

Hi, I'm using Python bolt SDK and trying to read a message that got received on a specific slack channel. That message was delivered using the following webhook curl request:-
curl -X POST -H 'Content-type: application/json' -H 'Channel_Name: slave1_private' --data '{"text":"Hello, World!"}' <webhook url>\?channel_name\=slave1_private

I do not find any way of parsing either the custom header or query string from the following bolt code:-

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):
    # user = event["user"]
    print("..app..", app.client.headers.get("Channel_Name"))
    print('event:::::::::::::::::::', event)
    print('context............', context)
    text = event["text"]
    channel = event["channel"]

    # Access query parameters
    # query_params = context.request.query
    # print("Query Parameters:", query_params)

    # print("event->>", event["headers"])
    # Access channel name from the payload
    # channel_name = event.get("channel_name")
    # headers = event.get("headers", {})  # Access headers from the event data
    # print("headers:::", headers)
    # channel_name = headers.get("Channel_Name")
    # print("Channel Name:", channel_name)

if __name__ == "__main__":
    handler = SocketModeHandler(app, SLACK_APP_TOKEN)
    handler.start()

Is there any support in the SDK to read the custom headers or query string?

hi, @vinod827! Thank you for your question 🙌

I'm wondering if the middleware proposed in this link can provide you with the headers you are trying to access - this will allow you to fetch the headers from the request property by using request.headers.

Let me know if this helps! 😄

@hello-ashleyintech thanks for the reply. I have tried the solution given by you but still, the headers are not getting logged.

Logs for reference:-

DEBUG:slack_bolt.App:Applying slack_bolt.middleware.url_verification.url_verification.UrlVerification
DEBUG:slack_bolt.App:Applying CustomMiddleware(func=log_request_headers)
$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ {}
Channel Name Header: None
INFO:app.py:log_request_headers:{}
DEBUG:slack_bolt.App:Checking listener: handle_message ...
DEBUG:slack_bolt.App:Running listener: handle_message ...

Here is my code snippet:-

import os
import logging
from slack_bolt import App
from slack_bolt import Say
from slack_bolt.adapter.socket_mode import SocketModeHandler
from slack_sdk import WebClient
from pathlib import Path
from dotenv import load_dotenv

import json
from slack_bolt.adapter.flask import SlackRequestHandler

logging.basicConfig(level=logging.DEBUG)
env_path = Path('.') / '.env'
load_dotenv(dotenv_path=env_path)

SLACK_BOT_TOKEN = os.environ["SLACK_BOT_TOKEN"]
SLACK_APP_TOKEN = os.environ['SLACK_APP_TOKEN']

app = App(
    token=SLACK_BOT_TOKEN,
    signing_secret=os.environ.get("SLACK_SIGNING_SECRET"),
    process_before_response=True
)
handler = SlackRequestHandler(app)
client = WebClient(SLACK_BOT_TOKEN)


@app.middleware
def log_request_headers(logger, request, next):
    print("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$", request.headers)
    channel_name_header = request.headers.get("Channel_Name")
    print("Channel Name Header:", channel_name_header)
    logger.info(request.headers)
    next()


@app.event("message")
def handle_message(event, say, context):
    print('event:::::::::::::::::::', event)
    print('context............', context)
    text = event["text"]
    channel = event["channel"]
    print(text)
    print(channel)

if __name__ == "__main__":
    handler = SocketModeHandler(app, SLACK_APP_TOKEN)
    handler.start()

This is how I'm sending the payload using the curl:-
curl -X POST -H 'Content-type: application/json' -H 'Channel_Name: slave1_private' --data '{"text":"Hello, World!"}' https://hooks.slack.com/services/<redacted>\?channel_name\=slave1_private

I want to capture the custom header or request parameter which is channel_name=slave1_private once received through the code. I'm very close to it but not able to get my head around this problem

@vinod827 Your additional request headers in an incoming webhook request won't be transferred to the payload request to your Bolt app. Those unsupported data could be just ignored. Instead, you can have message metadata to relay arbitrary data within a channel message: https://api.slack.com/metadata/using

Thanks @seratch this works and fulfills my requirements here by passing the metadata in the message