Search code examples
pythonpython-2.7confluence-rest-api

Create a New page in a specific space and update it with existing file Contents in Confluence in python using REST API?


I am writing a Python script to create a new Page on Confluence and update the page with the contents which is in html file.Below is my code.I am using the confluence version 5.8.10

import argparse
import getpass
import sys

import json
import keyring
import requests

#-----------------------------------------------------------------------------
# Globals

BASE_URL = "https://wiki.hurry.com/rest/api/content"

def pprint(data):
    '''
    Pretty prints json data.
    '''
    print json.dumps(
        data,
        sort_keys = True,
        indent = 4,
        separators = (', ', ' : '))


def write_data(auth, html, title):

    ver = 'TEST'

    data = {
        'type' : 'page',
        'title' : str(title),
        'space' : {'key' : TEST},
        'body'  : {
            'storage' :
            {
                'representation' : 'storage',
                'value' : str(html),
            }
        }
    }

    data = json.dumps(data)

    print data

    url = '{base}/?os_authType=basic'.format(base = BASE_URL)
    print url
    r = requests.post(
        url,
        data = data,
        auth = auth,
        headers = { 'Content-Type' : 'application/json' }
    )

    r.raise_for_status()



def get_login(username = None):
    '''
    Get the password for username out of the keyring.
    '''

    if username is None:
        username = getpass.getuser()

    passwd = keyring.get_password('confluence_script', username)

    if passwd is None:
        passwd = getpass.getpass()
        keyring.set_password('confluence_script', username, passwd)

    return (username, passwd)


def main():

    parser = argparse.ArgumentParser()

    parser.add_argument(
        "-u",
        "--user",
        default = getpass.getuser(),
        help = "Specify the username to log into Confluence")

    parser.add_argument(
        "-t",
        "--title",
        default = None,
        type = str,
        help = "Specify a new title")

    parser.add_argument(
        "-f",
        "--file",
        default = None,
        type = str,
        help = "Write the contents of FILE to the confluence page")

    parser.add_argument(
        "html",
        type = str,
        default = None,
        nargs = '?',
        help = "Write the immediate html string to confluence page")

    options = parser.parse_args()

    auth = get_login(options.user)

    if options.html is not None and options.file is not None:
        raise RuntimeError(
            "Can't specify both a file and immediate html to write to page!")

    if options.html:
        html = options.html

    else:

        with open(options.file, 'r') as fd:
            html = fd.read()

    write_data(auth, html, options.title)


if __name__ == "__main__" : main()

Below is the error I am getting

  r.raise_for_status()
  File "C:\Python27\lib\site-packages\requests\models.py", line 928, in raise_for_status
    raise HTTPError(http_error_msg, response=self)
requests.exceptions.HTTPError: 400 Client Error: Bad Request for url: https://wiki.hurry.com/rest/api/content/?os_authType=basic

Could someone let me know what am I doing wrong here?


Solution

  • Based on the error you got 400 Client Error the problem is definitely on your side. RESTful APIs usually expect JSON data, not HTML.

    Be sure about the data you are sending and the way you are using Requests, because Requests are performing additional stuff "behind the scenes" depending on what you pass to some of the methods (e.g. adding json parameter to post will automatically append Content-Type: application/json header in your request).

    Also, be sure you understand HTTP response codes ;)