Mengedarkan fail daripada Google Drive menggunakan nginx

prasejarah

Kebetulan saya perlu menyimpan lebih daripada 1.5 TB data di suatu tempat, dan juga menyediakan keupayaan untuk pengguna biasa memuat turunnya melalui pautan terus. Oleh kerana secara tradisinya jumlah memori seperti itu pergi ke VDS, kos penyewaan yang tidak begitu banyak termasuk dalam belanjawan projek dari kategori "tiada untuk dilakukan", dan dari data sumber saya mempunyai VPS 400GB SSD, di mana, walaupun saya mahu, saya tidak boleh meletakkan 1.5TB imej tanpa pemampatan tanpa kehilangan ia akan berjaya.

Dan kemudian saya teringat bahawa jika saya memadamkan sampah dari Google Drive, seperti program yang hanya akan dijalankan pada Windows XP, dan perkara lain yang telah berpindah dari satu peranti ke peranti lain sejak zaman Internet tidak begitu pantas sama sekali tidak terhad ( sebagai contoh, 10-20 versi kotak maya itu tidak mungkin mempunyai sebarang nilai selain daripada nostalgia), maka semuanya harus sesuai dengan baik. Tidak lebih awal berkata daripada selesai. Oleh itu, dengan menerobos had bilangan permintaan kepada api (dengan cara itu, sokongan teknikal tanpa sebarang masalah meningkatkan kuota permintaan setiap pengguna kepada 100 dalam 10 saat), data dengan cepat mengalir ke tempat penggunaan selanjutnya .

Semuanya nampak baik, tetapi kini ia perlu disampaikan kepada pengguna akhir. Lebih-lebih lagi, tanpa sebarang ubah hala ke sumber lain, tetapi supaya seseorang hanya menekan butang "Muat turun" dan menjadi pemilik gembira fail yang berharga itu.

Di sini, demi Tuhan, saya mengalami pelbagai masalah. Pada mulanya ia adalah skrip dalam AmPHP, tetapi saya tidak berpuas hati dengan beban yang dibuatnya (lonjakan mendadak pada permulaan kepada penggunaan teras 100%). Kemudian pembungkus curl untuk ReactPHP dimainkan, yang agak sesuai dengan kehendak saya dari segi bilangan kitaran CPU yang digunakan, tetapi tidak memberikan kelajuan sama sekali apa yang saya mahukan (ternyata anda hanya boleh mengurangkan selang panggilan curl_multi_select, tetapi kemudian kita mempunyai kerakusan yang serupa dengan pilihan pertama ). Saya juga cuba menulis perkhidmatan kecil dalam Rust, dan ia berfungsi dengan cepat (mengejutkan bahawa ia berfungsi, berdasarkan pengetahuan saya), tetapi saya mahukan lebih banyak lagi, dan entah bagaimana sukar untuk menyesuaikannya. Di samping itu, semua penyelesaian ini entah bagaimana peliknya menimbal tindak balas, dan saya ingin menjejaki saat apabila muat turun fail berakhir dengan ketepatan yang paling tinggi.

Secara umum, ia bengkok untuk seketika, tetapi ia berfungsi. Sehingga suatu hari saya mendapat idea yang luar biasa dalam kegilaannya: nginx, secara teori, boleh melakukan apa yang saya mahu, bekerja dengan cepat, dan juga membenarkan semua jenis penyelewengan dengan konfigurasi. Kita perlu mencuba - bagaimana jika ia berkesan? Dan selepas setengah hari pencarian yang berterusan, penyelesaian telah lahir yang telah berfungsi dengan stabil selama beberapa bulan dan memenuhi semua keperluan saya.

Menyediakan 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;
}

Versi pendek tanpa komen boleh dilihat di bawah 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;
}

Kami sedang menulis skrip untuk menguruskan semua kebahagiaan ini

Contoh akan dalam PHP dan sengaja ditulis dengan kit minimum. Saya rasa sesiapa yang mempunyai pengalaman dengan mana-mana bahasa lain akan dapat mengintegrasikan bahagian ini menggunakan contoh saya.

<?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));

Keputusan

Secara umum, kaedah ini menjadikannya agak mudah untuk mengatur pengedaran fail kepada pengguna dari mana-mana storan awan. Ya, walaupun dari telegram atau VK, (dengan syarat saiz fail tidak melebihi saiz storan yang dibenarkan). Saya mempunyai idea yang serupa dengan ini, tetapi malangnya saya menjumpai fail sehingga 2GB, dan saya masih belum menemui kaedah atau modul untuk melekatkan respons dari huluan, dan menulis beberapa jenis pembungkus untuk projek ini adalah tidak munasabah intensif buruh.

Terima kasih kerana memberi perhatian. Saya harap cerita saya sekurang-kurangnya menarik atau berguna kepada anda.

Sumber: www.habr.com

Tambah komen