Как перейти к директиве nginx content_by_lua в зависимости от действия HTTP и префикса URL?

Я бы хотел, чтобы все запросы, отправленные на мой сервер nginx, по умолчанию использовались в моем бэкэнд-приложении, но выборочно отправлять запросы API с глаголами GET HTTP в REST API на основе OpenResty Lua, поддерживаемый content_by_lua директива nginx.

Я успешно смог направить все запросы API к API Lua на основе их префикса URL, используя следующую конфигурацию (обратите внимание, что это не учитывает HTTP-глагол):

http {
  upstream backend {
    server localhost:8080;
  }
  server {
    listen 80;

    location / {
      # Send all requests to the backend application
      proxy_pass http://backend;
      proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;
      proxy_set_header   Host             $http_host;
      proxy_set_header   X-Real-IP        $remote_addr;
      proxy_set_header   CLIENT_IP $remote_addr;
      proxy_set_header   HTTP_CLIENT_IP $remote_addr;
      proxy_redirect off;
    }

    location /api {
      # Send any URL with the /api prefix to the nginx Lua API application
      content_by_lua '
        require("lapis").serve("app")
      ';
    }
  }
}

Но, как я уже говорил выше, я бы хотел еще больше ограничить запросы API, чтобы любые запросы с HTTP-глаголами, отличными от GET (например, POST, PUT, DELETE и т. Д.), По-прежнему направлялись на серверную часть, а только запросы GET маршрутизировались. в местоположение Lua API.

На основании некоторых других постов, блогов и документации (и слышать, что if директива не одобряется), я пытался с помощью limit_except директивы, но затем сервер nginx завис при запуске, как кажется, content_by_lua Директива не была предназначена для limit_except блоки. Здесь была моя попытка:

http {
  upstream backend {
    server localhost:8080;
  }
  server {
    listen 80;

    location / {
      proxy_pass http://backend;
      proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;
      proxy_set_header   Host             $http_host;
      proxy_set_header   X-Real-IP        $remote_addr;
      proxy_set_header   CLIENT_IP $remote_addr;
      proxy_set_header   HTTP_CLIENT_IP $remote_addr;
      proxy_redirect off;
    }

    location /api {
      # Default the non-get API requests back to the backend server
      proxy_pass http://backend;
      proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;
      proxy_set_header   Host             $http_host;
      proxy_set_header   X-Real-IP        $remote_addr;
      proxy_set_header   CLIENT_IP $remote_addr;
      proxy_set_header   HTTP_CLIENT_IP $remote_addr;
      proxy_redirect off;

      # Select requests that *aren't* a PUT, POST, or DELETE, and pass those to the Lapis REST API
      limit_except PUT POST DELETE {
        content_by_lua '
          require("lapis").serve("app")
        ';
      }
    }
  }
}

который быстро разбился с

nginx: [emerg] "content_by_lua" directive is not allowed here in nginx.conf:46

Каков наилучший способ выборочной маршрутизации в nginx на основе префикса URL-адреса и глагола HTTP при делегировании content_by_lua Директива?

1 ответ

Решение

Я реализовал условную маршрутизацию определенных действий URL GET, используя if директива, даже если это зло в соответствии с разработчиками nginx. Похоже, что это может быть одним из немногих желательных вариантов использования для if директива, но если это не так или у кого-то есть лучший подход, пожалуйста, дайте мне знать (вот почему я не принял мой собственный ответ).

Вот файл конфигурации nginx, который в настоящее время реализует решение:

http {

  upstream backend {
    server localhost:3000;
  }

  server {
    listen 80;
    proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;
    proxy_set_header   Host             $http_host;
    proxy_set_header   X-Real-IP        $remote_addr;
    proxy_set_header   CLIENT_IP $remote_addr;
    proxy_set_header   HTTP_CLIENT_IP $remote_addr;
    proxy_redirect off;

    # By default pass all the requests to the Rails app backend
    location / {
      proxy_pass http://backend;
    }

    # Delegate certain API calls to our special OpenResty Endpoints
    location /api {
      # Makes sure all POSTs, PUTs, and DELETE actions still get handed off to the backend
      if ($request_method ~ POST|PUT|DELETE) {
        proxy_pass http://backend;
      }
      # All that should remain are the GET and OPTIONS endpoints so send them to the OpenResty Lua backend!)
      content_by_lua 'require("lapis").serve("app")';
    }
  }

}
Другие вопросы по тегам