Dreifing skráa frá Google Drive með nginx

Forsaga

Það gerðist bara að ég þurfti að geyma meira en 1.5 TB af gögnum einhvers staðar, og einnig veita venjulegum notendum möguleika á að hlaða þeim niður með beinum hlekk. Þar sem slíkt minni fer venjulega til VDS, leigukostnaður sem er ekki mjög innifalinn í verkefnisáætluninni úr flokknum „ekkert að gera“ og frá upprunagögnunum var ég með VPS 400GB SSD, þar sem, jafnvel þótt ég vildi, ég gæti ekki sett 1.5TB af myndum án tapslausrar þjöppunar það mun takast.

Og svo mundi ég eftir því að ef ég eyði drasli af Google Drive, eins og forritum sem keyra bara á Windows XP, og annað sem hefur verið að færast úr einu tæki í annað síðan þá daga þegar internetið var alls ekki svo hratt ekki ótakmarkað ( til dæmis var ólíklegt að þessar 10-20 útgáfur af sýndarboxinu hefðu annað gildi en nostalgíu), þá ætti allt að passa mjög vel. Ekki fyrr sagt en gert. Og svo, með því að brjóta í gegnum takmörk á fjölda beiðna í forritaskilin (við the vegur, tækniaðstoð jók án nokkurra vandræða kvóta beiðna á hvern notanda í 100 á 10 sekúndum), gögnin streymdu fljótt á staðinn fyrir frekari dreifingu þeirra .

Allt virðist vera gott en nú þarf að koma því á framfæri við endanotandann. Þar að auki, án þess að beina til annarra auðlinda, heldur þannig að einstaklingur ýtir einfaldlega á „Hlaða niður“ hnappinn og verður hamingjusamur eigandi dýrmætu skráarinnar.

Hér, í guðanna bænum, fór ég í alls kyns vandræði. Í fyrstu var þetta handrit í AmPHP, en ég var ekki sáttur við álagið sem það skapaði (mikið stökk í byrjun í 100% kjarnanotkun). Svo kom krulluhjúpurinn fyrir ReactPHP til sögunnar, sem passaði alveg að óskum mínum hvað varðar fjölda örgjörva sem neytt var, en gaf hraðanum alls ekki það sem ég vildi (kom í ljós að þú getur einfaldlega minnkað hringingarbilið curl_multi_select, en þá erum við með oflæti svipað og í fyrsta valmöguleikanum ). Ég reyndi meira að segja að skrifa litla þjónustu í Rust, og það virkaði nokkuð fljótt (það kemur á óvart að það virkaði, miðað við þekkingu mína), en ég vildi meira og það var einhvern veginn erfitt að sérsníða hana. Þar að auki stöðvuðu allar þessar lausnir svarið á einhvern undarlegan hátt og ég vildi fylgjast með augnablikinu þegar niðurhali skráa endaði með mestri nákvæmni.

Almennt séð var það skakkt um tíma, en það tókst. Þangað til einn daginn datt mér í hug hugmynd sem var merkileg í brjálæði sínu: nginx, í orði, getur gert það sem ég vil, unnið hratt og jafnvel leyft alls kyns rangfærslur með stillingum. Við verðum að reyna - hvað ef það virkar? Og eftir hálfan dag af þrálátri leit fæddist lausn sem hafði virkað stöðugt í nokkra mánuði og uppfyllti allar mínar kröfur.

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

Stutta útgáfu án athugasemda má sjá undir spoilernum

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

Við erum að skrifa handrit til að stjórna allri þessari hamingju

Dæmið verður í PHP og vísvitandi skrifað með að minnsta kosti setti. Ég held að allir sem hafa reynslu af einhverju öðru tungumáli geti samþætt þennan hluta með því að nota dæmið mitt.

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

Niðurstöður

Almennt séð gerir þessi aðferð það nokkuð auðvelt að skipuleggja dreifingu skráa til notenda úr hvaða skýjageymslu sem er. Já, jafnvel frá símskeyti eða VK, (að því gefnu að skráarstærðin fari ekki yfir leyfilega stærð þessarar geymslu). Ég fékk svipaða hugmynd og þetta, en því miður rekst ég á skrár allt að 2GB, og ég hef ekki enn fundið aðferð eða einingu til að líma svör frá andstreymis, og að skrifa einhvers konar umbúðir fyrir þetta verkefni er óeðlilega vinnufrekt.

Takk fyrir athyglina. Ég vona að sagan mín hafi verið að minnsta kosti svolítið áhugaverð eða gagnleg fyrir þig.

Heimild: www.habr.com

Bæta við athugasemd