Temos um cliente com problemas no upload de mídia segura.
Esse cliente está executando um Discourse baseado em Docker (instalação oficial) com AWS S3 e mídia segura habilitada.
O fórum possui vários arquivos de som nos formatos mp3 e m4a.
O Discourse incorpora automaticamente um player agradável, como este:
Problema: os arquivos de som não funcionam de forma confiável. Às vezes, eles não são reproduzidos.
Não consigo reproduzir isso 100% das vezes; acredito que seja devido ao cache, mas parece que o download é adiado até que o botão de reprodução seja pressionado. Isso parece lógico e bom.
No entanto, isso não funciona bem com uploads de mídia segura: se você deixar uma página aberta por um tempo e pressionar o botão de reprodução após um minuto ou mais, o arquivo de som não será reproduzido (nem sempre). Nesse ponto, o AWS retorna um erro 403 Expired. Parece que a solicitação não foi assinada no momento em que o arquivo foi solicitado, mas sim anteriormente. A mensagem de erro indica claramente que a solicitação expirou no passado.
Suspeito que isso esteja relacionado ao atraso, mas não tenho 100% de certeza. O fato é que isso está acontecendo apenas com arquivos de som (ou seja, não com imagens incorporadas, que são sempre baixadas imediatamente).
Sim, o horário do servidor está correto.
Consigo reproduzir em uma instalação recente executando a versão beta mais recente. Basta colocar dois arquivos de som em um tópico e brincar um pouco.
Isso pode ser devido à forma como os navegadores lidam com as tags de áudio e vídeo e ao valor padrão de preload. Os arquivos são especialmente longos? Pelo que sei, os navegadores fazem o download usando intervalos de bytes sob demanda.
Se você tiver uma tag <audio> ou <video>, definir o atributo preload=auto nela indicará ao navegador para baixá-la inteira ao carregar a página, assim você não teria esse problema com a expiração da URL assinada do S3.
Como costuma acontecer com essas coisas, os sites começaram a abusar desse atributo e ele não é mais seguido cegamente, mas é um hint que o navegador considerará.
Não há uma tag <audio> explícita; ela é gerada automaticamente pelo Discourse quando o arquivo de áudio é inserido, sem o atributo preload.
A parte que não entendo: se a rota /secure-media-uploads está gerando a URL assinada, por que importa quanto tempo passa entre o carregamento da página e o acesso à rota? Afinal, ela gera a rota assinada e imediatamente redireciona para ela. Mas, de alguma forma, parece importar mesmo. Parece que algo está sendo armazenado em cache ou algo assim?
Existe no HTML gerado a partir da marcação do post, e é disso que estou falando. Diria que faz sentido adicionar esse atributo quando a configuração estiver habilitada.
Acredito que todo o ponto da funcionalidade seja exatamente isso. Ter URLs que não podem ser compartilhadas em outros lugares para os uploads, e a única maneira de fazer isso é usando URLs que expiram.
Sim, eu entendo isso. E o temporizador de expiração começa a contar no momento em que a rota /secure-media-uploads é chamada, e não quando a página é carregada.
Ainda assim, parece importar se a página foi carregada muito antes da rota ser acessada. E então algo quebra, de alguma forma. Só não entendo por que isso está acontecendo.
Isso já foi corrigido aqui: FIX: Disable preloading audio + video when secure media enabled (#8922) · discourse/discourse@7ff58f1 · GitHub@RGJ. O problema ocorria porque os navegadores enviam uma solicitação inicial para arquivos de áudio e vídeo para obter metadados, como a duração. No entanto, devido à URL assinada segura, essa solicitação inicial iniciava a contagem regressiva de expiração de 15 segundos. Assim, quando os usuários tentavam reproduzir o áudio e o vídeo após esse período, recebíamos o erro 403 da AWS.
Agora, desativamos o pré-carregamento em vídeos e áudios quando a mídia segura está habilitada. Postagens existentes com áudio e vídeo precisarão ter seu HTML recriado para que a alteração seja aplicada.