diff --git a/slack/webhook/client.py b/slack/webhook/client.py index a5a4ee200..a548ffd0d 100644 --- a/slack/webhook/client.py +++ b/slack/webhook/client.py @@ -17,7 +17,8 @@ class WebhookClient: def __init__( self, url: str, default_headers: Dict[str, str] = {}, ): - """urllib-based API client. + """API client for Incoming Webhooks and response_url + :param url: a complete URL to send data (e.g., https://hooks.slack.com/XXX) :param default_headers: request headers to add to all requests """ self.url = url @@ -27,52 +28,45 @@ def send( self, body: Dict[str, any], additional_headers: Dict[str, str] = {}, ) -> WebhookResponse: """Performs a Slack API request and returns the result. - :param url: a complete URL (e.g., https://hooks.slack.com/XXX) - :param json_body: json data structure (it's still a dict at this point), + :param body: json data structure (it's still a dict at this point), if you give this argument, body_params and files will be skipped - :param body_params: form params - :param additional_headers: request headers to append + :param additional_headers: request headers to append only for this request :return: API response """ - body = convert_bool_to_0_or_1(body) self._parse_blocks(body) if self.logger.level <= logging.DEBUG: self.logger.debug( - f"Slack API Request - url: {self.url}, " + f"Sending a request - url: {self.url}, " f"body: {body}, " f"additional_headers: {additional_headers}" ) - request_headers = self._build_request_headers( - has_json=json is not None, additional_headers=additional_headers, + return self._perform_http_request( + url=self.url, + body=body, + headers=self._build_request_headers(additional_headers), ) - args = { - "headers": request_headers, - "body": body, - } - return self._perform_http_request(url=self.url, args=args) def _perform_http_request( - self, *, url: str, args: Dict[str, Dict[str, any]] + self, *, url: str, body: Dict[str, any], headers: Dict[str, str] ) -> WebhookResponse: """Performs an HTTP request and parses the response. - :param url: a complete URL (e.g., https://www.slack.com/api/chat.postMessage) - :param args: args has "headers", "data", "params", and "json" - "headers": Dict[str, str] - "params": Dict[str, str], - "json": Dict[str, any], - :return: a tuple (HTTP response and its body) + :param url: a complete URL to send data (e.g., https://hooks.slack.com/XXX) + :param body: request body data + :param headers: complete set of request headers + :return: API response """ - headers = args["headers"] - body = json.dumps(args["body"]).encode("utf-8") + body = json.dumps(body).encode("utf-8") headers["Content-Type"] = "application/json;charset=utf-8" try: + # for security if url.lower().startswith("http"): req = Request(method="POST", url=url, data=body, headers=headers) else: raise SlackRequestError(f"Invalid URL detected: {url}") + resp: HTTPResponse = urlopen(req) charset = resp.headers.get_content_charset() or "utf-8" return WebhookResponse( @@ -98,21 +92,19 @@ def _perform_http_request( raise err def _build_request_headers( - self, has_json: bool, additional_headers: dict, - ): - headers = { + self, additional_headers: Dict[str, str], + ) -> Dict[str, str]: + request_headers = { "User-Agent": get_user_agent(), - "Content-Type": "application/x-www-form-urlencoded;charset=utf-8", + "Content-Type": "application/json;charset=utf-8", } - headers.update(self.default_headers) + request_headers.update(self.default_headers) if additional_headers: - headers.update(additional_headers) - if has_json: - headers.update({"Content-Type": "application/json;charset=utf-8"}) - return headers + request_headers.update(additional_headers) + return request_headers @staticmethod - def _parse_blocks(body): + def _parse_blocks(body) -> None: blocks = body.get("blocks", None) def to_dict(b: Union[Dict, Block]):