Distribuímos arquivos do Google Drive usando nginx

Antecedentes


Aconteceu que eu precisava de um lugar para armazenar mais de 1,5 TB de dados e até fornecer a capacidade de baixá-los por usuários comuns por meio de um link direto. Como tradicionalmente essas quantidades de memória já vão para o VDS, cujo custo de aluguel não é muito investido no orçamento do projeto da categoria "nada a fazer", e dos dados de origem eu tinha um SSD VPS de 400GB, onde não era possível colocar 1,5 TB de imagens sem compactação sem perdas terá sucesso.


E então lembrei que, se você excluir o lixo da unidade do Google, como programas executados apenas no Windows XP, e outras coisas que vagam da minha mídia para a mídia, uma vez que a Internet não era tão rápida e completa ilimitado (por exemplo, é improvável que essas versões de 10 a 20 da caixa virtual tenham outro valor além de nostálgico), então tudo deve se encaixar muito bem. Mal disse o que fez. E assim, percorrendo o limite do número de solicitações de API (a propósito, o suporte técnico sem problemas aumentou a cota de solicitações por usuário em 100 segundos para 10.000), os dados fluíram rapidamente para o local de sua implantação posterior.


Tudo parece estar bem, mas agora precisa ser transmitido ao usuário final. Além disso, sem redirecionamentos para outros recursos, e para que uma pessoa simplesmente clique no botão "Download" e se torne o proprietário sortudo do arquivo estimado.


Então, por Deus, parti de todas as formas sérias. No começo, era um script no AmPHP, mas não fiquei satisfeito com a carga criada (um salto acentuado na inicialização para 100% do consumo do kernel). Então o wrapper curl do ReactPHP entrou em ação, o que se encaixava perfeitamente nos meus desejos para o número consumido de ciclos de clock da CPU, mas não dava a velocidade do que eu queria (acabou que você pode simplesmente reduzir o intervalo de chamada curl_multi_select, mas temos a mesma gula para a primeira opção ) Eu até tentei escrever um pequeno serviço no Rust, e funcionou rapidamente (e surpreendentemente, funcionou com o meu conhecimento), mas eu queria mais e, de alguma forma, não foi fácil personalizá-lo. Além disso, todas essas soluções de alguma forma estranhamente armazenaram a resposta, e eu queria acompanhar o momento em que o download do arquivo com a maior precisão terminou.


Em geral, por um tempo ficou torto, mas funcionou. Até que um dia tive a ideia de uma maravilhosa idéia ilusória: o nginx em teoria pode fazer o que eu quero, funciona rapidamente e até permite todos os tipos de perversões na configuração. Temos que tentar - e se der certo? E, após meio dia de pesquisas persistentes, uma solução funcionou de maneira estável por vários meses, que atendeu a todos os meus requisitos.


Personalizar NGINX


#         . location ~* ^/google_drive/(.+)$ { #       (,     ). internal; #       (  ). limit_rate 1m; #   nginx    google drive    . resolver 8.8.8.8; # C     (    ). set $download_url https://www.googleapis.com/drive/v3/files/$upstream_http_file_id?alt=media; #    Content-Disposition ,        . set $content_disposition 'attachment; filename="$upstream_http_filename"'; #     . proxy_max_temp_file_size 0; # ,  ,     (  ,     $http_upstream    .   ,     -  ,      ). proxy_set_header Authorization 'Bearer $1'; #  ,         . proxy_pass $download_url; #              . add_header Content-Disposition $content_disposition; #        . proxy_hide_header Content-Disposition; proxy_hide_header Alt-Svc; proxy_hide_header Expires; proxy_hide_header Cache-Control; proxy_hide_header Vary; proxy_hide_header X-Goog-Hash; proxy_hide_header X-GUploader-UploadID; } 

Uma versão curta sem comentários pode ser vista sob o spoiler
 location ~* ^/google_drive/(.+)$ { internal; limit_rate 1m; resolver 8.8.8.8; set $download_url https://www.googleapis.com/drive/v3/files/$upstream_http_file_id?alt=media; set $content_disposition 'attachment; filename="$upstream_http_filename"'; proxy_max_temp_file_size 0; proxy_set_header Authorization 'Bearer $1'; proxy_pass $download_url; add_header Content-Disposition $content_disposition; proxy_hide_header Content-Disposition; proxy_hide_header Alt-Svc; proxy_hide_header Expires; proxy_hide_header Cache-Control; proxy_hide_header Vary; proxy_hide_header X-Goog-Hash; proxy_hide_header X-GUploader-UploadID; } 



Escrever um script para gerenciar toda essa felicidade


O exemplo será em PHP e propositalmente escrito com um kit de corpo mínimo. Acho que todos que têm experiência com qualquer outro idioma poderão integrar este artigo usando o meu exemplo.


 <?php #   Google Drive Api. define('TOKEN', '*****'); # ID     $fileId = 'abcdefghijklmnopqrstuvwxyz1234567890'; # ,         -    ? http_response_code(204); #   c ID  (  nginx      $upstream_http_file_id). header('File-Id: ' . $fileId); #      ( $upstream_http_filename). header('Filename: ' . 'test.zip'); #  .       ,  ,     $1  nginx. header('X-Accel-Redirect: ' . rawurlencode('/google_drive/' . TOKEN)); 

Sumário


Em geral, esse método facilita bastante a organização da distribuição de arquivos para os usuários a partir de qualquer armazenamento em nuvem. Sim, mesmo de telegrama ou VK, (desde que o tamanho do arquivo não exceda o tamanho permitido para este repositório). Tive uma ideia semelhante a essa , mas infelizmente me deparei com arquivos de até 2 GB e ainda não encontrei uma maneira ou módulo para colar as respostas do upstream, escrever alguns invólucros para este projeto é excessivamente trabalhoso.


Obrigado pela atenção. Espero que minha história seja pelo menos um pouco interessante ou útil para você.

Source: https://habr.com/ru/post/pt460685/


All Articles