HAproxy Lua:如果Lua脚本验证失败,则返回请求

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)