Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

televersement de fichiers #897

Open
vincentporte opened this issue Jan 29, 2025 · 15 comments · May be fixed by #900
Open

televersement de fichiers #897

vincentporte opened this issue Jan 29, 2025 · 15 comments · May be fixed by #900
Assignees
Labels
python Pull requests that update Python code

Comments

@vincentporte
Copy link
Contributor

erreur 500

https://inclusion.sentry.io/issues/27866577/?project=4508410606452816&referrer=project-issue-stream

2025-01-29T10:18:03.449Z ERROR 2025-01-29 11:18:03,442 /home/bas/venv/lib/python3.13/site-packages/django/utils/log.py : Internal Server Error: /forum/le-questionnement-dans-le-diagnostic-socio-professionnel-dsp-225/update/
Traceback (most recent call last):
  File "/home/bas/venv/lib/python3.13/site-packages/django/core/handlers/exception.py", line 55, in inner
    response = get_response(request)
  File "/home/bas/venv/lib/python3.13/site-packages/django/core/handlers/base.py", line 197, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/home/bas/venv/lib/python3.13/site-packages/sentry_sdk/integrations/django/views.py", line 94, in sentry_wrapped_callback
    return callback(request, *args, **kwargs)
  File "/usr/host/lib/python3.13/contextlib.py", line 85, in inner
    return func(*args, **kwds)
  File "/home/bas/venv/lib/python3.13/site-packages/django/views/generic/base.py", line 104, in view
    return self.dispatch(request, *args, **kwargs)
           ~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/bas/venv/lib/python3.13/site-packages/django/contrib/auth/mixins.py", line 135, in dispatch
    return super().dispatch(request, *args, **kwargs)
           ~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/bas/venv/lib/python3.13/site-packages/django/views/generic/base.py", line 143, in dispatch
    return handler(request, *args, **kwargs)
  File "/home/bas/venv/lib/python3.13/site-packages/django/views/generic/edit.py", line 206, in post
    return super().post(request, *args, **kwargs)
           ~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/bas/venv/lib/python3.13/site-packages/django/views/generic/edit.py", line 151, in post
    return self.form_valid(form)
           ~~~~~~~~~~~~~~~^^^^^^
  File "/home/bas/venv/lib/python3.13/site-packages/django/views/generic/edit.py", line 133, in form_valid
    self.object = form.save()
                  ~~~~~~~~~^^
  File "/home/bas/app_be9c4821-d5c0-4470-b290-d5d33ad9b4f9/lacommunaute/forum/forms.py", line 49, in save
    forum.save()
    ~~~~~~~~~~^^
  File "/home/bas/venv/lib/python3.13/site-packages/machina/apps/forum/abstract_models.py", line 167, in save
    super().save(*args, **kwargs)
    ~~~~~~~~~~~~^^^^^^^^^^^^^^^^^
  File "/home/bas/venv/lib/python3.13/site-packages/mptt/models.py", line 1106, in save
    super().save(*args, **kwargs)
    ~~~~~~~~~~~~^^^^^^^^^^^^^^^^^
  File "/home/bas/venv/lib/python3.13/site-packages/django/db/models/base.py", line 892, in save
    self.save_base(
    ~~~~~~~~~~~~~~^
        using=using,
        ^^^^^^^^^^^^
    ...<2 lines>...
        update_fields=update_fields,
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    )
    ^
  File "/home/bas/venv/lib/python3.13/site-packages/django/db/models/base.py", line 998, in save_base
    updated = self._save_table(
        raw,
    ...<4 lines>...
        update_fields,
    )
  File "/home/bas/venv/lib/python3.13/site-packages/django/db/models/base.py", line 1125, in _save_table
    (getattr(self, f.attname) if raw else f.pre_save(self, False)),
                                          ~~~~~~~~~~^^^^^^^^^^^^^
  File "/home/bas/venv/lib/python3.13/site-packages/django/db/models/fields/files.py", line 338, in pre_save
    file.save(file.name, file.file, save=False)
    ~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/bas/venv/lib/python3.13/site-packages/django/db/models/fields/files.py", line 99, in save
    self.name = self.storage.save(name, content, max_length=self.field.max_length)
                ~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/bas/venv/lib/python3.13/site-packages/django/core/files/storage/base.py", line 49, in save
    name = self._save(name, content)
  File "/home/bas/venv/lib/python3.13/site-packages/storages/backends/s3.py", line 564, in _save
    obj.upload_fileobj(content, ExtraArgs=params, Config=self.transfer_config)
    ~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/bas/venv/lib/python3.13/site-packages/boto3/s3/inject.py", line 731, in object_upload_fileobj
    return self.meta.client.upload_fileobj(
           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^
        Fileobj=Fileobj,
        ^^^^^^^^^^^^^^^^
    ...<4 lines>...
        Config=Config,
        ^^^^^^^^^^^^^^
    )
    ^
  File "/home/bas/venv/lib/python3.13/site-packages/boto3/s3/inject.py", line 642, in upload_fileobj
    return future.result()
           ~~~~~~~~~~~~~^^
  File "/home/bas/venv/lib/python3.13/site-packages/s3transfer/futures.py", line 103, in result
    return self._coordinator.result()
           ~~~~~~~~~~~~~~~~~~~~~~~~^^
  File "/home/bas/venv/lib/python3.13/site-packages/s3transfer/futures.py", line 264, in result
    raise self._exception
  File "/home/bas/venv/lib/python3.13/site-packages/s3transfer/tasks.py", line 135, in __call__
    return self._execute_main(kwargs)
           ~~~~~~~~~~~~~~~~~~^^^^^^^^
  File "/home/bas/venv/lib/python3.13/site-packages/s3transfer/tasks.py", line 158, in _execute_main
    return_value = self._main(**kwargs)
  File "/home/bas/venv/lib/python3.13/site-packages/s3transfer/upload.py", line 796, in _main
    client.put_object(Bucket=bucket, Key=key, Body=body, **extra_args)
    ~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/bas/venv/lib/python3.13/site-packages/botocore/client.py", line 569, in _api_call
    return self._make_api_call(operation_name, kwargs)
           ~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/bas/venv/lib/python3.13/site-packages/botocore/client.py", line 1023, in _make_api_call
    raise error_class(parsed_response, operation_name)
