HAproxy+Lua: Return requests if validation fails from Lua script
我们正在尝试使用HAProxy Lua构建传入请求验证平台。
我们的用例是创建一个LUA脚本,该脚本本质上将根据验证结果对Validation API进行套接字调用
从验证API,我们希望将请求重定向到后端API,如果验证失败,我们希望返回
直接来自LUA脚本的请求。例如,对于200响应,我们希望将请求重定向到后端api,对于404,我们希望
返回请求。从文档中,我了解到有许多可用的默认功能
与Lua-Haproxy集成。
1 2 3 4 5 6 | core.register_action() --> I'm using this. Take TXN as input core.register_converters() --> Essentially used for string manipulations. core.register_fetches() --> Takes TXN as input and returns string; Mainly used for representing dynamic backend profiles in haproxy config core.register_init() --> Used for initialization core.register_service() --> You have to return the response mandatorily while using this function, which doesn't satisfy our requirements core.register_task() --> For using normal functions. No mandatory input class. TXN is required to fetch header details from request |
我已经尝试了上面列表中的所有功能,我知道core.register_service基本上是从
Lua脚本。但是,有问题的是,我们必须从LUA脚本发送响应,并且它不会将请求重定向到BACKEND。
当前,我正在使用core.register_action中断请求,但是无法使用此函数返回请求。这是
我的代码如下所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | local http_socket = require("socket.http") local pretty_print = require("pl.pretty") function add_http_request_header(txn, name, value) local headerName = name local headerValue = value txn.http:req_add_header(headerName, headerValue) end function call_validation_api() local request, code, header = http_socket.request { method ="GET", -- Validation API Method url ="http://www.google.com/" -- Validation API URL } -- Using core.log; Print in some cases is a blocking operation http://www.arpalert.org/haproxy-lua.html#h203 core.Info("Validation API Response Code:" .. code ) pretty_print.dump( header ) return code end function failure_response(txn) local response ="Validation Failed" core.Info(response) txn.res:send(response) -- txn:close() end core.register_action("validation_action", {"http-req","http-res" }, function(txn) local validation_api_code = call_validation_api() if validation_api_code == 200 then core.Info("Validation Successful") add_http_request_header(txn,"test-header","abcdefg") pretty_print.dump( txn.http:req_get_headers() ) else failure_response(txn) --->>> **HERE I WANT TO RETURN THE RESPONSE** end end) |
以下是配置文件条目:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | frontend http-in bind :8000 mode http http-request lua.validation_action #Capturing header of the incoming request capture request header test-header len 64 #use_backend %[lua.fetch_req_params] default_backend app backend app balance roundrobin server app1 127.0.0.1:9999 check |
在实现此功能方面,任何帮助都将受到赞赏。另外,我知道从Lua脚本进行的SOCKET调用是阻塞调用,这与HAProxy的keep-alive连接的默认性质相反。如果您已经使用过,请随时提出其他实用程序来实现此功能。
好吧,我已经找到了这个问题的答案:
我创建了2个用于成功和失败请求的后端,并根据响应返回了2个不同的字符串。在" failure_backend"中,我调用了另一个服务,该服务本质上是core.register_service,可以返回响应。我正在粘贴配置文件和lua脚本的代码
HAProxy conf文件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 | #--------------------------------------------------------------------- # Global settings #--------------------------------------------------------------------- global # to have these messages end up in /var/log/haproxy.log you will # need to: # # 1) configure syslog to accept network log events. This is done # by adding the '-r' option to the SYSLOGD_OPTIONS in # /etc/sysconfig/syslog # # 2) configure local2 events to go to the /var/log/haproxy.log # file. A line like the following can be added to # /etc/sysconfig/syslog # # local2.* /var/log/haproxy.log # log 127.0.0.1 local2 maxconn 4000 user haproxy group haproxy daemon #lua file load lua-load /home/aman/coding/haproxy/http_header.lua # turn on stats unix socket stats socket /var/lib/haproxy/stats #--------------------------------------------------------------------- # common defaults that all the 'listen' and 'backend' sections will # use if not designated in their block #--------------------------------------------------------------------- defaults mode http log global option httplog option dontlognull retries 3 timeout http-request 90s timeout queue 1m timeout connect 10s timeout client 1m timeout server 1m timeout http-keep-alive 10s timeout check 10s maxconn 3000 #--------------------------------------------------------------------- # main frontend which proxys to the backends #--------------------------------------------------------------------- frontend http-in bind :8000 mode http use_backend %[lua.validation_fetch] default_backend failure_backend #--------------------------------------------------------------------- # round robin balancing between the various backends #--------------------------------------------------------------------- backend success_backend balance roundrobin server app1 172.23.12.94:9999 check backend failure_backend http-request use-service lua.failure_service # For displaying HAProxy statistics. frontend stats bind :8888 default_backend stats backend stats stats enable stats hide-version stats realm Haproxy Statistics stats uri /haproxy/stats stats auth aman:rjil@123 |
Lua脚本:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | local http_socket = require("socket.http") local pretty_print = require("pl.pretty") function add_http_request_header(txn, name, value) local headerName = name local headerValue = value txn.http:req_add_header(headerName, headerValue) end function call_validation_api() local request, code, header = http_socket.request { method ="GET", -- Validation API Method url ="http://www.google.com/" -- Validation API URL } -- Using core.log; Print in some cases is a blocking operation http://www.arpalert.org/haproxy-lua.html#h203 core.Info("Validation API Response Code:" .. code ) pretty_print.dump( header ) return code end function failure_response(txn) local response ="Validation Failed" core.Info(response) return"failure_backend" end -- Decides back-end based on Success and Failure received from validation API core.register_fetches("validation_fetch", function(txn) local validation_api_code = call_validation_api() if validation_api_code == 200 then core.Info("Validation Successful") add_http_request_header(txn,"test_header","abcdefg") pretty_print.dump( txn.http:req_get_headers() ) return"success_backend" else failure_response(txn) end end) -- Failure service core.register_service("failure_service","http", function(applet) local response ="Validation Failed" core.Info(response) applet:set_status(400) applet:add_header("content-length", string.len(response)) applet:add_header("content-type","text/plain") applet:start_response() applet:send(response) end) |