0

I wrote a python script to automate the process of uploading images to an endpoint. The code is as follows:

import time
import requests
from pathlib import Path
from random import randint

def single_campus_upload(image_file, property_id):
    BASE_URL_CAMPUS = f'http://[redacted].up.railway.app/api/properties/{property_id}/images/'

    # Open the image file in read-binary mode using the `with` statement to automatically close it after reading
    with image_file.open(mode='rb') as f:
        # Read the contents of the file into a bytes object
        image_data = f.read()

    # Send the POST request to the API endpoint with the image data
    response = requests.post(BASE_URL_CAMPUS, data=image_data)

    # Check the status code to see if the request was successful
    if response.status_code >= 200 and response.status_code < 300:
        # Parse the JSON response and print it in a readable format
        print(response.json())
    else:
        # Print the status code and the raw response if the request was not successful
        print(f'Request failed with status code {response.status_code}: {response.text}')

The code above throws an error, here is the traceback:

`

ConnectionResetError                      Traceback (most recent call last)
File ~/anaconda3/lib/python3.9/site-packages/urllib3/connectionpool.py:703, in HTTPConnectionPool.urlopen(self, method, url, body, headers, retries, redirect, assert_same_host, timeout, pool_timeout, release_conn, chunked, body_pos, **response_kw)
    702 # Make the request on the httplib connection object.
--> 703 httplib_response = self._make_request(
    704     conn,
    705     method,
    706     url,
    707     timeout=timeout_obj,
    708     body=body,
    709     headers=headers,
    710     chunked=chunked,
    711 )
    713 # If we're going to release the connection in ``finally:``, then
    714 # the response doesn't need to know about the connection. Otherwise
    715 # it will also try to release it and we'll have a double-release
    716 # mess.

File ~/anaconda3/lib/python3.9/site-packages/urllib3/connectionpool.py:398, in HTTPConnectionPool._make_request(self, conn, method, url, timeout, chunked, **httplib_request_kw)
    397     else:
--> 398         conn.request(method, url, **httplib_request_kw)
    400 # We are swallowing BrokenPipeError (errno.EPIPE) since the server is
    401 # legitimately able to close the connection after sending a valid response.
    402 # With this behaviour, the received response is still readable.

File ~/anaconda3/lib/python3.9/site-packages/urllib3/connection.py:239, in HTTPConnection.request(self, method, url, body, headers)
    238     headers["User-Agent"] = _get_default_user_agent()
--> 239 super(HTTPConnection, self).request(method, url, body=body, headers=headers)

File ~/anaconda3/lib/python3.9/http/client.py:1285, in HTTPConnection.request(self, method, url, body, headers, encode_chunked)
   1284 """Send a complete request to the server."""
-> 1285 self._send_request(method, url, body, headers, encode_chunked)

File ~/anaconda3/lib/python3.9/http/client.py:1331, in HTTPConnection._send_request(self, method, url, body, headers, encode_chunked)
   1330     body = _encode(body, 'body')
-> 1331 self.endheaders(body, encode_chunked=encode_chunked)

File ~/anaconda3/lib/python3.9/http/client.py:1280, in HTTPConnection.endheaders(self, message_body, encode_chunked)
   1279     raise CannotSendHeader()
-> 1280 self._send_output(message_body, encode_chunked=encode_chunked)

File ~/anaconda3/lib/python3.9/http/client.py:1079, in HTTPConnection._send_output(self, message_body, encode_chunked)
   1077         chunk = f'{len(chunk):X}\r\n'.encode('ascii') + chunk \
   1078             + b'\r\n'
-> 1079     self.send(chunk)
...
    503 except MaxRetryError as e:
    504     if isinstance(e.reason, ConnectTimeoutError):
    505         # TODO: Remove this in 3.0.0: see #2811

ConnectionError: ('Connection aborted.', ConnectionResetError(104, 'Connection reset by peer'))

It uploads successfully if I manually upload the image to the end point, so I have no idea why the script throws the error. My guess is that the server (railway) stops the script because it is too rapid, but even after implementing a rate limiter, the problem persisted.

Other Relevant Information:

  • The endpoint is a Django/DRF backend.
  • The backend is hosted on railway's servers
  • The images are uploaded to cloudinary for storage (This may be where the issue is coming from) `

Any help would be much appreciated. Thanks in advance.

*Update while writing this*

I tried running the API I'm posting to - locally in dev mode rather than prod, but I connected the image storage to cloudinary still, then I ran the script and I observed the same problem, so definitely, the problem is not from railway, but from cloudinary. Can't figure out what's wrong, maybe it's expecting the file data / content-type header in some format I'm not aware of?

1 Answers1

0

Turns out I used http:// in the url rather than https://, took me 10 days to figure out, so dumb.

Julia Meshcheryakova
  • 3,162
  • 3
  • 22
  • 42