'Transform request data in Krakrnd with lua

Using Krakend as api gateway.

I have an endpoint configured in krakend.json:

"endpoint":"/call",
"extra_config":{
   "github.com/devopsfaith/krakend-lua/proxy":{
      "sources":[
         "/function.lua"
      ],
      "pre":"pre_backend(request.load())",
      "live":true,
      "allow_open_libs":true
   }
},
"method":"POST",
"output_encoding":"json",
"headers_to_pass":[
   "*"
],
"backend":[
   {
      "url_pattern":"/api/v1/get_client_id",
    [...]]
},

The endopont "/api/v1/get_client_id" recives just a param:

{"user_mail_1":"[email protected]"}

I want, whith the lua script my endopoint "/call" recives:

{"email":"[email protected]"}

and transform on before send:

{"user_mail_1":"[email protected]"}

I tried with gsub, but use body() as "string" is no efficient.

    function pre_backend( req )
      print('--Backend response, pre-logic:'); 
      local r = req;
      r:params('test','test');
      r:query('lovelyquery')
      r:body('test','test');
      lolcal v = r:body():gsub('email', 'user_mail_1')
...

Is a way to parse "req" as a table, dict or something i can transform data?

Is another way to transform REQUEST data?

EXAMPLE WORKING WITH GSUB:

function pre_backend( req )
  print('--Backend response, pre-logic:'); 
  print('--req');
  print(req);
  print(type(req));
  local r = req;
  print('--body');
  print(type(r:body()));
  print(r:body())
  local body_transformed = r:body():gsub('email', 'user_mail_1');
  print('--body_transformed');
  print(body_transformed);
  print(type(body_transformed));
end

Console output:

2022/02/11 09:59:52  DEBUG: [http-server-handler: no extra config]
--Backend response, pre-logic:
--req
userdata: 0xc0004f9b60
userdata
--body
string
{"email" : "[email protected]","test_field":"email"}
--body_transformed
{"user_mail_1" : "[email protected]","test_field":"user_mail_1"}
string

As we can see the gsub is not efficient becouse replace all strings. If I can work with req as table, dict or something similar, I can replace dict key/value. ex: req['xxx] = 'xxx' or iterate req.keys



Solution 1:[1]

gsub stands for global substitution. It replaces all occurances of the pattern in the string.

If you just want to replace "email" infront of an email address simply use a pattern that takes this into account.

print((r:body():gsub('(")(email)("%s-:%s-"%w+@%w+%.%w+")', "%1user_mail_1%3")))

Alternatively if you knwo that you only want to replace the first occurance of email you can simply do this:

print((r:body():gsub("email", "user_mail_1", 1)))

The thrid parameter will stop gsub after the first replacement.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Piglet