I have a yaml file : file.yaml structured as follows :
index:
  - uid: "uid"
    name: "name"
    headline: "headline"
    overview: "overview"
    features: "features"
    instructions: "instructions"
    callback_url: "https://some-url.com/params"
    edit_url: "https://edit-url/params"
    uninstall_hook: "https://uninstall-url/params"
    svg: 
    screenshot1: 
    screenshot2: 
    screenshot3: 
I have to upload those informations to an api endpoint by performing a PUT request. I managed to do it first using the register.py following script that I just run python register.py:
import json
import requests
from pathlib import Path
import base64
import yaml
BASE_URL = "https://url.com"  # API Host
FILE_FOLDER = Path.cwd()  # Current working directory
if __name__ == "__main__":
    public_key = <public_key>
    private_key = <private_key>
    auth_key = "{}:{}".format(public_key, private_key).encode("utf-8")
    encodedKey = base64.b64encode(auth_key).decode("utf-8")
    headers = {"Authorization": f"Basic {encodedKey}", "Content-type": "application/json"}
    def update_app_info():
        infos_file = FILE_FOLDER / "file.yaml"
        with open(infos_file) as infos_file_data:
            yamlcontent = yaml.safe_load(infos_file_data)  # Parse file.yaml and produce a dictionary of it
        file_infos = yamlcontent["index"][0]  # retrieve actual configuration informations
        response = requests.put(
            f"{BASE_URL}/path/to/api_endpoint/{public_key}", data=json.dumps(file_infos), headers=headers
        )
        print(response)
        print(response.json())
    update_app_info()
That gives a 202 success response.
As you may observe, I tried to get content of the yaml file as a dicitonary and send that in data. I proceeded that way regarding format of data at GET https://url.com/path/to/api_endpoint (mock example for illustration...) . Having the dictionary file_infos seemed more appropriate and gets me a success response. Sending directly the file itself or 'infos_file_data' gave me some errors I got over with the above script.
The issue is when I update svg, screenshot1, screenshot2 & screenshot3 so that file.yaml is now :
index:
  - uid: "uid"
    name: "name"
    headline: "headline"
    overview: "overview"
    features: "features"
    instructions: "instructions"
    callback_url: "https://some-url.com/params"
    edit_url: "https://edit-url/params"
    uninstall_hook: "https://uninstall-url/params"
    svg: "icon.svg"
    screenshot1: "screenshot1.png"
    screenshot2: "screenshot2.png"
    screenshot3: "screenshot3.png"
That gives now :
<Response [400]>
{'error': {'message': {'svg': ['The submitted data was not a file. Check the encoding type on the form.'], 'screenshot1': ['The submitted data was not a file. Check the encoding type on the form.'], 'screenshot2': ['The submitted data was not a file. Check the encoding type on the form.'], 'screenshot3': ['The submitted data was not a file. Check the encoding type on the form.']}, 'code': 400}}
I've done multiple searches (1 , 2 , 3 , 4 , 5...) but their application and few other errors, eventually get me to this :
import base64
import json
from pathlib import Path
import requests
import yaml
from requests_toolbelt.multipart.encoder import MultipartEncoder
BASE_URL = "https://url.com"  # API Host
FILE_FOLDER = Path.cwd()  # Current working directory
if __name__ == "__main__":
    public_key = <public_key>
    private_key = <private_key>
    auth_key = "{}:{}".format(public_key, private_key).encode("utf-8")
    encodedKey = base64.b64encode(auth_key).decode("utf-8")
    def update_app_info():
        infos_file = FILE_FOLDER / "file.yaml"
        with open(infos_file) as infos_file_data:
            yamlcontent = yaml.safe_load(infos_file_data)  # Parse file.yaml and produce a dictionary of it
        file_infos = yamlcontent["index"][0]  # retrieve actual configuration informations
        m = MultipartEncoder(fields=file_infos)
        #print(m.content_type)
        headers = {
            "Authorization": f"Basic {encodedKey}",
            "Content-Type": m.content_type,
        }
        response = requests.put(
            f"{BASE_URL}/path/to/api_endpoint/{public_key}",
            data=json.dumps(file_infos),
            headers=headers
        )
        print(response)
        print(response.json())
    update_app_info()
That is also giving me the 202 success response but the file svg, screenshot1, screenshot2 & screenshot3 fields are not updated.
I'll share more informations where needed. Your help is very welcome.
