openresty / lua-nginx-module

Embed the Power of Lua into NGINX HTTP servers
https://openresty.org/
11.33k stars 2.03k forks source link

Lua parse json value from request_body #2162

Open xmanag3r opened 1 year ago

xmanag3r commented 1 year ago

Hello, i'm receiving POST to my lua endpoint.

That post body it's with json body.

I need to cut off one object from json post body

The body that is coming is looking like this :

{
    "param1": "1033893",
    "param2": "337483",
    "param3": "test",

}

I want to cut only param2 (only numbers) and put it as a value because I need to compare it with one file content

I'm using this local : local check_body = ngx.req.get_body_data()

In bash script I normally run this :

echo $CURL_post_request | cut -d\| -f 1| grep -m1 -oP '\s*"param2"\s*:\s*\K[^,]+'| tr -d '"'| tr -d '}'

But in lua I'm not sure how I can fix this

agentzh commented 1 year ago

You can just use the lua-cjson library shipped with OpenResty to parse your POST request body in the JSON format.

xmanag3r commented 1 year ago

Thanks, i've solved that. I have another bug now,

local first_one = 12

string.match(first_one, second_one)

For example let's say first_one is a static variable that I'm entering second_one is a file where it's containing 12 number from file that it's having multiple numbers

local open_file = io.open(filepath, "rb")
   local second_one = open_file:read("*a")

open_file is containing for example

1283813122344
12
12838138931316
128381383131

But I want to get only 12 number (in this case second line) What is the best way to do this?

zhuizhuhaomeng commented 1 year ago

I don't know what exactly you want. Did you want to get the line number in the file? Or did you want to know if the number is in the file? Does the file change?

xmanag3r commented 1 year ago

Hi @zhuizhuhaomeng ,

i want the exact match with the exact of the content to get matched with my actual number .

So please let me know the both options and when i test i will update this issue, so everyone will be aware which one is working for me.

Thanks so much

zhuizhuhaomeng commented 1 year ago

I think you can read the file line by line and use a table to cache the lines if the file content does not change.

xmanag3r commented 1 year ago

Hi @zhuizhuhaomeng

local open_file = io.open(filepath, "rb")
   local second_one = open_file:read("*a")

I'm reading by that, what do you mean line by line, can you give me example?

zhuizhuhaomeng commented 1 year ago
local fh, err = io.open("data.txt")

local cache = {}
if fh == nil then
    -- 
    return
end

for line in fh:lines()
do
    cache[line] = 1
end

Something like the above. It would help if you gave a minimal example to show what you want. Otherwise, we don't know what exactly you want.

xmanag3r commented 1 year ago

So here is my scenario :

I have nginx-lua config, that it contains json data (from POST request) :

{
    "profile_name": "test",
    "number_from_json": "12",
}

In my /opt/file1.csv

1283813122344
12
12838138931316
128381383131

I have

So I'm having this config

location /reader_x {
   proxy_set_header X-Forwarded-Host $host;
   proxy_set_header X-Forwarded-Server $host;
   proxy_set_header X-Real-IP $remote_addr;
   proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
   proxy_set_header X-Url-Scheme $scheme;
   proxy_set_header X-Forwarded-Proto $scheme;
   proxy_set_header Host $http_host;
   proxy_redirect off;
   proxy_pass_request_body on;
   proxy_pass_request_headers on;
   proxy_ssl_verify off;
   if ($request_method = POST ) {
   rewrite_by_lua '
   ngx.req.read_body()
   local check_body = ngx.req.get_body_data()
   local data = ngx.req.get_body_data()
   json = require "dkjson"
   local json_parse = json.decode(check_body)
   local number_cut = json_parse.number_from_json
   local filepath = "/opt/file1.csv"
   local open_file = io.open(filepath, "rb")
   local second_one = open_file:read("*a")
   io.close(open_file)
   local  match0 = string.match(second_one, number_cut)
   if match0 then
   ngx.say("this is exactly matched 12")
else
   ngx.say("not matching")
   end
   ';
proxy_pass https://localhost:8421 ;

So I need only to match 12 unique number, not if the other numbers are contains "12"

Let me know if you need more info

zhuizhuhaomeng commented 1 year ago

Just like what I said above, you need to read the content from the file and cache the result if it is possible. If you open the file and read from the file every time, the disk IO would become a bottleneck.

If the content change from time to time, you want to match the file content you need to use ngx.re: eg:

local m, err = ngx.re.match(second_one, [[\b12\b]], "jo")
if m ~= nil then
    ngx.say("match")
end