minio / minio-py

MinIO Client SDK for Python
https://docs.min.io/docs/python-client-quickstart-guide.html
Apache License 2.0
852 stars 325 forks source link

api.py completely breaks HTTPx client requests. #1276

Closed caner-cetin closed 1 year ago

caner-cetin commented 1 year ago

THIS IS NOT JUST HTTPx, ANY OPERATIONS ON FILES LIKE SEEK ON FILE AFTER THE MinIO SDK OPERATIONS WILL BREAK.

Title.

https://github.com/minio/minio-py/blob/master/minio/api.py#L941

Do you see the


        with open(file_path, "rb") as file_data:
            return self.put_object(
                bucket_name, object_name, file_data, file_size,
                content_type=content_type,
                metadata=metadata, sse=sse, progress=progress,
                part_size=part_size, num_parallel_uploads=num_parallel_uploads,
                tags=tags, retention=retention, legal_hold=legal_hold,
            )

code block? Yes, it completely breaks HTTPx client requests. How?

https://github.com/encode/httpx/blob/master/httpx/_client.py#L1584

Do you see the

        try:
            if not stream:
                await response.aread()

            return response

        except BaseException as exc:  # pragma: no cover
            await response.aclose()
            raise exc

code block? I get

self = <tempfile.SpooledTemporaryFile object at 0x7f6664f085e0>

    def close(self):
>       self._file.close()
E       OSError: [Errno 29] Illegal seek

/usr/lib/python3.10/tempfile.py:866: OSError
======================================================================================================= short test summary info ========================================================================================================
ERROR unit_tests/test_a.py::test_are_we_there_yet - OSError: [Errno 29] Illegal seek

error when I do

await http_client.post(
        "/some/shit",
       files={
            "document": open(
                f"canerinensonmutluoldugunadiranlar.png", "r+b"
            )
        },
    )

How? Now look at https://github.com/minio/minio-py/blob/master/minio/api.py#L941 again. Whenever I ping against an FastAPI endpoint that uses MinIO SDK, MinIO SDK will do the operations, and CLOSE the file after it is done thanks to:

with open(file_path, "rb") as file_data:

and due to MinIO SDK closing the file before the endpoint's purpose is over, when we get the response, file will be closed, and when HTTPx is assembling the response it will try to seek the file for some reason, and shit will happen.

Example code:

@router.post("/upload")
async def upload(document: UploadFile = File(...)):
    # do some operations with minio SDK
    minio_client.fput_object(
                "damacana", "canımdamacanam", object.file.fileno(), content_type="image/jpg"
          )
    return

where object.file.fileno is => https://docs.python.org/3.10/library/tempfile.html#tempfile.SpooledTemporaryFile.fileno

I dont know who to blame for this, but yeah.

caner-cetin commented 1 year ago

If I couldnt pinpoint the problem, there is certainly a problem in SDK that file is closed or a operation is done that file is no longer seekable.

balamurugana commented 1 year ago

minio-py doesn't use httpx instead uses urllib3.

caner-cetin commented 1 year ago

@balamurugana So if I use your SDK in a REST API endpoint, I can't ping it with HTTPx anymore for testing? Wow.

Maybe you can write this in a small corner of documentation, as this may be annoying to some like I find it.

caner-cetin commented 1 year ago

And urllib3 does not support async client. So uh, flexibility would be nice.