如何根据 HTTP 操作和 URL 前缀路由到 content_by_lua nginx 指令?

How to route to content_by_lua nginx directive depending on both HTTP Action and URL prefix?

我想默认将发送到我的 nginx 服务器的所有请求路由到我的后端应用程序,但有选择地发送 API 带有 GET HTTP 动词的请求到基于 OpenResty Lua 的 REST API 由 content_by_lua nginx 指令支持。

我使用以下配置成功地将所有 API 请求路由到 Lua API 基于它们的 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 位置。

根据其他一些帖子、博客和文档(并听说 the if directive is frowned upon),我尝试使用 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

在委派给 content_by_lua 指令时,基于 URL 前缀 HTTP 动词在 nginx 中选择性路由的最佳方法是什么?

我通过使用 if 指令实现了特定 URL GET 操作的条件路由,尽管根据 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")';
    }
  }

}