توزیع فایل ها از Google Drive با استفاده از nginx

ماقبل تاریخ

اتفاقاً مجبور شدم بیش از 1.5 ترابایت داده را در جایی ذخیره کنم و همچنین امکان دانلود آن را از طریق لینک مستقیم برای کاربران عادی فراهم کنم. از آنجایی که به طور سنتی چنین مقادیری از حافظه به VDS می رود، هزینه اجاره که در بودجه پروژه از رده "هیچ کاری انجام نمی شود" بسیار گنجانده شده است، و از داده های منبع یک SSD VPS 400 گیگابایتی داشتم، حتی اگر من می خواستم، نمی توانم 1.5 ترابایت تصاویر را بدون فشرده سازی بدون اتلاف قرار دهم، موفق خواهد شد.

و بعد به یاد آوردم که اگر ناخواسته را از Google Drive حذف کنم، مانند برنامه هایی که فقط روی ویندوز XP اجرا می شوند، و چیزهای دیگری که از یک دستگاه به دستگاه دیگر منتقل شده اند از روزهایی که اینترنت اصلاً سریع نبود و نامحدود نیست ( به عنوان مثال، آن 10-20 نسخه از جعبه مجازی بعید بود ارزشی غیر از نوستالژیک داشته باشند)، پس همه چیز باید خیلی خوب باشد. زودتر گفته شود. و بنابراین، با شکستن محدودیت تعداد درخواست‌ها به api (به هر حال، پشتیبانی فنی بدون هیچ مشکلی سهمیه درخواست‌های هر کاربر را به 100 در 10 ثانیه افزایش داد)، داده‌ها به سرعت به محل استقرار بعدی آن سرازیر شدند. .

به نظر همه چیز خوب است، اما اکنون باید به کاربر نهایی منتقل شود. علاوه بر این، بدون هیچ تغییر مسیری به منابع دیگر، اما به این ترتیب که شخص به سادگی دکمه "دانلود" را فشار داده و صاحب خوشحال فایل ارزشمند می شود.

اینجا به خدا به همه گرفتاری ها رسیدم. در ابتدا این یک اسکریپت در AmPHP بود، اما من از بار ایجاد شده راضی نبودم (پرش شدید در شروع به مصرف 100٪ اصلی). سپس پیچ پیچ برای ReactPHP وارد بازی شد که از نظر تعداد سیکل های مصرفی CPU کاملاً با خواسته های من مطابقت داشت ، اما به هیچ وجه سرعت مورد نظر من را ارائه نکرد (معلوم شد که می توانید به سادگی فاصله تماس را کاهش دهید. curl_multi_select، اما پس از آن ما یک glutony مشابه گزینه اول داریم). من حتی سعی کردم یک سرویس کوچک در Rust بنویسم، و خیلی سریع کار کرد (با توجه به دانش من، جای تعجب است که کار می کرد)، اما بیشتر می خواستم، و سفارشی کردن آن به نوعی دشوار بود. علاوه بر این، همه این راه حل ها به نحوی عجیب پاسخ را بافر می کردند و من می خواستم لحظه پایان یافتن فایل را با بیشترین دقت پیگیری کنم.

کلا یه مدت کج بود ولی کار کرد. تا اینکه یک روز به ایده‌ای رسیدم که در دیوانگی‌اش قابل توجه بود: nginx، در تئوری، می‌تواند کاری را که من می‌خواهم انجام دهد، به سرعت کار کند و حتی انواع انحرافات را با پیکربندی اجازه دهد. ما باید تلاش کنیم - اگر کار کرد چه؟ و پس از نیم روز جستجوی مداوم، راه حلی متولد شد که چندین ماه به طور پایدار کار می کرد و تمام نیازهای من را برآورده می کرد.

راه اندازی 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;
}

نسخه کوتاه بدون نظر در زیر اسپویلر قابل مشاهده است

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

ما در حال نوشتن فیلمنامه ای برای مدیریت این همه شادی هستیم

مثال به زبان PHP خواهد بود و عمداً با حداقل کیت نوشته می شود. من فکر می کنم هر کسی که با هر زبان دیگری تجربه دارد می تواند با استفاده از مثال من این بخش را ادغام کند.

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

نمایش نتایج: از

به طور کلی، این روش سازماندهی توزیع فایل ها به کاربران را از هر فضای ذخیره سازی ابری بسیار آسان می کند. بله، حتی از تلگرام یا VK، (به شرطی که حجم فایل از اندازه مجاز این ذخیره سازی بیشتر نباشد). من یک ایده مشابه داشتم این، اما متاسفانه با فایل های تا 2 گیگابایت مواجه شدم و هنوز روش یا ماژولی برای چسباندن پاسخ ها از بالادست پیدا نکردم و نوشتن نوعی لفاف برای این پروژه بی دلیل زحمت زیادی دارد.

با تشکر از توجه شما. امیدوارم داستان من حداقل برای شما جالب یا مفید بوده باشد.

منبع: www.habr.com

اضافه کردن نظر