1

I have tried to send POST requests to my slack channel using webhooks to no avail.
It always returns a bad request no matter what I do.
Is there a way to send a POST request to slack without using webhooks?

EDIT: Code that I'm using

import json
import urllib.request
#import botocore.requests as requests

def lambda_handler(event, context):
  webhook=event['webhook']
  #response = urllib.request.urlopen(message) 
  #print(response) 

  slack_URL = 'https://hooks.slack.com/services/mywebhookurl'

#  req = urllib.request.Request(SLACK_URL, json.dumps(webhook).encode('utf-8'))
  json=webhook
  json=json.encode('utf-8')
  headers={'Content-Type': 'application/json'}
  #urllib.request.add_data(data)
  req = urllib.request.Request(slack_URL, json, headers)
  response = urllib.request.urlopen(req)
  • How are using webhooks? Can u show your code? – skaul05 Nov 11 '19 at 17:37
  • I added my code but the problem is I always get HTTP 400 Error Bad Request. I have been debugging for days and nothing works so I'm trying to see if there's a different way to do this. – cookiecrumbler Nov 11 '19 at 17:43

2 Answers2

4

I think the problem arises when you encode your JSON in utf-8. Try the following script.

import json
import requests

# Generate your webhook url at  https://my.slack.com/services/new/incoming-webhook/
webhook_url = "https://hooks.slack.com/services/YYYYYYYYY/XXXXXXXXXXX"
slack_data = {'text': "Hi Sarath Kaul"}

response = requests.post(webhook_url, data=json.dumps(slack_data),headers={'Content-Type': 'application/json'})
print response.status_code

If you want to use urllib

import json
import urllib.request

import urllib.parse


url = 'https://hooks.slack.com/services/YYYYYYYYY/XXXXXXXXXXX'
data = json.dumps({'text': "Sarath Kaul"}).encode('utf-8') #data should be in bytes
headers = {'Content-Type': 'application/json'}
req = urllib.request.Request(url, data, headers)
resp = urllib.request.urlopen(req)
response = resp.read()

print(response)
skaul05
  • 2,154
  • 3
  • 16
  • 26
  • I am using AWS Lambda, which cannot use the requests library. That is why I am using urllib. – cookiecrumbler Nov 11 '19 at 17:51
  • Pretty sure that this in incorrect. Check out this answer on how to use the requests library with AWS Lambda: https://stackoverflow.com/questions/47077829/send-post-request-to-an-external-api-using-aws-lambda-in-python?noredirect=1&lq=1 – Erik Kalkoken Nov 11 '19 at 18:29
  • I was told by an AWS rep that requests will not work as it is not installed. I have already tried installing the library using those exact instructions and it still will not recognize the requests library. – cookiecrumbler Nov 11 '19 at 18:54
  • Wow I had this almost verbatim several debuggings ago and didn't have the urllib.parse part.....crazy what small difference makes – cookiecrumbler Nov 11 '19 at 19:01
  • I must say it would surprise me if AWS Lambda would not be able to use the most popular library for HTTP requests. I know that it works with Heroku, but have not tried it on AWS myself. But thanks for the info. – Erik Kalkoken Nov 11 '19 at 19:24
  • Yes, unfortunately they stopped functionality for it about a year or two ago and you have to create a deployment package with the request library that requires you to use about 3 AWS services and create permissions for all 3. A lot of room for things to go wrong, which it unfortunately did. – cookiecrumbler Nov 11 '19 at 19:43
  • @cookiecrumbler You can use this tutorial to include "requests" and any other library you want to use: https://docs.aws.amazon.com/lambda/latest/dg/configuration-layers.html This can be done completely in the UI and won't require any additional permissions or AWS services. – sktan Nov 12 '19 at 00:02
1

Without using any extra lib(like requests), one can still do GET/POST using urllib build-in python3 module. Below is the example code:

def sendSlack(message):

    req_param= {"From":"","Time":"","message":message}
    slack_data = {
            "blocks": [
                {
                    "type": "header",
                    "text": {
                        "type": "plain_text",
                        "text": "Message",
                    }
                },
                {
                    "type": "section",
                    "fields": [
                        {
                            "type": "mrkdwn",
                            "text": "*From:*\n{}".format(req_param['From'])
                        },
                        {
                            "type": "mrkdwn",
                            "text": "*Time:*\n{}".format(req_param['Time'])
                        }
                    ]
                },
                {
                    "type": "section",
                    "fields": [
                        {
                            "type": "mrkdwn",
                            "text": "*Message:*\n{}".format(req_param['message'])
                        }
                    ]
                }
            ]}
    
    req =  request.Request("https://hooks.slack.com/services/<COMPLETE THE URL>", data=json.dumps(slack_data).encode('utf-8')) # this will make the method "POST"
    resp = request.urlopen(req)
    print(resp.read())

Make sure to send the right payload, on slack. This code will work like a charm for AWS LAMBDA too. Please see the example below:

import json
from urllib import request

def sendSlack(message):
    req_param= {"From":"","StartTime":"now","DialWhomNumber":message}
    slack_data = {
        "blocks": [
            {
                "type": "header",
                "text": {
                    "type": "plain_text",
                    "text": "Message",
                }
            },
            {
                "type": "section",
                "fields": [
                    {
                        "type": "mrkdwn",
                        "text": "*From:*\n{}".format(req_param['From'])
                    },
                    {
                        "type": "mrkdwn",
                        "text": "*Time:*\n{}".format(req_param['Time'])
                    }
                ]
            },
            {
                "type": "section",
                "fields": [
                    {
                        "type": "mrkdwn",
                        "text": "*Message:*\n{}".format(req_param['message'])
                    }
                ]
            }
        ]}

    req =  request.Request("https://hooks.slack.com/services/<COMPLETE THE URL>", data=json.dumps(slack_data).encode('utf-8')) # this will make the method "POST"
    resp = request.urlopen(req)
    print(resp.read())



def lambda_handler(event, context):
    # TODO implement
    try:
        print("-->GOT A REQUEST",event['queryStringParameters'])
        sendSlack(event['queryStringParameters']['message'])
        return {'body':json.dumps({'status':200,'event':'accepted'})}
    except Exception as e:
        print("Exception happenned",e)
    return {
        'statusCode': 400,
        'body': json.dumps({'status':400,'event':'Something went wrong'})
    }
SilentEntity
  • 354
  • 1
  • 4