1

I am working on python code for some webhook urls. Earlier the code was working on python 2.7 and had to be updated to python 3 Python 2 to 3 conversion was done using 2to3. Python 2 code :

def send_webhook_request(url, body, user_agent=None): if url is None: print >> sys.stderr, "ERROR No URL provided" return False print >> sys.stderr, "INFO Sending POST request to url=%s with size=%d bytes payload" % (url, len(body)) print >> sys.stderr, "DEBUG Body: %s" % body try: user="USER" password="PASSWORD" credentials = (user + ':' + password).encode('utf-8') base64_encoded_credentials = base64.b64encode(credentials).decode('utf-8') headers = {'Authorization': 'Basic ' + base64_encoded_credentials, "Content-Type": "application/json", 'User-Agent': user_agent} #req = urllib.urlopen(url, body, headers) req = urllib2.Request(url, body, headers) res = urllib2.urlopen(req) response = res.read() #res = urllib2.read() if 200 <= res.code < 300: print >> sys.stderr, "INFO Webhook receiver responded with HTTP status=%d" % res.code return response else: print >> sys.stderr, "ERROR Webhook receiver responded with HTTP status=%d" % res.code return False except urllib2.HTTPError, e: print >> sys.stderr, "ERROR Error sending webhook request: %s" % e except urllib2.URLError, e: print >> sys.stderr, "ERROR Error sending webhook request: %s" % e except ValueError, e: print >> sys.stderr, "ERROR Invalid URL: %s" % e return False 

Python 3 Code : EDIT 1 - added encode to body.

def send_webhook_request(url, body, user_agent=None): if url is None: print("ERROR No URL provided", file=sys.stderr) return False print("INFO Sending POST request to url=%s with size=%d bytes payload" % (url, len(body)), file=sys.stderr) print("DEBUG Body: %s" % body, file=sys.stderr) try: user="integration.argossplunk" password="hv6ep_gXR+M$#8tk@e4cePYx@*Er4VD#" credentials = (user + ':' + password).encode('utf-8') base64_encoded_credentials = base64.b64encode(credentials).decode('utf-8') headers = {'Authorization': 'Basic ' + base64_encoded_credentials, "Content-Type": "application/json", 'User-Agent': user_agent} #req = urllib.urlopen(url, body, headers) body = body.encode() #body = urllib.parse.urlencode(body).encode("utf-8") req = urllib.request.Request(url, body, headers) res = urllib.request.urlopen(req) response = res.read() #res = urllib2.read() if 200 <= res.code < 300: print("INFO Webhook receiver responded with HTTP status=%d" % res.code, file=sys.stderr) return response else: print("ERROR Webhook receiver responded with HTTP status=%d" % res.code, file=sys.stderr) return False except urllib.error.HTTPError as e: print("ERROR Error sending webhook request: %s" % e, file=sys.stderr) except urllib.error.URLError as e: print("ERROR Error sending webhook request: %s" % e, file=sys.stderr) except ValueError as e: print("ERROR Invalid URL: %s" % e, file=sys.stderr) return False 

When I am calling this fuction :

send_webhook_request(url, json.dumps(body), user_agent=user_agent) 

It gives me error - TypeError: POST data should be bytes, an iterable of bytes, or a file object. It cannot be of type str.

Please suggest what can be done ?

Thanks

4
  • Please show the full traceback. Commented Jul 13, 2021 at 9:44
  • 1
    Personally I'd suggest you move from using urllib to using requests, but for your code, if you read the error message and consult the documentation for urllib.request.Request docs.python.org/3/library/… you'll see that the data parameter has to be bytes - but as the error message says you're providing a value which is a str. You can convert (encode) str to bytes using encode() see docs.python.org/3/library/… Commented Jul 13, 2021 at 9:44
  • @barny : I have added encode - updated the code in edit 1. However, Now I am getting error related to headers once I made the change. ERROR : C:\ProgramData\Anaconda3\lib\http\client.py in putheader(self, header, *values) 1204 values[i] = str(one_value).encode('ascii') 1205 -> 1206 if _is_illegal_header_value(values[i]): 1207 raise ValueError('Invalid header value %r' % (values[i],)) 1208 TypeError: expected string or bytes-like object Commented Jul 13, 2021 at 10:00
  • 1
    Post a minimal reproducible example, please. Emphasis on minimal. Commented Jul 13, 2021 at 10:02

1 Answer 1

1

You need to make sure to convert everything to Bytes correctly, as mentioned in the comments it would be way easier using requests than urllib.

import base64 import urllib from urllib import request import sys import json def send_webhook_request(url, body, user_agent=None): if url is None: print("ERROR No URL provided", file=sys.stderr) return False print( "INFO Sending POST request to url=%s with size=%d bytes payload" % (url, len(body)), file=sys.stderr ) print("DEBUG Body: %s" % body, file=sys.stderr) user = "integration.argossplunk" password = "hv6ep_gXR+M$#8tk@e4cePYx@*Er4VD#" # use f-strings to format Auth header correctly! credentials = f"{user}:{password}" base64_encoded_credentials = base64.b64encode(credentials.encode('utf-8')) headers = { 'Authorization': f'Basic {base64_encoded_credentials.decode()}', "Content-Type": "application/json", } # urllib doesn't like None, so add it when given! if user_agent: headers['User-Agent'] = user_agent try: req = urllib.request.Request(url, body, headers) res = urllib.request.urlopen(req) response = res.read() if 200 <= res.code < 300: return res.code print( "INFO Webhook receiver responded with HTTP status=%d" % res.code, file=sys.stderr ) return response else: print( "ERROR Webhook receiver responded with HTTP status=%d" % res.code, file=sys.stderr ) return False except urllib.error.HTTPError as e: print("ERROR Error sending webhook request: %s" % e, file=sys.stderr) except urllib.error.URLError as e: print("ERROR Error sending webhook request: %s" % e, file=sys.stderr) except ValueError as e: print("ERROR Invalid URL: %s" % e, file=sys.stderr) return False for url in ('https://xxx.yyy.zzz', 'htt://errorRaising.url'): params = {'param1': 'value1', 'param2': 'value2'} res = send_webhook_request(url, json.dumps(params).encode('utf8')) print(res) 

Out:

INFO Sending POST request to url=... with size=40 bytes payload DEBUG Body: b'{"param1": "value1", "param2": "value2"}' ERROR Error sending webhook request: HTTP Error 401: Unauthorized False INFO Sending POST request to url=htt://errorRaising.url with size=40 bytes payload DEBUG Body: b'{"param1": "value1", "param2": "value2"}' ERROR Error sending webhook request: <urlopen error unknown url type: htt> False 
Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.