jsonrpc.lua 1.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. -- Copyright 2008 Steven Barth <steven@midlink.org>
  2. -- Copyright 2008 Jo-Philipp Wich <jow@openwrt.org>
  3. -- Licensed to the public under the Apache License 2.0.
  4. module("luci.jsonrpc", package.seeall)
  5. require "luci.json"
  6. function resolve(mod, method)
  7. local path = luci.util.split(method, ".")
  8. for j=1, #path-1 do
  9. if not type(mod) == "table" then
  10. break
  11. end
  12. mod = rawget(mod, path[j])
  13. if not mod then
  14. break
  15. end
  16. end
  17. mod = type(mod) == "table" and rawget(mod, path[#path]) or nil
  18. if type(mod) == "function" then
  19. return mod
  20. end
  21. end
  22. function handle(tbl, rawsource, ...)
  23. local decoder = luci.json.Decoder()
  24. local stat = luci.ltn12.pump.all(rawsource, decoder:sink())
  25. local json = decoder:get()
  26. local response
  27. local success = false
  28. if stat then
  29. if type(json.method) == "string"
  30. and (not json.params or type(json.params) == "table") then
  31. local method = resolve(tbl, json.method)
  32. if method then
  33. response = reply(json.jsonrpc, json.id,
  34. proxy(method, unpack(json.params or {})))
  35. else
  36. response = reply(json.jsonrpc, json.id,
  37. nil, {code=-32601, message="Method not found."})
  38. end
  39. else
  40. response = reply(json.jsonrpc, json.id,
  41. nil, {code=-32600, message="Invalid request."})
  42. end
  43. else
  44. response = reply("2.0", nil,
  45. nil, {code=-32700, message="Parse error."})
  46. end
  47. return luci.json.Encoder(response, ...):source()
  48. end
  49. function reply(jsonrpc, id, res, err)
  50. require "luci.json"
  51. id = id or luci.json.null
  52. -- 1.0 compatibility
  53. if jsonrpc ~= "2.0" then
  54. jsonrpc = nil
  55. res = res or luci.json.null
  56. err = err or luci.json.null
  57. end
  58. return {id=id, result=res, error=err, jsonrpc=jsonrpc}
  59. end
  60. function proxy(method, ...)
  61. local res = {luci.util.copcall(method, ...)}
  62. local stat = table.remove(res, 1)
  63. if not stat then
  64. return nil, {code=-32602, message="Invalid params.", data=table.remove(res, 1)}
  65. else
  66. if #res <= 1 then
  67. return res[1] or luci.json.null
  68. else
  69. return res
  70. end
  71. end
  72. end