pythonjsonrestpython-requestsbitbucket-server

How to fix '415 Unsupported Media Type' error in Python using requests


I would like to create a commit by using bitbucket's rest api. So far, all the answers to questions about Response 415 have been resolved by setting the Content-Type in the header to application/json;charset-UTF8. However, this does not solve the response I get.

So here is what I am trying to do:

import requests

def commit_file(s, path, content, commit_message, branch, source_commit_id):
    data = dict(content=content, message=commit_message, branch=branch, sourceCommitId=source_commit_id)
    r = s.put(path, data=data, headers={'Content-type': 'application/json;charset=utf-8'})
    return r.status_code

s = requests.Session()
s.auth = ('name', 'token')
url = 'https://example.com/api/1.0/projects/Project/repos/repo/browse/file.txt'
file = s.get(url)
r = commit_file(s, url, file.json() , 'Commit Message', 'test', '51e0f6faf64')

The GET requests successfully returns the file and I would like to commit it's contents on the branch test which does exist.

No matter the Content-Type, the status_code of the response is 415.

Here is the header of the put request:

OrderedDict([('user-agent', ('User-Agent', 'python-requests/2.21.0')), ('accept-encoding', ('Accept-Encoding', 'gzip, deflate')), ('accept', ('Accept', '*/*')), ('connection', ('Connection', 'keep-alive')), ('content-type', ('Content-type', 'application/json;charset=utf-8')), ('content-length', ('Content-Length', '121')), ('authorization', ('Authorization', 'Basic YnVybWF4MDA6Tnp...NkJqWGp1a2JjQ3dNZzhHeGI='))])

This explains the usage with curl and when the file is locally available. How would a correct request look like in python when the content of the file are retrieved as shown above?

This is the solution by using the MultipartEncoder:

import requests
import requests_toolbelt.multipart.encoder

def commit_file(s, path, content, commit_message, branch, source_commit_id):
    data = requests_toolbelt.MultipartEncoder(
        fields={
            'content': content,
            'message': commit_message,
            'branch': branch,
            'sourceCommitId': source_commit_id
        }
    )
    r = s.put(path, data=data, headers={'Content-type': data.content_type})

Solution

  • Content type application/json;charset=utf-8 is incorrect.

    According to the documentation, you must send multipart form data. You cannot use JSON.

    This resource accepts PUT multipart form data, containing the file in a form-field named content.

    See: How to send a "multipart/form-data" with requests in python?