Skip to content

Commit 8cd8bc2

Browse files
authored
fix: be compatible with the usage in APISIX (#186)
1 parent 8be79dc commit 8cd8bc2

File tree

3 files changed

+103
-19
lines changed

3 files changed

+103
-19
lines changed

lib/resty/etcd/v3.lua

Lines changed: 45 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,16 @@ local function _request_uri(self, method, uri, opts, timeout, ignore_auth)
261261
end
262262

263263

264+
local function serialize_grpc_value(serialize_fn, val)
265+
local err
266+
val, err = serialize_fn(val)
267+
if not val then
268+
return nil, err
269+
end
270+
return val
271+
end
272+
273+
264274
local function serialize_and_encode_base64(serialize_fn, data)
265275
local err
266276
data, err = serialize_fn(data)
@@ -987,20 +997,34 @@ local function watch(self, key, attr)
987997
return callback_fun
988998
end
989999

990-
local function convert_grpc_to_http_res(res)
1000+
function _grpc_M.convert_grpc_to_http_res(self, res)
9911001
if res == nil then
9921002
return nil
9931003
end
9941004

995-
if res.kvs and #res.kvs == 0 then
996-
-- gRPC returns empty kvs while HTTP returns nil
997-
res.kvs = nil
1005+
local status = 200
1006+
1007+
if res.kvs then
1008+
if #res.kvs == 0 then
1009+
-- gRPC returns empty kvs while HTTP returns nil
1010+
res.kvs = nil
1011+
else
1012+
for _, kv in ipairs(res.kvs) do
1013+
kv.value = self.serializer.deserialize(kv.value)
1014+
end
1015+
end
1016+
1017+
elseif res.deleted then
1018+
-- so fast APISIX only allow to delete a resource
1019+
if res.deleted == 0 then
1020+
status = 404
1021+
end
9981022
end
9991023

10001024
-- We leak the structure of http response in too many places, so here we need to convert
10011025
-- it to http response
10021026
local r = {
1003-
status = 200,
1027+
status = status,
10041028
headers = {},
10051029
body = res,
10061030
}
@@ -1009,18 +1033,9 @@ end
10091033

10101034

10111035
function _grpc_M.grpc_call(self, serv, meth, attr, key, val, opts)
1012-
if type(val) ~= "string" then
1013-
local err
1014-
val, err = encode_json(val)
1015-
if not val then
1016-
return nil, err
1017-
end
1018-
-- gRPC doesn't need `serializer`
1019-
end
1020-
10211036
local conn = self.conn
10221037
attr.key = key
1023-
attr.value = val
1038+
attr.value = serialize_grpc_value(self.serializer.serialize, val)
10241039

10251040
if opts then
10261041
self.call_opts.timeout = opts.timeout and opts.timeout * 1000
@@ -1031,7 +1046,7 @@ function _grpc_M.grpc_call(self, serv, meth, attr, key, val, opts)
10311046
self.call_opts.int64_encoding = self.grpc.INT64_AS_STRING
10321047

10331048
local res, err = conn:call(serv, meth, attr, self.call_opts)
1034-
return convert_grpc_to_http_res(res), err
1049+
return self:convert_grpc_to_http_res(res), err
10351050
end
10361051

10371052

@@ -1223,6 +1238,13 @@ function _M.txn(self, compare, success, failure, opts)
12231238

12241239
if self.use_grpc then
12251240
rule.key = utils.get_real_key(self.key_prefix, rule.key)
1241+
if rule.value then
1242+
rule.value, err = serialize_grpc_value(self.serializer.serialize,
1243+
rule.value)
1244+
if not rule.value then
1245+
return nil, "failed to encode value: " .. err
1246+
end
1247+
end
12261248
else
12271249
rule.key = encode_base64(utils.get_real_key(self.key_prefix, rule.key))
12281250

@@ -1246,16 +1268,20 @@ function _M.txn(self, compare, success, failure, opts)
12461268
rule = tab_clone(rule)
12471269
if rule.requestPut then
12481270
local requestPut = tab_clone(rule.requestPut)
1271+
local err
12491272
if self.use_grpc then
12501273
requestPut.key = utils.get_real_key(self.key_prefix, requestPut.key)
1274+
requestPut.value, err = serialize_grpc_value(self.serializer.serialize,
1275+
requestPut.value)
12511276
else
12521277
requestPut.key =
12531278
encode_base64(utils.get_real_key(self.key_prefix, requestPut.key))
12541279
requestPut.value, err = serialize_and_encode_base64(self.serializer.serialize,
12551280
requestPut.value)
1256-
if not requestPut.value then
1257-
return nil, "failed to encode value: " .. err
1258-
end
1281+
end
1282+
1283+
if not requestPut.value then
1284+
return nil, "failed to encode value: " .. err
12591285
end
12601286

12611287
if self.use_grpc then

t/v3/grpc/key.t

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,7 @@ ok
145145
146146
local data, err = etcd:delete("/test")
147147
assert(data.body.deleted == 0)
148+
assert(data.status == 404)
148149
local data, err = etcd:get("/test")
149150
check_res(data, nil)
150151
}

t/v3/grpc/txn.t

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,3 +147,60 @@ checked val as expect: abc
147147
}
148148
--- response_body
149149
checked val as expect: aaa
150+
151+
152+
153+
=== TEST 4: txn with table
154+
--- http_config eval: $::HttpConfig
155+
--- config
156+
location /t {
157+
content_by_lua_block {
158+
local cjson = require("cjson.safe")
159+
local function check_res(data, err, val, status)
160+
if err then
161+
ngx.say("err: ", err)
162+
ngx.exit(200)
163+
end
164+
165+
if val then
166+
if data.body.kvs==nil then
167+
ngx.exit(404)
168+
end
169+
if data.body.kvs and val ~= cjson.encode(data.body.kvs[1].value) then
170+
ngx.say("failed to check value")
171+
ngx.log(ngx.ERR, "failed to check value, got: ",
172+
cjson.encode(data.body.kvs[1].value),
173+
", expect: ", val)
174+
ngx.exit(200)
175+
else
176+
ngx.say("checked val as expect: ", val)
177+
end
178+
end
179+
180+
if status and status ~= data.status then
181+
ngx.exit(data.status)
182+
end
183+
end
184+
185+
local etcd, err = require "resty.etcd" .new({protocol = "v3", use_grpc = false})
186+
check_res(etcd, err)
187+
188+
local res, err = etcd:set("/test", {k = "abc"})
189+
check_res(res, err)
190+
191+
local data, err = etcd:get("/test")
192+
check_res(data, err, '{"k":"abc"}')
193+
194+
local data, err = etcd:txn(
195+
{{key = "/test", result = "EQUAL", value = {k = "abc"}, target = "VALUE"}},
196+
{{requestPut = {key = "/test", value = {k = "ddd"}}}}
197+
)
198+
check_res(data, err)
199+
200+
local data, err = etcd:get("/test")
201+
check_res(data, err, '{"k":"ddd"}')
202+
}
203+
}
204+
--- response_body
205+
checked val as expect: {"k":"abc"}
206+
checked val as expect: {"k":"ddd"}

0 commit comments

Comments
 (0)