Sparte i schedari da Google Drive cù nginx

Pristoria

Hè accadutu cusì chì avia bisognu di almacenà più di 1.5 TB di dati in qualchì locu, è ancu furnisce l'abilità per l'utilizatori ordinariu di scaricà via un ligame direttu. Siccomu tradiziunale tali quantità di memoria vanu à VDS, u costu di l'affittu chì ùn hè micca assai inclusu in u budgetu di u prugettu da a categuria "nunda di fà", è da a fonte di dati aghju avutu un VPS 400GB SSD, induve, ancu s'ellu aghju. vulia, ùn pudia micca mette 1.5TB d'imaghjini senza cumpressione senza perdita di successu.

E poi mi ricurdava chì s'ellu sguassate i junk da Google Drive, cum'è i prugrammi chì funzionanu solu in Windows XP, è altre cose chì si movenu da un dispositivu à l'altru dapoi i tempi quandu l'Internet ùn era micca cusì veloce in tuttu micca illimitatu ( per esempiu, quelli versioni 10-20 di a scatula virtuale eranu improbabile di avè qualchì valore altru ch'è nostalgicu), allora tuttu deve esse assai bè. Nantu à dì chè fattu. È cusì, sfondendu u limitu di u nùmeru di dumande à l'api (per via, u supportu tecnicu senza alcunu prublema hà aumentatu a quota di richieste per utilizatore à 100 10 in 000 seconde), i dati scorri rapidamente à u locu di a so implementazione ulteriore. .

Tuttu pare esse bè, ma avà deve esse trasmessu à l'utilizatori finali. Inoltre, senza alcunu redirects à altre risorse, ma cusì chì una persona simpricimenti pressu u buttone "Download" è diventa u felice pruprietariu di u schedariu tesoru.

Quì, per Diu, sò andatu in ogni tipu di prublemi. À u principiu era un script in AmPHP, ma ùn era micca cuntentu di a carica chì hà creatu (un saltu forte à u principiu à u cunsumu core 100%). Allora u curl wrapper per ReactPHP hè ghjuntu in ghjocu, chì si adatta bè à i mo desideri in quantu à u nùmeru di ciculi CPU cunsumati, ma ùn hà micca datu a rapidità à tuttu ciò chì vulia (hè risultatu chì pudete solu riduce l'intervallu di chjamà). curl_multi_select, ma allora avemu una gola simile à a prima opzione). Aghju ancu pruvatu à scrive un picculu serviziu in Rust, è hà travagliatu abbastanza rapidamente (hè surprisante chì hà travagliatu, datu a mo cunniscenza), ma vulia più, è era qualchì manera difficiuli di persunalizà. Inoltre, tutte queste suluzioni in qualchì manera stranamente buffered a risposta, è aghju vulsutu seguità u mumentu quandu u scaricamentu di u schedariu hè finitu cù a più grande precisione.

In generale, era crooked per un tempu, ma hà travagliatu. Finu à un ghjornu aghju avutu una idea chì era notevule in a so pazzia: nginx, in teoria, pò fà ciò chì vogliu, travaglià rapidamente, è ancu permette ogni tipu di perversione cù cunfigurazione. Avemu da pruvà - è s'ellu funziona? È dopu à una meza ghjurnata di ricerca persistente, hè nata una suluzione chì hà travagliatu stabile per parechji mesi è hà sappiutu tutte e mo esigenze.

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

Una versione corta senza cumenti pò esse vistu sottu u 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;
}

Scrivemu un script per gestisce tutta sta felicità

L'esempiu serà in PHP è deliberatamente scrittu cù un minimu di kit. Pensu chì qualchissia chì hà sperienza cù qualsiasi altra lingua puderà integrà sta sezione cù u mo esempiu.

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

Risultati

In generale, stu metudu rende abbastanza faciule d'urganizà a distribuzione di i schedari à l'utilizatori da ogni almacenamentu in nuvola. Iè, ancu da telegramma o VK, (sempre chì a dimensione di u schedariu ùn supere micca a dimensione permessa di stu almacenamentu). Aghju avutu una idea simile à questu, ma sfurtunatamenti aghju trovu schedarii finu à 2GB, è ùn aghju micca ancu trovu un metudu o un modulu per l'incollatura di risposti da upstream, è scrive qualchì tipu di wrappers per stu prughjettu hè un ragiunamentu intensivu di travagliu.

Grazie per a vostra attenzione. Spergu chì a mo storia hè stata almenu un pocu interessante o utile per voi.

Source: www.habr.com

Add a comment