Skip to content

feat: separate MinIO write path from public URL#999

Closed
rondinelisaad wants to merge 1 commit into
mainfrom
codex/minio-read-write-paths
Closed

feat: separate MinIO write path from public URL#999
rondinelisaad wants to merge 1 commit into
mainfrom
codex/minio-read-write-paths

Conversation

@rondinelisaad

@rondinelisaad rondinelisaad commented Jun 19, 2026

Copy link
Copy Markdown
Member

O que esse PR faz?

Separa o endpoint/caminho de gravação no MinIO/S3 da URL pública de leitura armazenada no banco.

A mudança adiciona suporte a:

  • write_prefix: prefixo usado no object storage durante a gravação.
  • public_base_url: URL pública usada para montar a URI salva/lida pela aplicação.
  • uri com max_length=500, para suportar URLs públicas mais longas.

Com isso, é possível gravar arquivos em um bucket/caminho como scielo/upload/... usando s3.wasabisys.com, mas armazenar no banco uma URL pública como https://minio.scielo.br/upload/....

Onde a revisão poderia começar?

Comece por:

  • files_storage/minio.py

Depois revise:

  • files_storage/models.py
  • files_storage/migrations/0005_minioconfiguration_public_read_write_prefix_and_more.py
  • files_storage/test_minio.py

Como este poderia ser testado manualmente?

  1. Rodar as migrações:

    docker compose -f local.yml run --rm django python manage.py migrate
  2. Configurar um registro MinioConfiguration com:

    name: website
    host: s3.wasabisys.com
    bucket_root: scielo
    write_prefix: upload
    public_base_url: https://minio.scielo.br/upload
    secure: true
    
  3. Enviar/publicar um pacote que acione o fluxo de upload para MinIO.

  4. Confirmar que o objeto foi gravado no storage em:

    bucket: scielo
    object: upload/<caminho-do-arquivo>
    
  5. Confirmar que a URI salva no banco usa a URL pública:

    https://minio.scielo.br/upload/<caminho-do-arquivo>
    
  6. Rodar os testes automatizados:

    docker compose -f local.yml run --rm django python manage.py test files_storage.test_minio

Algum cenário de contexto que queira dar?

Antes deste PR, a URL salva no banco era derivada do mesmo cliente MinIO usado para gravação via presigned_get_object. Isso acoplava o endpoint de escrita à URL de leitura.

No cenário atual, a aplicação precisa gravar no endpoint S3/Wasabi (s3.wasabisys.com) usando o bucket scielo e o prefixo upload, mas os consumidores devem ler os arquivos por uma URL pública diferente: https://minio.scielo.br/upload.

Screenshots

Não aplicável. A alteração é de backend/configuração de storage.

Quais são tickets relevantes?

Não informado.

Referências

  • Implementação existente em files_storage/minio.py.
  • Configuração existente em files_storage/models.py.
  • SDK MinIO Python: fput_object e presigned_get_object.

@robertatakenaka

Copy link
Copy Markdown
Member

@rondinelisaad não poderíamos ter uma URL para escrita e outra para leitura? Isso funcionaria para a demanda?

@rondinelisaad

Copy link
Copy Markdown
Member Author

@rondinelisaad não poderíamos ter uma URL para escrita e outra para leitura? Isso funcionaria para a demanda?

@robertatakenaka essa é a intenção. A url de leitura é minio.scielo.br e a de gravação será o endpoint definido pelo provedor. Exemplo: s3.wasabisys.com

@robertatakenaka

Copy link
Copy Markdown
Member

@rondinelisaad mas acho que está complicando com

bucket_root: scielo
write_prefix: upload

@rondinelisaad

Copy link
Copy Markdown
Member Author

@rondinelisaad mas acho que está complicando com

bucket_root: scielo write_prefix: upload

Não acho que fica complicado dessa forma, o complicado é quando vc não trata níveis diferentes de depósito. O padrão que o minio usa não é comum entra as nuvens. E essa sugestão trata pelo o menos dois níveis. Lembrando que se o write_prefix ficar vazio ele vai considerar apenas um nível. Da mesma forma como é no minio hj.

Comment thread files_storage/minio.py
self.http_client = minio_http_client
self._client_instance = None
self.location = location
self.location = location or bucket_subdir

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rondinelisaad é um erro considerar location como um subdir.

Cria um bucket no MinIO/S3.

self._client — cliente MinIO (instância de Minio).
make_bucket(...) — cria um novo bucket no armazenamento de objetos.
self.bucket_root — nome do bucket a ser criado.
location=self.location — região onde o bucket será criado (ex.: "us-east-1").

Não. make_bucket não aceita caminhos com / — o nome do bucket é plano, não hierárquico.

Buckets S3/MinIO não têm subdiretórios reais. A "estrutura de pastas" é uma ilusão criada por prefixos na chave do objeto, não no nome do bucket.
"pasta/subpasta" como nome de bucket falharia: / é caractere inválido em nome de bucket (regras S3). Você receberia um erro de validação (InvalidBucketName).

# bucket plano
self._client.make_bucket("scielo-assets")

# "pastas" via prefixo na chave do objeto
self._client.put_object(
    "scielo-assets",
    "pasta/subpasta/arquivo.pdf",  # aqui o / é permitido e simula diretórios
    data, length,
)

@robertatakenaka robertatakenaka left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Veja meu comentário

@rondinelisaad

Copy link
Copy Markdown
Member Author

Veja meu comentário

Oi @robertatakenaka
Faz sentido esse ponto colocado. Vc vai ajustar ou quer que abra um PR?
Abs,

@robertatakenaka

Copy link
Copy Markdown
Member

@rondinelisaad deixa que eu faço

@robertatakenaka

Copy link
Copy Markdown
Member

#1015 substitui este

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants