0

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.

1 Answer 1

0

I've got additional resources that helped.

As I was trying to solve my issue, I found this. It happens I didn't wrote files part as it should, plus I was having data as a JSON string. That causes a ValueError: Data must not be a string. error. This was useful to get it fixed.

Now, for what it's worth, here's the working script :

import base64 from pathlib import Path import requests 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") 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 if "index" in yamlcontent: file_infos = yamlcontent["index"][0] # retrieve actual configuration informations headers = { "Authorization": f"Basic {encodedKey}", } files = { "svg": open("icon.svg", "rb"), "screenshot1": open("screenshot1.png", "rb"), "screenshot2": open("screenshot2.png", "rb"), "screenshot3": open("screenshot3.png", "rb"), } response = requests.put( f"{BASE_URL}/path/to/api_endpoint/{public_key}", data=file_infos, files=files, headers=headers ) print("\n", response) print("\n", response.headers) print("\n", response.json()) update_app_info() 
Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.