nginx/Passenger: обслуживание кэшированного файла только в том случае, если параметр отсутствует в запросе

nginx/Passenger: обслуживание кэшированного файла только в том случае, если параметр отсутствует в запросе

Для заданного шаблона URL ( /scripts/.*\.meta\.js) я хотел бы иметь следующее поведение:

  • Если URL-адрес содержит определенный параметр ( version), передайте запрос на обработку Passenger.
  • Если URL-адрес не содержит этого конкретного параметра и существует кэшированный файл, предоставьте его.
  • Если URL-адрес не содержит этого конкретного параметра и кэшированный файл не существует, передайте запрос на обработку Passenger.

Я делаю это для повышения производительности, избегая необходимости обработки большинства запросов по этому пути Passenger и приложению Rails.

Мой файл конфигурации nginx выглядит так:

server {

  listen 80;
  server_name my.site;

  root /path/to/rails/public;
  passenger_enabled on;
  rails_env development;
  passenger_min_instances 1;

  client_max_body_size 5m;

  location ~* /scripts/.*\.meta\.js {

    error_page 418 = @noparams;

    if ( $arg_version = '' ) {
      return 418;
    }
  }

  location @passenger {
    root /path/to/rails/public;
    proxy_set_header X-Forwarded-Proto http;
    passenger_enabled on;
  }

  location @noparams {
    try_files  /a$uri @passenger =401;
  }

}

Я поместил тестовые файлы в /path/to/rails/public/a. Это дает следующее поведение:

  • ✓ Если URL-адрес содержит определенный параметр ( version), передайте запрос на обработку Passenger.
  • ✓ Если URL-адрес не содержит этого конкретного параметра и существует кэшированный файл, предоставьте его.
  • ❌ Если URL-адрес не содержит этот конкретный параметр и кэшированный файл не существует, передайте запрос на обработку Passenger.Фактическое поведение: HTTP 401.

Похоже, у меня неправильный способ ссылаться на Passenger в try_files. Что мне нужно сделать, чтобы это заработало?

решение1

У меня было впечатление, что try_filesэто список "вещей", которые можно попробовать, и вы можете поместить именованное местоположение в любую позицию. Как отмечает Майкл Хэмптон в комментарии, это неверно. Именованные местоположения и коды HTTP могут быть только на последней позиции в try_files; все, что не на последней позиции, должно быть путем к файлу. Так что try_files /a$uri @passengerработает так, как я и задумал.

Также нет необходимости повторять конфигурацию внутри, @passengerтак как она наследуется от serverблока. Итак, рабочая конфигурация:

server {

  listen 80;
  server_name my.site;

  root /path/to/rails/public;
  passenger_enabled on;
  rails_env development;
  passenger_min_instances 1;

  client_max_body_size 5m;

  location ~* /scripts/.*\.meta\.js {

    error_page 418 = @noparams;

    if ( $arg_version = '' ) {
      return 418;
    }
  }

  location @passenger { }

  location @noparams {
    try_files  /a$uri @passenger;
  }

}

Связанный контент