From c8eaea90bb8db8386a5d43fecefa767f926e18d2 Mon Sep 17 00:00:00 2001 From: Omri Rosner <68001413+rosomri@users.noreply.github.com> Date: Sat, 13 May 2023 18:59:41 +0300 Subject: [PATCH] [Confluence]: PDF export function no longer working #1158 BUGFIX (#1161) * To get the export task's current state, use the 'task/progress' endpoint instead of the deprecated 'runningtaskxml.action?taskId' * fix Requests call without timeout issue * log percentage_complete before sleeping * task result url starts with /wiki, remove it --- atlassian/confluence.py | 52 ++++++++++++++++++++--------------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/atlassian/confluence.py b/atlassian/confluence.py index 74fc6d52c..938e1e252 100644 --- a/atlassian/confluence.py +++ b/atlassian/confluence.py @@ -5,6 +5,7 @@ import json from requests import HTTPError +import requests from deprecated import deprecated from atlassian import utils from .errors import ApiError, ApiNotFoundError, ApiPermissionError, ApiValueError, ApiConflictError, ApiNotAcceptable @@ -2433,7 +2434,11 @@ def get_page_as_pdf(self, page_id): url = "spaces/flyingpdf/pdfpageexport.action?pageId={pageId}".format(pageId=page_id) if self.api_version == "cloud": url = self.get_pdf_download_url_for_confluence_cloud(url) - + if not url: + log.error("Failed to get download PDF url.") + raise ApiNotFoundError("Failed to export page as PDF", reason="Failed to get download PDF url.") + # To download the PDF file, the request should be with no headers of authentications. + return requests.get(url, timeout=75).content return self.get(url, headers=headers, not_json_response=True) def get_page_as_word(self, page_id): @@ -2669,45 +2674,40 @@ def get_pdf_download_url_for_confluence_cloud(self, url): :param url: URL to initiate PDF export :return: Download url for PDF file """ - download_url = None try: - long_running_task = True + running_task = True headers = self.form_token_headers log.info("Initiate PDF export from Confluence Cloud") response = self.get(url, headers=headers, not_json_response=True) response_string = response.decode(encoding="utf-8", errors="strict") task_id = response_string.split('name="ajs-taskId" content="')[1].split('">')[0] - poll_url = "runningtaskxml.action?taskId={0}".format(task_id) - while long_running_task: - long_running_task_response = self.get(poll_url, headers=headers, not_json_response=True) - long_running_task_response_parts = long_running_task_response.decode( - encoding="utf-8", errors="strict" - ).split("\n") - percentage_complete = long_running_task_response_parts[6].strip() - is_successful = long_running_task_response_parts[7].strip() - is_complete = long_running_task_response_parts[8].strip() - log.info("Sleep for 5s.") - time.sleep(5) + poll_url = "/services/api/v1/task/{0}/progress".format(task_id) + while running_task: log.info("Check if export task has completed.") - if is_complete == "true": - if is_successful == "true": - log.info(percentage_complete) - log.info("Downloading content...") - log.debug("Extract taskId and download PDF.") - current_status = long_running_task_response_parts[3] - download_url = current_status.split("href="/wiki/")[1].split(""")[0] - long_running_task = False - elif is_successful == "false": + progress_response = self.get(poll_url) + percentage_complete = int(progress_response.get("progress", 0)) + task_state = progress_response.get("state") + if percentage_complete == 100: + running_task = False + log.info(f"Task completed - {task_state}") + if task_state == "FAILED": log.error("PDF conversion not successful.") return None + log.debug("Extract task results to download PDF.") + task_result_url = progress_response.get("result") else: - log.info(percentage_complete) + log.info(f"{percentage_complete}% - {task_state}") + time.sleep(3) + log.debug("Task successfully done, querying the task result for the download url") + # task result url starts with /wiki, remove it. + task_content = self.get(task_result_url[5:], not_json_response=True) + download_url = task_content.decode(encoding="utf-8", errors="strict") + log.debug("Successfully got the download url") + return download_url except IndexError as e: log.error(e) return None - return download_url - def audit( self, start_date=None,