Подтвердить что ты не робот

Прокси Nginx для файлов на локальном диске или S3

Итак, я перемещаю свой сайт из Apache и на Nginx, и у меня возникают проблемы с этим сценарием:

Пользователь загружает фотографию. Эта фотография изменяется, а затем копируется на S3. Если на диске есть подходящая комната (или файл не может быть передан на S3), локальная версия сохраняется.

Мне нужны запросы для этих изображений (например, http://www.mysite.com/p/1_1.jpg), чтобы сначала посмотреть в каталоге p/. Если локальный файл не существует, я хочу проксировать запрос на S3 и отображать изображение (но не перенаправлять).

В Apache я сделал это так:

RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^p/([0-9]+_[0-9]+\.jpg)$ http://my_bucket.s3.amazonaws.com/$1 [P,L]

Моя попытка реплицировать это поведение в Nginx такова:

location /p/ {
    if (-e $request_filename) {
        break;
    }
    proxy_pass http://my_bucket.s3.amazonaws.com/;
}

Что происходит, так это то, что каждый запрос пытается поразить Amazon S3, даже если файл существует на диске (и если он не существует на Amazon, я получаю ошибки.) Если я удалю строку proxy_pass, тогда запросы на файлы на диск DO работать.

Любые идеи о том, как исправить это?

4b9b3361

Ответ 1

Разве это не может быть пример использования try_files?

location /p/ {
    try_files $uri @s3;
}

location @s3{ 
    proxy_pass http://my_bucket.s3.amazonaws.com;
}

Убедитесь, что на URL-адресе S3 нет ссылки на

Ответ 2

Вы можете улучшить конфигурацию прокси-сервера s3, как это. Адаптировано из fooobar.com/questions/423997/...:

location /p/ {
    try_files $uri @s3;
}

location @s3 {
  set $s3_bucket        'your_bucket.s3.amazonaws.com';
  set $url_full         '$1';

  proxy_http_version     1.1;
  proxy_set_header       Host $s3_bucket;
  proxy_set_header       Authorization '';
  proxy_hide_header      x-amz-id-2;
  proxy_hide_header      x-amz-request-id;
  proxy_hide_header      x-amz-meta-server-side-encryption;
  proxy_hide_header      x-amz-server-side-encryption;
  proxy_hide_header      Set-Cookie;
  proxy_ignore_headers   Set-Cookie;
  proxy_intercept_errors on;

  resolver               8.8.4.4 8.8.8.8 valid=300s;
  resolver_timeout       10s;
  proxy_pass             http://$s3_bucket$url_full;
}

Ответ 3

Я решил это решить, проверив, не существует ли файл, и если да, переписывая этот запрос. Затем я обрабатываю повторно написанный запрос и делаю proxy_pass там, например:

location /p/ {
  if (!-f $request_filename) {
    rewrite ^/p/(.*)$ /ps3/$1 last;
    break;
  }
}

location /ps3/ {
  proxy_pass http://my_bucket.s3.amazonaws.com/;
}

Ответ 4

Спасибо за мой пост coderwall:) Для целей кэширования вы можете немного улучшить его:

http {

  proxy_cache_path          /tmp/cache levels=1:2 keys_zone=S3_CACHE:10m inactive=24h max_size=500m;
  proxy_temp_path           /tmp/cache/temp;

  server {
    location ~* ^/cache/(.*) {
      proxy_buffering        on;
      proxy_hide_header      Set-Cookie;
      proxy_ignore_headers   Set-Cookie;
      ...
      proxy_cache            S3_CACHE;
      proxy_cache_valid      24h;
      proxy_pass             http://$s3_bucket/$url_full;
    }
  }

}

Еще одна рекомендация заключается в расширении кэша резольвера до 5 минут:

resolver                  8.8.4.4 8.8.8.8 valid=300s;
resolver_timeout          10s;

Ответ 5

break не делает то, что вы ожидаете, что nginx сделает последнее, о чем вы просите об этом, что имеет смысл, если вы начнете копать вокруг создания модулей... но в основном защитите свой прокси-пароль с помощью do-not-exist версия

if (-f $request_filename) {
    break;
}
if(!-f $request_filename)
    proxy_pass  http://s3;
}