Goal: Establish connection to Confluence page, via. atlassian-python-api==3.41.1.
Configuration:
- Username - e-mail address
- Password - API key (regenerated many times)
Permissions:
- Contacted admins
- All have a green tick, under my account
URL:
- Works in browser
- However,
/rest/api/content/<page_id>is appended to the end ofURLstring.
HTTPError: 404 Client Error: Not Found for url: .../rest/api/content/123456
Questions:
- Is the URL appended string the reason for my error?
- If so, how can I prevent this behaviour?
- If not, what else should I investigate?
Jupyter Notebook:
from atlassian import Confluence
import re
from urllib.parse import urlparse
from parameter_store.params import project_params, ConfluenceParams
from typing import Any, Dict, List, Optional, Tuple
#%%
# USER INPUTS
URL = 'https://company-site.atlassian.net/wiki/spaces/my-space/pages/123456/Confluence+Python+API/' # anonymised
#%%
def establish_connection(url: str, username: str, password: str) -> Confluence:
return Confluence(url=url, username=username, password=password)
#%%
def get_domain_from_url(url: str) -> str:
return urlparse(url).netloc
#%%
def get_page_id_from_url(url: str) -> Optional[int]:
return int(re.search(r'/pages/(\d+)/', url).group(1)) if re.search(r'/pages/(\d+)/', url) else None
#%%
def generate_content(dynamic_text: str = '') -> str:
static_content = """
h1. Header
h2. Sub-header
This is text.
# Numbered list
## Sub-list
(/)
||Header 1||Header 2||
|Cell A1|Cell B1|
{info:title=Info}
This is an info panel
{info}
{code:python}
print('Hello, world!')
{code}
----
{quote}
This is a quote.
{quote}
"""
return static_content + f'\nh2. Dynamic Text\n{dynamic_text}'
#%%
def update_confluence_page(confluence, page_id: str, new_content: str) -> None:
confluence.update_page(
page_id=page_id,
title='Your Updated Page Title',
body=new_content
)
#%%
def delete_confluence_page(confluence: Confluence, page_id: str) -> None:
confluence.delete_page(page_id)
#%%
if __name__ == '__main__':
confluence_params = project_params.confluence
username = confluence_params.username
password = confluence_params.api_key
confluence = establish_connection(URL, username, password)
domain = get_domain_from_url(URL)
page_id = get_page_id_from_url(URL)
page_info = confluence.get_page_by_id(page_id)
content = generate_content()
update_confluence_page(confluence, page_id, content)
Traceback:
Expecting value: line 3 column 1 (char 10)
---------------------------------------------------------------------------
JSONDecodeError Traceback (most recent call last)
File ~/miniconda3/envs/venv/lib/python3.10/site-packages/requests/models.py:971, in Response.json(self, **kwargs)
970 try:
--> 971 return complexjson.loads(self.text, **kwargs)
972 except JSONDecodeError as e:
973 # Catch JSON-related errors and raise as requests.JSONDecodeError
974 # This aliases json.JSONDecodeError and simplejson.JSONDecodeError
File ~/miniconda3/envs/venv/lib/python3.10/json/__init__.py:346, in loads(s, cls, object_hook, parse_float, parse_int, parse_constant, object_pairs_hook, **kw)
343 if (cls is None and object_hook is None and
344 parse_int is None and parse_float is None and
345 parse_constant is None and object_pairs_hook is None and not kw):
--> 346 return _default_decoder.decode(s)
347 if cls is None:
File ~/miniconda3/envs/venv/lib/python3.10/json/decoder.py:337, in JSONDecoder.decode(self, s, _w)
333 """Return the Python representation of ``s`` (a ``str`` instance
334 containing a JSON document).
335
336 """
--> 337 obj, end = self.raw_decode(s, idx=_w(s, 0).end())
338 end = _w(s, end).end()
File ~/miniconda3/envs/venv/lib/python3.10/json/decoder.py:355, in JSONDecoder.raw_decode(self, s, idx)
354 except StopIteration as err:
--> 355 raise JSONDecodeError("Expecting value", s, err.value) from None
356 return obj, end
JSONDecodeError: Expecting value: line 3 column 1 (char 10)
During handling of the above exception, another exception occurred:
JSONDecodeError Traceback (most recent call last)
File ~/miniconda3/envs/venv/lib/python3.10/site-packages/atlassian/confluence.py:3145, in Confluence.raise_for_status(self, response)
3144 try:
-> 3145 j = response.json()
3146 error_msg = j["message"]
File ~/miniconda3/envs/venv/lib/python3.10/site-packages/requests/models.py:975, in Response.json(self, **kwargs)
972 except JSONDecodeError as e:
973 # Catch JSON-related errors and raise as requests.JSONDecodeError
974 # This aliases json.JSONDecodeError and simplejson.JSONDecodeError
--> 975 raise RequestsJSONDecodeError(e.msg, e.doc, e.pos)
JSONDecodeError: Expecting value: line 3 column 1 (char 10)
During handling of the above exception, another exception occurred:
HTTPError Traceback (most recent call last)
File ~/miniconda3/envs/venv/lib/python3.10/site-packages/atlassian/confluence.py:345, in Confluence.get_page_by_id(self, page_id, expand, status, version)
344 try:
--> 345 response = self.get(url, params=params)
346 except HTTPError as e:
File ~/miniconda3/envs/venv/lib/python3.10/site-packages/atlassian/rest_client.py:285, in AtlassianRestAPI.get(self, path, data, flags, params, headers, not_json_response, trailing, absolute, advanced_mode)
272 """
273 Get request based on the python-requests module. You can override headers, and also, get not json response
274 :param path:
(...)
283 :return:
284 """
--> 285 response = self.request(
286 "GET",
287 path=path,
288 flags=flags,
289 params=params,
290 data=data,
291 headers=headers,
292 trailing=trailing,
293 absolute=absolute,
294 advanced_mode=advanced_mode,
295 )
296 if self.advanced_mode or advanced_mode:
File ~/miniconda3/envs/venv/lib/python3.10/site-packages/atlassian/rest_client.py:257, in AtlassianRestAPI.request(self, method, path, data, json, flags, params, headers, files, trailing, absolute, advanced_mode)
255 return response
--> 257 self.raise_for_status(response)
258 return response
File ~/miniconda3/envs/venv/lib/python3.10/site-packages/atlassian/confluence.py:3149, in Confluence.raise_for_status(self, response)
3148 log.error(e)
-> 3149 response.raise_for_status()
3150 else:
File ~/miniconda3/envs/venv/lib/python3.10/site-packages/requests/models.py:1021, in Response.raise_for_status(self)
1020 if http_error_msg:
-> 1021 raise HTTPError(http_error_msg, response=self)
HTTPError: 404 Client Error: Not Found for url: https://company-site.atlassian.net/wiki/spaces/my-space/pages/123456/Confluence+Python+API/rest/api/content/123456
During handling of the above exception, another exception occurred:
ApiError Traceback (most recent call last)
Cell In[130], line 11
9 domain = get_domain_from_url(URL)
10 page_id = get_page_id_from_url(URL)
---> 11 page_info = confluence.get_page_by_id(page_id)
13 content = generate_content()
14 update_confluence_page(confluence, page_id, content)
File ~/miniconda3/envs/venv/lib/python3.10/site-packages/atlassian/confluence.py:349, in Confluence.get_page_by_id(self, page_id, expand, status, version)
346 except HTTPError as e:
347 if e.response.status_code == 404:
348 # Raise ApiError as the documented reason is ambiguous
--> 349 raise ApiError(
350 "There is no content with the given id, "
351 "or the calling user does not have permission to view the content",
352 reason=e,
353 )
355 raise
357 return response
ApiError: There is no content with the given id, or the calling user does not have permission to view the content
In the docs the Confluence instance is created with the base-URL of the confluence server. The API library you are using then creates the URL for the resource you are using itself. So please change the URL to: