Deel lêers vanaf Google Drive met nginx

voorgeskiedenis

Dit het net so gebeur dat ek meer as 1.5 TB se data iewers moes stoor, en ook die vermoë bied vir gewone gebruikers om dit via 'n direkte skakel af te laai. Aangesien tradisioneel sulke hoeveelhede geheue na VDS gaan, is die huurkoste wat nie baie ingesluit is in die projekbegroting van die "niks om te doen" nie, en uit die brondata, 'n VPS 400GB SSD gehad, waar, selfs as ek wou, kon ek nie 1.5TB beelde sit sonder verlieslose kompressie nie, dit sal slaag.

En toe onthou ek dat as ek rommel uit Google Drive uitvee, soos programme wat net op Windows XP sal loop, en ander dinge wat van een toestel na 'n ander beweeg sedert die dae toe die internet glad nie so vinnig was nie, nie onbeperk nie ( dit was byvoorbeeld onwaarskynlik dat daardie 10-20 weergawes van die virtuele boks enige waarde anders as nostalgies sou hê), dan behoort alles baie goed te pas. Nie gou gesê as gedaan nie. En so, deur die limiet op die aantal versoeke na die API te breek (terloops, tegniese ondersteuning het sonder enige probleme die kwota versoeke per gebruiker tot 100 10 in 000 sekondes verhoog), het die data vinnig gevloei na die plek van sy verdere ontplooiing .

Alles blyk goed te wees, maar nou moet dit aan die eindgebruiker oorgedra word. Boonop sonder enige herleidings na ander hulpbronne, maar sodat 'n persoon eenvoudig die "Download"-knoppie druk en die gelukkige eienaar van die kosbare lêer word.

Hier, by God, het ek in allerhande moeilikhede beland. Aanvanklik was dit 'n skrif in AmPHP, maar ek was nie tevrede met die las wat dit geskep het nie ('n skerp sprong aan die begin tot 100% kernverbruik). Toe kom die krulomhulsel vir ReactPHP in werking, wat goed inpas by my wense in terme van die aantal SVE-siklusse wat verbruik is, maar glad nie die spoed gegee het wat ek wou hê nie (dit het geblyk dat jy eenvoudig die interval van oproepe kan verminder curl_multi_select, maar dan het ons 'n vraatsug soortgelyk aan die eerste opsie ). Ek het selfs probeer om 'n klein diens in Rust te skryf, en dit het redelik vinnig gewerk (dit is verbasend dat dit gewerk het, gegewe my kennis), maar ek wou meer hê, en dit was op een of ander manier moeilik om dit aan te pas. Boonop het al hierdie oplossings die reaksie op een of ander manier vreemd gebuffer, en ek wou die oomblik opspoor wanneer die lêeraflaai met die grootste akkuraatheid geëindig het.

Oor die algemeen was dit 'n rukkie skeef, maar dit het gewerk. Totdat ek eendag met 'n idee vorendag gekom het wat merkwaardig in sy gekheid was: nginx, in teorie, kan doen wat ek wil, vinnig werk, en selfs allerhande perversies met konfigurasie toelaat. Ons moet probeer - wat as dit werk? En na 'n halwe dag van aanhoudende soektog, is 'n oplossing gebore wat al vir 'n paar maande stabiel werk en aan al my vereistes voldoen het.

Die opstel van 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;
}

’n Kort weergawe sonder kommentaar kan onder die bederf gesien word

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

Ons skryf 'n draaiboek om al hierdie geluk te bestuur

Die voorbeeld sal in PHP wees en doelbewus geskryf met 'n minimum kit. Ek dink enigiemand wat ondervinding het met enige ander taal sal hierdie afdeling kan integreer deur my voorbeeld te gebruik.

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

Resultate van

Oor die algemeen maak hierdie metode dit redelik maklik om die verspreiding van lêers na gebruikers vanaf enige wolkberging te organiseer. Ja, selfs vanaf telegram of VK, (mits die lêergrootte nie die toelaatbare grootte van hierdie berging oorskry nie). Ek het 'n idee soortgelyk aan hierdie, maar ongelukkig kom ek op lêers tot 2GB teë, en ek het nog nie 'n metode of module gevind om antwoorde van stroomop te plak nie, en die skryf van 'n soort omhulsels vir hierdie projek is onredelik arbeidsintensief.

Dankie vir jou aandag. Ek hoop my storie was ten minste 'n bietjie interessant of nuttig vir jou.

Bron: will.com

Voeg 'n opmerking