botocore.exceptions.ClientError: An error occurred (MissingContentLength) when calling the PutObject operation: None
@vincentporte vincentporte self-assigned this Jan 29, 2025
@vincentporte vincentporte added the python Pull requests that update Python code label Jan 29, 2025
@vincentporte
Copy link
Contributor Author

OK en local avec minio et variables d'environnements par defaut

AWS_S3_ACCESS_KEY_ID = os.getenv("CELLAR_ADDON_KEY_ID", "minioadmin")
AWS_S3_SECRET_ACCESS_KEY = os.getenv("CELLAR_ADDON_KEY_SECRET", "minioadmin")
AWS_S3_ENDPOINT_URL = (
    f"{os.getenv('CELLAR_ADDON_PROTOCOL', 'http')}://{os.getenv('CELLAR_ADDON_HOST', 'localhost:9000')}"
)

KO en local avec variable environnement de prod (S3 clever) :

CELLAR_ADDON_KEY_ID=xxx
CELLAR_ADDON_KEY_SECRET=xxx
CELLAR_ADDON_HOST=cellar-c2.services.clever-cloud.com
CELLAR_ADDON_PROTOCOL=https

@francoisfreitag
Copy link
Contributor

Probablement une question de serveur (qui supporterait ou non request_checksum_calculation) ?

Idéalement, on utiliserait le même logiciel que Clever pour le S3 de test, mais ça demande plus d’efforts que de démarrer MinIO.

@vincentporte
Copy link
Contributor Author

vincentporte commented Feb 3, 2025

emploi :

  • django-storage 1.14.4
  • boto3 1.35.99
  • botocore 1.35.99
  • s3tranfer 0.10.4

commu :

  • django-storage 1.14.4
  • boto3 1.36.4
  • botocore 1.36.4
  • s3transfer 0.11.1

@vincentporte
Copy link
Contributor Author

vincentporte commented Feb 3, 2025

OK en local avec les variables d'environnement de prod is boto3 et botocore en 1.35.99

@vincentporte
Copy link
Contributor Author

vincentporte commented Feb 3, 2025

KO avec boto3 > 1.36.5 , malgré boto/boto3#4398 (comment)

 - boto3==1.35.99
 + boto3==1.36.11
 - botocore==1.35.99
 + botocore==1.36.11
 - s3transfer==0.10.4
 + s3transfer==0.11.2

@vincentporte vincentporte linked a pull request Feb 3, 2025 that will close this issue
vincentporte added a commit that referenced this issue Feb 3, 2025
## Description

