415 Unsupported Media Type for projects.delete function in _operations.py
Using the example python for the Delete an Existing Project API call results in a 415 Unsupported Media Type error
(https://docs.digitalocean.com/reference/api/api-reference/#operation/projects_delete) e.g.:
resp = client.projects.delete(project_id="038ea76a-cae8-4c26-a1c6-3476e7a94ceb")
As shown in the following error output:
╰─λ python digitalOceanDroplet.py
Request: <HttpRequest [DELETE], url: 'https://api.digitalocean.com/v2/projects/038ea76a-cae8-4c26-a1c6-3476e7a94ceb'>
Current Headers: {'Accept': 'application/json'}
Server Response: <HttpResponse: 415 Unsupported Media Type, Content-Type: application/json; charset=utf-8>
Traceback (most recent call last):
... ... ... ...
File "digitalOceanDroplet.py", line 48, in deleteDOProject
resp = client.projects.delete(project_id="038ea76a-cae8-4c26-a1c6-3476e7a94ceb")
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File ".../lib/python3.12/site-packages/azure/core/tracing/decorator.py", line 94, in wrapper_use_tracer
return func(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^
File ".../lib/python3.12/site-packages/pydo/operations/_operations.py", line 145454, in delete
raise HttpResponseError(response=response)
azure.core.exceptions.HttpResponseError: Operation returned an invalid status 'Unsupported Media Type'
In file _operations.py, the project DELETE functionality is outlined, with the request sent and response handled at (https://raw.githubusercontent.com/digitalocean/pydo/refs/heads/main/src/pydo/operations/_operations.py):
145439 _request.url = self._client.format_url(_request.url)
... ... ...
145448 response = pipeline_response.http_response
145449
145450 if response.status_code not in [204, 404, 412]:
145451 if _stream:
145452 response.read() # Load the body in memory and close the socket
145453 map_error(status_code=response.status_code, response=response, error_map=error_map) # type: ignore
145454 raise HttpResponseError(response=response)
... ... ...
Temporary Workaround
As a hacky workaround, forcing the Content-Type header prior to the request within _operations.py with the following to force the Content-Type HTTP Header allows the API call to successfully process.
... ... ...
145439 _request.url = self._client.format_url(_request.url)
print('Request: ', _request) # <- optional print for visibility
print('Current Headers: ', _request.headers) # <- optional print for visibility
_request.headers['Content-Type'] = 'application/json; charset=utf-8' # <- Update HTTP header to force Content-Type
print('Forced Content-Type addition headers:', _request.headers) # <- optional print updated headers
145441 _stream = False
145442 pipeline_response: PipelineResponse = (
145443 self._client._pipeline.run( # pylint: disable=protected-acces144581
145444 _request, stream=_stream, **kwargs
145445 )
145446 )
145447
145448 response = pipeline_response.http_response
print('Server Response:', response) # <- optional print for visibility of server response
145450 if response.status_code not in [204, 404, 412]:
145451 if _stream:
145452 response.read() # Load the body in memory and close the socket
145453 map_error(status_code=response.status_code, response=response, error_map=error_map) # type: ignore
145454 raise HttpResponseError(response=response)
... ... ...
204 is returned confirming successful deletion:
[🔴] × python digitalOceanDroplet.py
Request: <HttpRequest [DELETE], url: 'https://api.digitalocean.com/v2/projects/038ea76a-cae8-4c26-a1c6-3476e7a94ceb'>
Current Headers: {'Accept': 'application/json'}
Forced Content-Type addition headers: {'Accept': 'application/json', 'Content-Type': 'application/json; charset=utf-8'}
Server Response: <HttpResponse: 204 No Content, Content-Type: application/json; charset=utf-8>
Content-Type is defined in multiple places throughout the _operations.py file but not the delete projects function; it's likely better defined elsewhere.
Hi i would like to work on this could you assign me
Hi i would like to work on this issue . Please assign it to me @ovidsec