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

时间:2017-05-10 18:42:26

标签: nginx lua openresty lapis

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

我已成功地使用以下配置根据URL前缀将所有API请求路由到Lua API(请注意,这不会考虑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请求,以便除了GET之外的任何HTTP动词请求(如POST,PUT,DELETE等)仍然路由到后端,而GET请求单独路由到Lua API位置。

基于其他一些帖子,博客和文档(以及听到the if directive is frowned upon),我尝试使用limit_except指令,但是nginx服务器在启动时崩溃,因为它似乎是{{1 }}指令不是为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 指令时,根据URL前缀 HTTP动词有选择地在nginx中路由的最佳方法是什么?

1 个答案:

答案 0 :(得分:2)

我使用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")';
    }
  }

}
相关问题