Tiedostojen jakaminen Google Drivesta nginxillä

esihistoria

Sattui vain niin, että minun piti tallentaa yli 1.5 TB tietoa jonnekin ja tarjota myös tavallisille käyttäjille mahdollisuus ladata se suoran linkin kautta. Koska perinteisesti tällaiset määrät muistia menevät VDS:lle, vuokraus, joka ei juurikaan sisälly projektibudjettiin "ei mitään tekemistä" -kategoriasta, ja lähdetiedoista minulla oli VPS 400GB SSD, jossa vaikka Halusin, en voinut laittaa 1.5 Tt kuvia ilman häviötöntä pakkausta, se onnistuu.

И тут я вспомнил про то, что если удалить с гугл-диска хлам, вроде программ, которые запустятся только на Windows XP, и прочие вещи, которые кочуют у меня с носителя на носитель с тех пор, когда интернет был не таким быстрым и вовсе не безлимитным (например, те 10-20 версий virtual box вряд ли имели какую-то ценность, кроме ностальгической), то все должно очень даже хорошо вместиться. Сказано — сделано. И вот, пробиваясь через лимит на количество запросов к api (кстати, техподдержка без проблем увеличила квоту запросов на пользователя за 100 секунд до 10 000) данные резво потекли в место своей дальнейшей дислокации.

Kaikki näyttää olevan hyvin, mutta nyt se on välitettävä loppukäyttäjälle. Lisäksi ilman uudelleenohjauksia muihin resursseihin, vaan niin, että henkilö painaa vain "Lataa" -painiketta ja hänestä tulee arvokkaan tiedoston onnellinen omistaja.

Täällä, Jumala, jouduin kaikenlaisiin ongelmiin. Aluksi se oli AmPHP-skripti, mutta en ollut tyytyväinen sen luomaan kuormaan (jyrkkä hyppy alussa 100% ydinkulutukseen). Sitten tuli peliin ReactPHP:n curl-kääre, joka sopi hyvin toiveisiini kulutettujen prosessorijaksojen lukumäärän suhteen, mutta ei antanut nopeutta ollenkaan mitä halusin (kävi ilmi, että voit yksinkertaisesti lyhentää soittoväliä curl_multi_select, mutta silloin meillä on samanlainen ahmatti kuin ensimmäisessä vaihtoehdossa ). Yritin jopa kirjoittaa pienen palvelun Rustiin, ja se toimi melko nopeasti (yllättävää, että se toimi, tietämykseni perusteella), mutta halusin enemmän, ja sitä oli jotenkin vaikea muokata. Lisäksi kaikki nämä ratkaisut jotenkin oudosti puskuroivat vastausta, ja halusin seurata hetkeä, jolloin tiedostojen lataus päättyi suurimmalla tarkkuudella.

Yleensä se oli jonkin aikaa vinossa, mutta se toimi. Kunnes eräänä päivänä keksin idean, joka oli hämmästyttävä hulluudellaan: nginx voi teoriassa tehdä mitä haluan, työskennellä nopeasti ja jopa sallia kaikenlaiset perversiot konfiguroinnilla. Meidän on yritettävä - entä jos se toimii? Ja puolen päivän jatkuvan etsinnän jälkeen syntyi ratkaisu, joka oli toiminut vakaasti useita kuukausia ja täytti kaikki vaatimukseni.

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

Lyhyt versio ilman kommentteja löytyy spoilerin alta

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

Kirjoitamme käsikirjoitusta hallitaksemme kaikkea tätä onnellisuutta

Esimerkki on PHP:llä ja tarkoituksella kirjoitettu vähimmäismäärällä. Uskon, että jokainen, jolla on kokemusta jostain muusta kielestä, pystyy integroimaan tämän osion esimerkkiäni avulla.

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

Tulokset

Yleensä tämän menetelmän avulla on melko helppoa järjestää tiedostojen jakelu käyttäjille mistä tahansa pilvitallennustilasta. Kyllä, jopa sähkeestä tai VK:sta (edellyttäen, että tiedostokoko ei ylitä tämän tallennustilan sallittua kokoa). Minulla oli samanlainen idea tämä, mutta valitettavasti törmään 2GB tiedostoihin, enkä ole vielä löytänyt menetelmää tai moduulia vastausten liimaamiseen ylävirrasta, ja jonkinlaisten kääreiden kirjoittaminen tähän projektiin on kohtuuttoman työvoimavaltaista.

Kiitos huomiostasi. Toivottavasti tarinani oli ainakin hieman kiinnostava tai hyödyllinen sinulle.

Lähde: will.com

Osta luotettava isännöinti sivustoille, joissa on DDoS-suojaus, VPS VDS -palvelimet 🔥 Osta luotettavaa verkkosivustojen hostingia DDoS-suojauksella, VPS VDS -palvelimilla | ProHoster