Anonymous Person
Anonymous Person

Reputation: 1538

Python - Unable to send request [error 203, POST]

I have 4 string variables like this:

a = 'a long string'
b = 'a longer string' 
c = 'a path (with a single slash \)' 
d = 'another path (with a single slash \)'

I am supposed to be adding this to a variable, which is a list of dictionaries. Something like this:

var = [
    {
        "op": "add",
        "path": "/fields/System.Title",
        "from": null,
        "value": a
    },
    {
        "op": "add",
        "path": "/fields/System.Description",
        "from": null,
        "value": b
    },
    {
        "op": "add",
        "path": "/fields/System.AreaPath",
        "from": null,
        "value": c
    },
    {
        "op": "add",
        "path": "/fields/System.State",
        "from": null,
        "value": "New"
    },
    {
        "op": "add",
        "path": "/fields/System.IterationPath",
        "from": null,
        "value": d
    }
]

FYI, var[3] does not take the variables I created. Only var[0], var[1], var[2] and var[4]

All this works fine. As you may have guessed by now, this is my payload for a POST operation that I am supposed to be sending (it's actually to create a work item in my Azure DevOps organization with the above parameters). Please note, the from in var only accepts null.

When I use POSTMAN to send the above request, it works (except I am not passing the variables in the body, but actually the hard coded values). When I do the same using Python, on VSCode, I am always thrown a 203, which is essentially an incorrect/incomprehensible payload. I am not able to get this working.

This is essentially the code (please assume the variables):

url = f'https://dev.azure.com/{organization}/{project}/_apis/wit/workitems/${workitemtype}?api-version=6.0'
header = {'Content-Type': 'application/json-patch+json', 'Authorization': f'Basic {PAT}'}
request = requests.post(url = url, json = var, headers = header)

I've tried everything I can think of: request = requests.post(url = url, **data = json.dumps(var)**, headers = header),

request = requests.post(url = url, **data = json.loads(var)**, headers = header),

request = requests.post(url = url, **data = json.loads(str(var))**, headers = header) -> this because loads(var) was throwing TypeError: the JSON object must be str, bytes or bytearray, not list

I also tried to include the entire var variable as a docstring - but the problem with that is that I need to pass the variables (a, b, c and d) into it, and docstrings cannot accept them.

How may I overcome this?

I have a feeling that it's the null that's causing this issue, but I could be wrong.

Upvotes: 0

Views: 631

Answers (1)

Levi Lu-MSFT
Levi Lu-MSFT

Reputation: 30313

I tested with your code, and i failed to pass the authorization if i defined the Authorization in the request headers. I fixed it by passing the PAT to the auth parameter in requests.post method. I made a little to your code. And it worked fine for me. See below:

import requests
if __name__ == '__main__':
    a = 'a longer string'
    b = 'a longer string' 
    c = 'project\area' 
    d = 'project\iteration'

    var = [
        {
            "op": "add",
            "path": "/fields/System.Title",
            "from": None,
            "value": a
        },
        {
            "op": "add",
            "path": "/fields/System.Description",
            "from": None,
            "value": b
        },
        {
            "op": "add",
            "path": "/fields/System.AreaPath",
            "from": None,
            "value": c
        },
        {
            "op": "add",
            "path": "/fields/System.State",
            "from": None,
            "value": "New"
        },
        {
            "op": "add",
            "path": "/fields/System.IterationPath",
            "from": None,
            "value": d
        }
    ]

    pat = "Personal access token"
    url = 'https://dev.azure.com/{organization}/{project}/_apis/wit/workitems/$Task?api-version=6.1-preview.3'
  
    header = {'Content-Type': 'application/json-patch+json'}
   
    request = requests.post(url = url, json = var, headers = header, auth=("", pat))

However you can also check out azure-devops-python-api. See below example code to create a work item.

from azure.devops.connection import Connection
from msrest.authentication import BasicAuthentication
from azure.devops.v5_1.work_item_tracking.models import JsonPatchOperation

def _create_patch_operation(op, path, value):
    patch_operation = JsonPatchOperation()
    patch_operation.op = op
    patch_operation.path = path
    patch_operation.value = value
    return patch_operation

def _create_work_item_field_patch_operation(op, field, value):
    path = '/fields/{field}'.format(field=field)
    return _create_patch_operation(op=op, path=path, value=value)

if __name__=='__main__':
    a = 'a longer string'
    b = 'a longer string' 
    c = 'project\area' 
    d = 'project\iteration'
# Fill in with your personal access token and org URL
    personal_access_token = 'PAT'
    organization_url = 'https://dev.azure.com/{org}/'

    # Create a connection to the org
    credentials = BasicAuthentication('', personal_access_token)
    connection = Connection(base_url=organization_url, creds=credentials)

    # Get a client 
    wit_client = connection.clients.get_work_item_tracking_client()

    patch_document=[]

    patch_document.append(_create_work_item_field_patch_operation('add', 'System.Title', a))
    patch_document.append(_create_work_item_field_patch_operation('add', 'System.Description', b))
    patch_document.append(_create_work_item_field_patch_operation('add', 'System.AreaPath', c))

    wit_client.create_work_item(patch_document, "Project", 'Task')

Upvotes: 1

Related Questions