Google Drive-tik fitxategiak banatzea nginx erabiliz

historiaurrea

Gertatu zen 1.5 TB baino gehiago datu nonbait gorde behar nituela, eta erabiltzaile arruntei zuzeneko esteka baten bidez deskargatzeko aukera ere eskaintzea. Tradizionalki memoria kopuru hori VDSra doazenez, proiektuaren aurrekontuan oso sartzen ez den alokairuaren kostua "ezer egin behar" kategoriatik, eta iturriko datuetatik VPS 400GB SSD bat nuen, non, nahiz eta nahi izan, ezin nituen 1.5TB irudi jarri galerarik gabeko konpresiorik gabe, arrakasta izango du.

Eta orduan gogoratu nintzen Google Drive-tik zaborra ezabatzen badut, Windows XP-n bakarrik exekutatzen diren programak eta beste gauza batzuk gailu batetik bestera mugitzen joan diren garaietatik Internet batere azkarra ez zen garaietatik ez mugagabea ( adibidez, kutxa birtualaren 10-20 bertsio haiek nekez izango zuten nostalgikoa ez den baliorik), orduan dena oso ondo moldatu behar zen. Esan baino lehenago egin. Beraz, APIrako eskaera-kopuruaren muga gaindituz (bide batez, laguntza teknikoak arazorik gabe erabiltzaile bakoitzeko eskaeren kuota 100ra igo zuen 10 segundotan), datuak azkar hedatu ziren tokira. .

Dena ondo dagoela dirudi, baina orain azken erabiltzaileari helarazi behar zaio. Gainera, beste baliabide batzuetara birbideratu gabe, baina pertsona batek "Deskargatu" botoia besterik gabe sakatu eta altxortutako fitxategiaren jabe zoriontsu bilakatzen da.

Hemen, Jainkoak, era guztietako arazoetan sartu nintzen. Hasieran AmPHP-ko script bat zen, baina ez nengoen konforme sortutako kargarekin (hasieran jauzi nabarmena %100eko core kontsumora). Ondoren, ReactPHP-ren kizkur-bilgarria sartu zen, nire nahietara nahiko bat zena kontsumitutako CPU ziklo kopuruari dagokionez, baina ez zuen batere abiadura eman nahi nuena (deien tartea murriztea besterik ez zen atera zen). curl_multi_select, baina gero lehen aukeraren antzeko glutey bat dugu). Rust-en zerbitzu txiki bat idazten ere saiatu nintzen, eta nahiko azkar funtzionatu zuen (harrigarria da funtzionatu izana, nire ezagutzak ikusita), baina gehiago nahi nuen, eta nolabait zaila zen pertsonalizatzea. Horrez gain, irtenbide horiek guztiak modu arraroan bufferatu zuten erantzuna, eta fitxategia deskargatzea zehaztasun handienarekin amaitu zen unea jarraitu nahi nuen.

Oro har, okertuta egon zen pixka bat, baina funtzionatu zuen. Egun batean bere zorakerian nabarmena zen ideia bat bururatu zitzaidan arte: nginx-ek, teorian, nahi dudana egin dezake, azkar lan egin dezake eta konfigurazioarekin mota guztietako perbertsioak ere baimendu ditzake. Saiatu behar dugu - eta funtzionatzen badu? Eta egun erdi etengabeko bilaketaren ostean, hainbat hilabetez egonkor funtzionatzen zuen eta nire eskakizun guztiak betetzen zituen irtenbide bat sortu zen.

NGINX konfiguratzen

# Первым делом создадим в конфигах нашего сайта отдельную локацию.
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;
}

Iruzkinik gabeko bertsio labur bat ikus daiteke spoiler azpian

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

Zorion hori guztia kudeatzeko gidoi bat idazten ari gara

Adibidea PHPn egongo da eta nahita idatzita egongo da gutxieneko kit batekin. Uste dut beste edozein hizkuntzarekin esperientzia duen edonork atal hau integratzeko aukera izango duela nire adibidea erabiliz.

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

Emaitzak

Oro har, metodo honek hodeiko edozein biltegiratzetik erabiltzaileen fitxategien banaketa antolatzea errazten du. Bai, telegrametik edo VKtik ere, (baldin eta fitxategiaren tamainak biltegiratze honen baimendutako tamaina gainditzen ez badu). antzeko ideia bat nuen hau, baina, zoritxarrez, 2 GB arteko fitxategiak topatzen ditut, eta oraindik ez dut aurkitu upstream-etik erantzunak itsasteko metodo edo modulurik, eta proiektu honetarako bilgarri moduko bat idaztea nahiko lan handia da.

Eskerrik asko zure arretagatik. Espero dut nire istorioa bederen apur bat interesgarria edo erabilgarria izan izana zuretzat.

Iturria: www.habr.com

Gehitu iruzkin berria