🛑 téléversement de fichier impossible. Erreur 500.

🎸 Issue #897 : `botocore.exceptions.ClientError: An error occurred
(MissingContentLength) when calling the PutObject operation: None`
🛸 suite au passage à `boto3` et `botocore` 1.36
🦺 aurait dû être résolu en `1.36.5`
boto/boto3#4398 (comment)
🦺 mais toujours ko avec la `1.36.11`

## Type de changement

🪲 Correction de bug (changement non cassant qui corrige un problème).
🚧 technique

### Points d'attention

🦺 WORKAROUND en attendant une résolution pérenne : downgrade en
`1.35.99`

---------

Co-authored-by: François Freitag <mail@franek.fr>
@vincentporte
Copy link
Contributor Author

vincentporte commented Feb 3, 2025

stack removed, unuseful

@vincentporte vincentporte reopened this Feb 3, 2025
@vincentporte
Copy link
Contributor Author

vincentporte commented Feb 3, 2025

stack removed, unuseful

@francoisfreitag
Copy link
Contributor

botocore.errorfactory.NoSuchBucket: An error occurred (NoSuchBucket) when calling the PutObject operation: None

Ceci indique que le bucket n’est pas créé dans minio.

@vincentporte
Copy link
Contributor Author

vincentporte commented Feb 3, 2025

et oui, si je ne mets pas la bonne trace, ca marche beaucoup moins bien

  • boto3==1.36.11
  • botocore==1.36.11
  • s3transfer==0.11.2
  • AWS_S3_ENDPOINT_URL=https://cellar-c2.services.clever-cloud.com

celle avec le bon nom de bucket

127.0.0.1 - - [03/Feb/2025 15:49:04] "POST /admin/forum_file/publicfile/add/ HTTP/1.1" 500 -
Traceback (most recent call last):
  File "/home/vincentporte/Products/betagouv/itou-communaute-django/.venv/lib/python3.13/site-packages/django/contrib/staticfiles/handlers.py", line 80, in __call__
    return self.application(environ, start_response)
           ~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/vincentporte/Products/betagouv/itou-communaute-django/.venv/lib/python3.13/site-packages/django/core/handlers/wsgi.py", line 124, in __call__
    response = self.get_response(request)
  File "/home/vincentporte/Products/betagouv/itou-communaute-django/.venv/lib/python3.13/site-packages/django/core/handlers/base.py", line 140, in get_response
    response = self._middleware_chain(request)
  File "/home/vincentporte/Products/betagouv/itou-communaute-django/.venv/lib/python3.13/site-packages/django/core/handlers/exception.py", line 57, in inner
    response = response_for_exception(request, exc)
  File "/home/vincentporte/Products/betagouv/itou-communaute-django/.venv/lib/python3.13/site-packages/django/core/handlers/exception.py", line 140, in response_for_exception
    response = handle_uncaught_exception(
    
  File "/home/vincentporte/Products/betagouv/itou-communaute-django/.venv/lib/python3.13/site-packages/django/core/handlers/exception.py", line 181, in handle_uncaught_exception
    return debug.technical_500_response(request, *exc_info)
           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^
  File "/home/vincentporte/Products/betagouv/itou-communaute-django/.venv/lib/python3.13/site-packages/django_extensions/management/technical_response.py", line 40, in null_technical_500_response
    raise exc_value.with_traceback(tb)
  File "/home/vincentporte/Products/betagouv/itou-communaute-django/.venv/lib/python3.13/site-packages/django/core/handlers/exception.py", line 55, in inner
    response = get_response(request)
  File "/home/vincentporte/Products/betagouv/itou-communaute-django/.venv/lib/python3.13/site-packages/django/core/handlers/base.py", line 197, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/home/vincentporte/.local/share/uv/python/cpython-3.13.1-linux-x86_64-gnu/lib/python3.13/contextlib.py", line 85, in inner
    return func(*args, **kwds)
  File "/home/vincentporte/Products/betagouv/itou-communaute-django/.venv/lib/python3.13/site-packages/django/contrib/admin/options.py", line 718, in wrapper
    return self.admin_site.admin_view(view)(*args, **kwargs)
           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^
  File "/home/vincentporte/Products/betagouv/itou-communaute-django/.venv/lib/python3.13/site-packages/django/utils/decorators.py", line 188, in _view_wrapper
    result = _process_exception(request, e)
  File "/home/vincentporte/Products/betagouv/itou-communaute-django/.venv/lib/python3.13/site-packages/django/utils/decorators.py", line 186, in _view_wrapper
    response = view_func(request, *args, **kwargs)
  File "/home/vincentporte/Products/betagouv/itou-communaute-django/.venv/lib/python3.13/site-packages/django/views/decorators/cache.py", line 80, in _view_wrapper
    response = view_func(request, *args, **kwargs)
  File "/home/vincentporte/Products/betagouv/itou-communaute-django/.venv/lib/python3.13/site-packages/django/contrib/admin/sites.py", line 241, in inner
    return view(request, *args, **kwargs)
  File "/home/vincentporte/Products/betagouv/itou-communaute-django/.venv/lib/python3.13/site-packages/django/contrib/admin/options.py", line 1961, in add_view
    return self.changeform_view(request, None, form_url, extra_context)
           ~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/vincentporte/Products/betagouv/itou-communaute-django/.venv/lib/python3.13/site-packages/django/utils/decorators.py", line 48, in _wrapper
    return bound_method(*args, **kwargs)
  File "/home/vincentporte/Products/betagouv/itou-communaute-django/.venv/lib/python3.13/site-packages/django/utils/decorators.py", line 188, in _view_wrapper
    result = _process_exception(request, e)
  File "/home/vincentporte/Products/betagouv/itou-communaute-django/.venv/lib/python3.13/site-packages/django/utils/decorators.py", line 186, in _view_wrapper
    response = view_func(request, *args, **kwargs)
  File "/home/vincentporte/Products/betagouv/itou-communaute-django/.venv/lib/python3.13/site-packages/django/contrib/admin/options.py", line 1820, in changeform_view
    return self._changeform_view(request, object_id, form_url, extra_context)
           ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/vincentporte/Products/betagouv/itou-communaute-django/.venv/lib/python3.13/site-packages/django/contrib/admin/options.py", line 1871, in _changeform_view
    self.save_model(request, new_object, form, not add)
    ~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/vincentporte/Products/betagouv/itou-communaute-django/lacommunaute/forum_file/admin.py", line 18, in save_model
    obj.save()
    ~~~~~~~~^^
  File "/home/vincentporte/Products/betagouv/itou-communaute-django/.venv/lib/python3.13/site-packages/django/db/models/base.py", line 892, in save
    self.save_base(
    ^
  File "/home/vincentporte/Products/betagouv/itou-communaute-django/.venv/lib/python3.13/site-packages/django/db/models/base.py", line 998, in save_base
    updated = self._save_table(
    
  File "/home/vincentporte/Products/betagouv/itou-communaute-django/.venv/lib/python3.13/site-packages/django/db/models/base.py", line 1161, in _save_table
    results = self._do_insert(
    
  File "/home/vincentporte/Products/betagouv/itou-communaute-django/.venv/lib/python3.13/site-packages/django/db/models/base.py", line 1202, in _do_insert
    return manager._insert(
    
  File "/home/vincentporte/Products/betagouv/itou-communaute-django/.venv/lib/python3.13/site-packages/django/db/models/manager.py", line 87, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^
  File "/home/vincentporte/Products/betagouv/itou-communaute-django/.venv/lib/python3.13/site-packages/django/db/models/query.py", line 1847, in _insert
    return query.get_compiler(using=using).execute_sql(returning_fields)
           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^
  File "/home/vincentporte/Products/betagouv/itou-communaute-django/.venv/lib/python3.13/site-packages/django/db/models/sql/compiler.py", line 1835, in execute_sql
    for sql, params in self.as_sql():
                       ~~~~~~~~~~~^^
  File "/home/vincentporte/Products/betagouv/itou-communaute-django/.venv/lib/python3.13/site-packages/django/db/models/sql/compiler.py", line 1760, in as_sql
    self.prepare_value(field, self.pre_save_val(field, obj))
                              ~~~~~~~~~~~~~~~~~^^^^^^^^^^^^
  File "/home/vincentporte/Products/betagouv/itou-communaute-django/.venv/lib/python3.13/site-packages/django/db/models/sql/compiler.py", line 1708, in pre_save_val
    return field.pre_save(obj, add=True)
           ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^
  File "/home/vincentporte/Products/betagouv/itou-communaute-django/.venv/lib/python3.13/site-packages/django/db/models/fields/files.py", line 338, in pre_save
    file.save(file.name, file.file, save=False)
    ~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/vincentporte/Products/betagouv/itou-communaute-django/.venv/lib/python3.13/site-packages/django/db/models/fields/files.py", line 99, in save
    self.name = self.storage.save(name, content, max_length=self.field.max_length)
                ~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/vincentporte/Products/betagouv/itou-communaute-django/.venv/lib/python3.13/site-packages/django/core/files/storage/base.py", line 49, in save
    name = self._save(name, content)
  File "/home/vincentporte/Products/betagouv/itou-communaute-django/.venv/lib/python3.13/site-packages/storages/backends/s3.py", line 564, in _save
    obj.upload_fileobj(content, ExtraArgs=params, Config=self.transfer_config)
    ~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/vincentporte/Products/betagouv/itou-communaute-django/.venv/lib/python3.13/site-packages/boto3/s3/inject.py", line 731, in object_upload_fileobj
    return self.meta.client.upload_fileobj(
    
  File "/home/vincentporte/Products/betagouv/itou-communaute-django/.venv/lib/python3.13/site-packages/boto3/s3/inject.py", line 642, in upload_fileobj
    return future.result()
           ~~~~~~~~~~~~~^^
  File "/home/vincentporte/Products/betagouv/itou-communaute-django/.venv/lib/python3.13/site-packages/s3transfer/futures.py", line 103, in result
    return self._coordinator.result()
           ~~~~~~~~~~~~~~~~~~~~~~~~^^
  File "/home/vincentporte/Products/betagouv/itou-communaute-django/.venv/lib/python3.13/site-packages/s3transfer/futures.py", line 264, in result
    raise self._exception
  File "/home/vincentporte/Products/betagouv/itou-communaute-django/.venv/lib/python3.13/site-packages/s3transfer/tasks.py", line 135, in __call__
    return self._execute_main(kwargs)
           ~~~~~~~~~~~~~~~~~~^^^^^^^^
  File "/home/vincentporte/Products/betagouv/itou-communaute-django/.venv/lib/python3.13/site-packages/s3transfer/tasks.py", line 158, in _execute_main
    return_value = self._main(**kwargs)
  File "/home/vincentporte/Products/betagouv/itou-communaute-django/.venv/lib/python3.13/site-packages/s3transfer/upload.py", line 796, in _main
    client.put_object(Bucket=bucket, Key=key, Body=body, **extra_args)
    ~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/vincentporte/Products/betagouv/itou-communaute-django/.venv/lib/python3.13/site-packages/botocore/client.py", line 569, in _api_call
    return self._make_api_call(operation_name, kwargs)
           ~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/vincentporte/Products/betagouv/itou-communaute-django/.venv/lib/python3.13/site-packages/botocore/client.py", line 1023, in _make_api_call
    raise error_class(parsed_response, operation_name)
botocore.exceptions.ClientError: An error occurred (MissingContentLength) when calling the PutObject operation: None

@vincentporte vincentporte linked a pull request Feb 3, 2025 that will close this issue
@vincentporte vincentporte linked a pull request Feb 3, 2025 that will close this issue
@vincentporte
Copy link
Contributor Author

vincentporte commented Feb 3, 2025

en accord avec ce post, ajouter ces 2 variables dans les variables d'environnement,
resout le problème d'upload avec boto3>=1.36

AWS_REQUEST_CHECKSUM_CALCULATION=when_required
AWS_RESPONSE_CHECKSUM_VALIDATION=when_required

@francoisfreitag
Copy link
Contributor

Je n’arrive pas à reproduire le problème avec le diff suivant:

diff --git a/config/settings/test.py b/config/settings/test.py
index e4730d0..fd0f622 100644
--- a/config/settings/test.py
+++ b/config/settings/test.py
@@ -27,8 +27,6 @@ AWS_S3_SECRET_ACCESS_KEY = os.getenv("CELLAR_ADDON_KEY_SECRET", "minioadmin")
 AWS_S3_ENDPOINT_URL = (
     f"{os.getenv('CELLAR_ADDON_PROTOCOL', 'http')}://{os.getenv('CELLAR_ADDON_HOST', 'localhost:9000')}"
 )
-AWS_STORAGE_BUCKET_NAME = "private-bucket"
-AWS_STORAGE_BUCKET_NAME_PUBLIC = "public-bucket"
 AWS_S3_STORAGE_BUCKET_REGION = "eu-west-3"
 
 MEDIA_URL = f"{AWS_S3_ENDPOINT_URL}/"
diff --git a/pyproject.toml b/pyproject.toml
index 6f62058..df48999 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -11,7 +11,7 @@ dependencies = [
     "python-dotenv>=1.0",
     "psycopg>=3.2",
     "django-machina>=1.2.0",
-    "boto3<1.36",
+    "boto3",
     "django-storages>=1.14",
     "httpx>=0.28",
     "django-compressor>=4.5",
diff --git a/uv.lock b/uv.lock
index 79a124f..68e78ca 100644
--- a/uv.lock
+++ b/uv.lock
@@ -46,30 +46,30 @@ wheels = [
 
 [[package]]
 name = "boto3"
-version = "1.35.99"
+version = "1.36.11"
 source = { registry = "https://pypi.org/simple" }
 dependencies = [
     { name = "botocore" },
     { name = "jmespath" },
     { name = "s3transfer" },
 ]
-sdist = { url = "https://files.pythonhosted.org/packages/f7/99/3e8b48f15580672eda20f33439fc1622bd611f6238b6d05407320e1fb98c/boto3-1.35.99.tar.gz", hash = "sha256:e0abd794a7a591d90558e92e29a9f8837d25ece8e3c120e530526fe27eba5fca", size = 111028 }
+sdist = { url = "https://files.pythonhosted.org/packages/ee/ac/2b4346474bd3ae501a2fc0e2b5b4f12f412dc89c05bf321a8108d3a95b5c/boto3-1.36.11.tar.gz", hash = "sha256:b40fbf2c0f22e55b67df95475a68bb72be5169097180a875726b6b884339ac8b", size = 111010 }
 wheels = [
-    { url = "https://files.pythonhosted.org/packages/65/77/8bbca82f70b062181cf0ae53fd43f1ac6556f3078884bfef9da2269c06a3/boto3-1.35.99-py3-none-any.whl", hash = "sha256:83e560faaec38a956dfb3d62e05e1703ee50432b45b788c09e25107c5058bd71", size = 139178 },
+    { url = "https://files.pythonhosted.org/packages/4e/a5/e6f90b0a768560a0c44cb9076a313ee6d669ec98fd2747a8451832403ffe/boto3-1.36.11-py3-none-any.whl", hash = "sha256:641dd772eac111d9443258f0f5491c57c2af47bddae94a8d32de19edb5bf7b1c", size = 139177 },
 ]
 
 [[package]]
 name = "botocore"
-version = "1.35.99"
+version = "1.36.11"
 source = { registry = "https://pypi.org/simple" }
 dependencies = [
     { name = "jmespath" },
     { name = "python-dateutil" },
     { name = "urllib3" },
 ]
-sdist = { url = "https://files.pythonhosted.org/packages/7c/9c/1df6deceee17c88f7170bad8325aa91452529d683486273928eecfd946d8/botocore-1.35.99.tar.gz", hash = "sha256:1eab44e969c39c5f3d9a3104a0836c24715579a455f12b3979a31d7cde51b3c3", size = 13490969 }
+sdist = { url = "https://files.pythonhosted.org/packages/a5/0f/6b92050154ad0e286b82ca36de5f87a466723e1cdc525df53270bcc36f60/botocore-1.36.11.tar.gz", hash = "sha256:c919be883f95b9e0c3021429a365d40cd7944b8345a07af30dc8d891ceefe07a", size = 13497505 }
 wheels = [
-    { url = "https://files.pythonhosted.org/packages/fc/dd/d87e2a145fad9e08d0ec6edcf9d71f838ccc7acdd919acc4c0d4a93515f8/botocore-1.35.99-py3-none-any.whl", hash = "sha256:b22d27b6b617fc2d7342090d6129000af2efd20174215948c0d7ae2da0fab445", size = 13293216 },
+    { url = "https://files.pythonhosted.org/packages/2c/ce/e97be00389d51a010c0680ea688a073737ca3b2de6f924800fc61bf68e41/botocore-1.36.11-py3-none-any.whl", hash = "sha256:82c5660027f696608d0e55feb08c146c11c7ebeba7615961c7765dcf6009a00d", size = 13327743 },
 ]
 
 [[package]]
@@ -730,7 +730,7 @@ dev = [
 
 [package.metadata]
 requires-dist = [
-    { name = "boto3", specifier = "==1.35.99" },
+    { name = "boto3" },
     { name = "django", specifier = ">=5.1" },
     { name = "django-compressor", specifier = ">=4.5" },
     { name = "django-csp", specifier = ">=3.8" },
@@ -1203,14 +1203,14 @@ wheels = [
 
 [[package]]
 name = "s3transfer"
-version = "0.10.4"
+version = "0.11.2"
 source = { registry = "https://pypi.org/simple" }
 dependencies = [
     { name = "botocore" },
 ]
-sdist = { url = "https://files.pythonhosted.org/packages/c0/0a/1cdbabf9edd0ea7747efdf6c9ab4e7061b085aa7f9bfc36bb1601563b069/s3transfer-0.10.4.tar.gz", hash = "sha256:29edc09801743c21eb5ecbc617a152df41d3c287f67b615f73e5f750583666a7", size = 145287 }
+sdist = { url = "https://files.pythonhosted.org/packages/62/45/2323b5928f86fd29f9afdcef4659f68fa73eaa5356912b774227f5cf46b5/s3transfer-0.11.2.tar.gz", hash = "sha256:3b39185cb72f5acc77db1a58b6e25b977f28d20496b6e58d6813d75f464d632f", size = 147885 }
 wheels = [
-    { url = "https://files.pythonhosted.org/packages/66/05/7957af15543b8c9799209506df4660cba7afc4cf94bfb60513827e96bed6/s3transfer-0.10.4-py3-none-any.whl", hash = "sha256:244a76a24355363a68164241438de1b72f8781664920260c48465896b712a41e", size = 83175 },
+    { url = "https://files.pythonhosted.org/packages/1b/ac/e7dc469e49048dc57f62e0c555d2ee3117fa30813d2a1a2962cce3a2a82a/s3transfer-0.11.2-py3-none-any.whl", hash = "sha256:be6ecb39fadd986ef1701097771f87e4d2f821f27f6071c872143884d2950fbc", size = 84151 },
 ]
 
 [[package]]

Dans mon environnement, j’ai:

export CELLAR_ADDON_KEY_ID=KEY_ID
export CELLAR_ADDON_KEY_SECRET=SECRET
export CELLAR_ADDON_PROTOCOL=https
export CELLAR_ADDON_HOST=cellar-c2.services.clever-cloud.com
export S3_STORAGE_BUCKET_NAME_PUBLIC=c3-django-review-bucket-public

@francoisfreitag
Copy link
Contributor

francoisfreitag commented Feb 3, 2025

Tu trouveras ma belle image cat-2083492_1280.jpg téléversée via l’admin forum_file PublicFile.

@francoisfreitag
Copy link
Contributor

🤦, j’arrive à reproduire, il manquait un uv sync après l’upgrade.

@francoisfreitag
Copy link
Contributor

Et du coup, le correctif:

diff --git a/config/settings/base.py b/config/settings/base.py
index 32bbbf0..cefbcd6 100644
--- a/config/settings/base.py
+++ b/config/settings/base.py
@@ -1,5 +1,6 @@
 import os
 
+from botocore.config import Config
 from dotenv import load_dotenv
 from machina import MACHINA_MAIN_STATIC_DIR, MACHINA_MAIN_TEMPLATE_DIR
 
@@ -273,6 +274,13 @@ AWS_S3_ENDPOINT_URL = f"{os.getenv('CELLAR_ADDON_PROTOCOL', 'https')}://{os.gete
 AWS_STORAGE_BUCKET_NAME = os.getenv("S3_STORAGE_BUCKET_NAME")
 AWS_STORAGE_BUCKET_NAME_PUBLIC = os.getenv("S3_STORAGE_BUCKET_NAME_PUBLIC")
 AWS_S3_STORAGE_BUCKET_REGION = os.getenv("S3_STORAGE_BUCKET_REGION")
+# CleverCloud S3 implementation does not support recent data integrity features from AWS.
+# https://github.com/boto/boto3/issues/4392
+# https://github.com/boto/boto3/issues/4398#issuecomment-2619946229
+AWS_S3_CLIENT_CONFIG = Config(
+    request_checksum_calculation="when_required",
+    response_checksum_validation="when_required",
+)
 
 # MEDIA CONFIGURATION
 # ------------------------------------------------------------------------------

@vincentporte
Copy link
Contributor Author

avec le test cassant attendu dans la CI, jusqu'à ce que clever gère ce paramètre

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
python Pull requests that update Python code
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants