URL do S3 CDN não está sendo usada em uploads que não são de imagem

Talvez relacionado a URL do CDN S3 ignorada ao fazer upload em posts.

A princípio, pensei que tivesse perdido alguma configuração, mas é reproduzível aqui no meta:
https://meta.discourse.org/uploads/short-url/dw1U4hctATusBlHsUmWQXeme66j.csv (upload aqui) é um redirecionamento 302 para
//assets-meta-cdck-prod-meta.s3.dualstack.us-west-1.amazonaws.com/original/3X/5/e/5ebb2cfb8cc907e8e8f7c6559a72d2f4a8ba2f8f.csv

Não deveria redirecionar para https://d11a6trkgmumsb.cloudfront.net/original/3X/5/e/5ebb2cfb8cc907e8e8f7c6559a72d2f4a8ba2f8f.csv em vez disso?

5 curtidas

Hmm, pode haver um problema aqui @martin, você pode investigar? Devemos redirecionar para o CDN, se possível.

5 curtidas

Isso é um pouco complicado, acabei de dar uma olhada nisso. Basicamente, sempre fazemos o download do S3 usando uma URL assinada quando realizamos um “download forçado”, que é o que ocorre ao clicar no link do anexo ou no botão Download em uma imagem. Isso é necessário para que os cabeçalhos content-disposition apropriados sejam adicionados:

attachment; filename="#{upload.original_filename}"; filename*=UTF-8''#{upload.original_filename}

Acho que não é possível fazer com que a URL da CDN se comporte dessa forma? A URL da CDN para imagens é usada apenas na exibição inline, não durante o download. Além disso, no caso de imagens e anexos seguros que possuem ACL privada, a URL assinada deve sempre ser utilizada.

2 curtidas

@martin em relação a links de anexos, não consigo ver como eles podem ser definidos para sempre “forçar download”. No momento, ao carregar um arquivo que não seja de imagem, a URL renderizada resultante é uma URL curta sem o parâmetro ?dl=1, que é resolvida para o valor do atributo url do upload correspondente (que não é uma URL pré-assinada e também falha em nosso caso, pois a URL não é a cdn_url do S3, mas uma construída que pode funcionar apenas para certos provedores S3).

Existe alguma maneira de forçar sempre o download de anexos, ou o comportamento atual é realmente um bug?

1 curtida

Você pode explicar melhor? Você está usando o Amazon S3 ou um provedor diferente? Se sim, qual?

1 curtida

Sim, parece que estou usando um provedor S3 não suportado (OVH Object Storage)

Com uma URL de endpoint de https://s3.de.ovh.cloud.net e uma s3 cdn_url configurada para https://storage.de.ovh.cloud.net/v1/<algum-id-de-usuário-único>/<o-nome-do-bucket>

Quando URLs curtas são resolvidas, o Discourse usa a URL do endpoint para construir a URL resultante (o que falha, pois não inclui o ID de usuário OVH correto - a parte na s3 cdn_url).

Forçar URLs curtas a terem dl=1 construiria uma presigned_url funcional, o que seria bom para mim.

Eu defini essas variáveis de ambiente (específicas de S3) dentro do YAML do contêiner:

DISCOURSE_USE_S3: true
DISCOURSE_S3_REGION: DE
DISCOURSE_S3_ENDPOINT: https://s3.de.cloud.ovh.net
DISCOURSE_S3_ACCESS_KEY_ID: ...
DISCOURSE_S3_SECRET_ACCESS_KEY: ...
DISCOURSE_S3_CDN_URL: https://storage.de.ovh.cloud.net/v1/<algum-id-de-usuário-único>/<o-nome-do-bucket>
DISCOURSE_S3_UPLOAD_BUCKET: <o-nome-do-bucket>
DISCOURSE_S3_INSTALL_CORS_RULE: false
1 curtida

Talvez isso esteja fora do escopo deste tópico, mas se o comportamento atual for intencional, como ou onde se poderia substituir a renderização de URLs curtas no frontend? Estou pensando em simplesmente me conectar ao processo de cozimento de posts e, em seguida, anexar o parâmetro de consulta aos URLs curtos de anexos. Estou ciente de como escrever plugins js para o Discourse, mas na maioria das vezes tenho dificuldade em encontrar o Widget certo para “reabrir” ou a função para substituir.

Ok, então encontrei o local onde o Markdown para anexos é gerado e, pelo que entendi da API do plugin, não se pode (facilmente) substituí-lo (até acho que não se deveria fazer isso).

Então, meu pensamento inicial de adicionar um parâmetro ?dl=1 a esses URLs parece ser a maneira errada de fazer isso.

Em relação a não forçar downloads para short-urls resolvidos: Se entendi corretamente o argumento contra ACLs públicas em buckets S3, deve-se:

  1. Servir arquivos do S3 via CDN (inviável para anexos, como @martin apontou, pois podemos não conseguir definir corretamente o nome do arquivo para download neste caso)
  2. Criar uma URL pré-assinada para o objeto S3

Mas o comportamento atual não faz nem um nem outro e espera que o bucket S3 tenha uma ACL pública. Este também parece ser o caso para provedores S3 suportados (incluindo a Amazon), então eu perguntaria por que não tornar a opção force_download em Discourse.store.url_for o padrão como true ao resolver short-urls para stores S3?

1 curtida

Estou tendo o mesmo problema aqui, o que eu espero é que o arquivo atrás de uploads/short-url seja baixado ou redirecionado para a URL do CDN da S3.

2 curtidas

Estamos enfrentando o mesmo problema com o Cloudflare R2, pois ele não parece permitir o uso da URL S3 direta sem uma URL pré-assinada.
E o R2 não suporta ACL para buckets.

Parece que o Discourse adicionou recentemente uma opção “s3 use cdn url for all uploads” que resolve este problema.