mirror of https://github.com/koreader/koreader
Merge pull request #1448 from chrox/sync_progress
add progress sync plugin and various fixespull/1453/head v2015.03.16-nightly
commit
2aebba97f2
@ -1 +1 @@
|
||||
Subproject commit 897906d91a3cbba0eb2aa27583a6510c99ac720d
|
||||
Subproject commit 7e39b96927d11083679e8329874da6ec92501d00
|
@ -1 +1 @@
|
||||
Subproject commit 576b42e8aedd29af20415fd840f26623258caaa3
|
||||
Subproject commit 64caed00259bb23b789f2a8051e77efa9bcde9cc
|
@ -0,0 +1,152 @@
|
||||
local UIManager = require("ui/uimanager")
|
||||
local DEBUG = require("dbg")
|
||||
|
||||
local KOSyncClient = {
|
||||
service_spec = nil,
|
||||
}
|
||||
|
||||
function KOSyncClient:new(o)
|
||||
local o = o or {}
|
||||
setmetatable(o, self)
|
||||
self.__index = self
|
||||
if o.init then o:init() end
|
||||
return o
|
||||
end
|
||||
|
||||
function KOSyncClient:init()
|
||||
local Spore = require("Spore")
|
||||
self.client = Spore.new_from_spec(self.service_spec)
|
||||
package.loaded['Spore.Middleware.GinClient'] = {}
|
||||
require('Spore.Middleware.GinClient').call = function(self, req)
|
||||
req.headers['accept'] = "application/vnd.koreader.v1+json"
|
||||
end
|
||||
package.loaded['Spore.Middleware.KOSyncAuth'] = {}
|
||||
require('Spore.Middleware.KOSyncAuth').call = function(args, req)
|
||||
req.headers['x-auth-user'] = args.username
|
||||
req.headers['x-auth-key'] = args.userkey
|
||||
end
|
||||
local HTTPClient = require("httpclient")
|
||||
local async_http_client = HTTPClient:new()
|
||||
package.loaded['Spore.Middleware.AsyncHTTP'] = {}
|
||||
require('Spore.Middleware.AsyncHTTP').call = function(args, req)
|
||||
req:finalize()
|
||||
local result
|
||||
async_http_client:request({
|
||||
url = req.url,
|
||||
method = req.method,
|
||||
body = req.env.spore.payload,
|
||||
on_headers = function(headers)
|
||||
for header, value in pairs(req.headers) do
|
||||
if type(header) == 'string' then
|
||||
headers:add(header, value)
|
||||
end
|
||||
end
|
||||
end,
|
||||
}, function(res)
|
||||
result = res
|
||||
-- Turbo HTTP client uses code instead of status
|
||||
-- change to status so that Spore can understand
|
||||
result.status = res.code
|
||||
-- fallback to sync http request
|
||||
if result.error then result = nil end
|
||||
coroutine.resume(args.thread)
|
||||
end)
|
||||
return coroutine.create(function() coroutine.yield(result) end)
|
||||
end
|
||||
end
|
||||
|
||||
function KOSyncClient:register(username, password)
|
||||
self.client:reset_middlewares()
|
||||
self.client:enable('Format.JSON')
|
||||
self.client:enable("GinClient")
|
||||
local ok, res = pcall(function()
|
||||
return self.client:register({
|
||||
username = username,
|
||||
password = password,
|
||||
})
|
||||
end)
|
||||
if ok then
|
||||
return res.status == 201, res.body
|
||||
else
|
||||
DEBUG(ok, res)
|
||||
return false, res.body
|
||||
end
|
||||
end
|
||||
|
||||
function KOSyncClient:authorize(username, password)
|
||||
self.client:reset_middlewares()
|
||||
self.client:enable('Format.JSON')
|
||||
self.client:enable("GinClient")
|
||||
self.client:enable("KOSyncAuth", {
|
||||
username = username,
|
||||
userkey = password,
|
||||
})
|
||||
local ok, res = pcall(function()
|
||||
return self.client:authorize()
|
||||
end)
|
||||
if ok then
|
||||
return res.status == 200, res.body
|
||||
else
|
||||
DEBUG("err:", res)
|
||||
return false, res
|
||||
end
|
||||
end
|
||||
|
||||
function KOSyncClient:update_progress(username, password,
|
||||
document, progress, percentage, device, callback)
|
||||
self.client:reset_middlewares()
|
||||
self.client:enable('Format.JSON')
|
||||
self.client:enable("GinClient")
|
||||
self.client:enable("KOSyncAuth", {
|
||||
username = username,
|
||||
userkey = password,
|
||||
})
|
||||
local co = coroutine.create(function()
|
||||
local ok, res = pcall(function()
|
||||
return self.client:update_progress({
|
||||
document = document,
|
||||
progress = progress,
|
||||
percentage = percentage,
|
||||
device = device,
|
||||
})
|
||||
end)
|
||||
if ok then
|
||||
callback(res.status == 200, res.body)
|
||||
else
|
||||
DEBUG("err:", res)
|
||||
callback(false, res)
|
||||
end
|
||||
end)
|
||||
self.client:enable("AsyncHTTP", {thread = co})
|
||||
coroutine.resume(co)
|
||||
UIManager.INPUT_TIMEOUT = 100
|
||||
end
|
||||
|
||||
function KOSyncClient:get_progress(username, password,
|
||||
document, callback)
|
||||
self.client:reset_middlewares()
|
||||
self.client:enable('Format.JSON')
|
||||
self.client:enable("GinClient")
|
||||
self.client:enable("KOSyncAuth", {
|
||||
username = username,
|
||||
userkey = password,
|
||||
})
|
||||
local co = coroutine.create(function()
|
||||
local ok, res = pcall(function()
|
||||
return self.client:get_progress({
|
||||
document = document,
|
||||
})
|
||||
end)
|
||||
if ok then
|
||||
callback(res.status == 200, res.body)
|
||||
else
|
||||
DEBUG("err:", res)
|
||||
callback(false, res)
|
||||
end
|
||||
end)
|
||||
self.client:enable("AsyncHTTP", {thread = co})
|
||||
coroutine.resume(co)
|
||||
UIManager.INPUT_TIMEOUT = 100
|
||||
end
|
||||
|
||||
return KOSyncClient
|
@ -0,0 +1,49 @@
|
||||
{
|
||||
"base_url" : "https://vislab.bjmu.edu.cn:7200/",
|
||||
"name" : "koreader-sync-api",
|
||||
"methods" : {
|
||||
"register" : {
|
||||
"path" : "/users/create",
|
||||
"method" : "POST",
|
||||
"required_params" : [
|
||||
"username",
|
||||
"password",
|
||||
],
|
||||
"payload" : [
|
||||
"username",
|
||||
"password",
|
||||
],
|
||||
"expected_status" : [201, 402]
|
||||
},
|
||||
"authorize" : {
|
||||
"path" : "/users/auth",
|
||||
"method" : "GET",
|
||||
"expected_status" : [200, 401]
|
||||
},
|
||||
"update_progress" : {
|
||||
"path" : "/syncs/progress",
|
||||
"method" : "PUT",
|
||||
"required_params" : [
|
||||
"document",
|
||||
"progress",
|
||||
"percentage",
|
||||
"device",
|
||||
],
|
||||
"payload" : [
|
||||
"document",
|
||||
"progress",
|
||||
"percentage",
|
||||
"device",
|
||||
],
|
||||
"expected_status" : [200, 202, 401]
|
||||
},
|
||||
"get_progress" : {
|
||||
"path" : "/syncs/progress/:document",
|
||||
"method" : "GET",
|
||||
"required_params" : [
|
||||
"document",
|
||||
],
|
||||
"expected_status" : [200, 401]
|
||||
},
|
||||
}
|
||||
}
|
@ -0,0 +1,307 @@
|
||||
local InputContainer = require("ui/widget/container/inputcontainer")
|
||||
local LoginDialog = require("ui/widget/logindialog")
|
||||
local InfoMessage = require("ui/widget/infomessage")
|
||||
local ConfirmBox = require("ui/widget/confirmbox")
|
||||
local DocSettings = require("docsettings")
|
||||
local NetworkMgr = require("ui/networkmgr")
|
||||
local UIManager = require("ui/uimanager")
|
||||
local Screen = require("device").screen
|
||||
local Device = require("device")
|
||||
local Event = require("ui/event")
|
||||
local Math = require("optmath")
|
||||
local DEBUG = require("dbg")
|
||||
local T = require("ffi/util").template
|
||||
local _ = require("gettext")
|
||||
local md5 = require("MD5")
|
||||
|
||||
local l10n = {
|
||||
_("Unknown server error."),
|
||||
_("Unauthorized"),
|
||||
_("Username is already registered."),
|
||||
}
|
||||
|
||||
local KOSync = InputContainer:new{
|
||||
name = "kosync",
|
||||
title = _("Register/login to Koreader server"),
|
||||
}
|
||||
|
||||
function KOSync:init()
|
||||
local settings = G_reader_settings:readSetting("kosync") or {}
|
||||
self.kosync_username = settings.username
|
||||
self.kosync_userkey = settings.userkey
|
||||
self.kosync_auto_sync = not (settings.auto_sync == false)
|
||||
self.ui:registerPostInitCallback(function()
|
||||
if self.kosync_auto_sync then
|
||||
UIManager:scheduleIn(1, function() self:getProgress() end)
|
||||
end
|
||||
end)
|
||||
self.ui.menu:registerToMainMenu(self)
|
||||
end
|
||||
|
||||
function KOSync:addToMainMenu(tab_item_table)
|
||||
table.insert(tab_item_table.plugins, {
|
||||
text = _("Progress sync"),
|
||||
sub_item_table = {
|
||||
{
|
||||
text_func = function()
|
||||
return self.kosync_userkey and (_("Logout"))
|
||||
or _("Register") .. " / " .. _("Login")
|
||||
end,
|
||||
callback_func = function()
|
||||
return self.kosync_userkey and
|
||||
function() self:logout() end or
|
||||
function() self:login() end
|
||||
end,
|
||||
},
|
||||
{
|
||||
text = _("Auto sync"),
|
||||
checked_func = function() return self.kosync_auto_sync end,
|
||||
callback = function()
|
||||
self.kosync_auto_sync = not self.kosync_auto_sync
|
||||
end,
|
||||
},
|
||||
{
|
||||
text = _("Sync now"),
|
||||
enabled_func = function()
|
||||
return self.kosync_userkey ~= nil
|
||||
end,
|
||||
callback = function()
|
||||
self:updateProgress()
|
||||
self:getProgress(true)
|
||||
end,
|
||||
}
|
||||
}
|
||||
})
|
||||
end
|
||||
|
||||
function KOSync:login()
|
||||
if NetworkMgr:getWifiStatus() == false then
|
||||
NetworkMgr:promptWifiOn()
|
||||
end
|
||||
self.login_dialog = LoginDialog:new{
|
||||
title = self.title,
|
||||
username = self.kosync_username or "",
|
||||
buttons = {
|
||||
{
|
||||
{
|
||||
text = _("Cancel"),
|
||||
enabled = true,
|
||||
callback = function()
|
||||
self:closeDialog()
|
||||
end,
|
||||
},
|
||||
{
|
||||
text = _("Login"),
|
||||
enabled = true,
|
||||
callback = function()
|
||||
local username, password = self:getCredential()
|
||||
self:closeDialog()
|
||||
UIManager:scheduleIn(0.5, function()
|
||||
self:doLogin(username, password)
|
||||
end)
|
||||
|
||||
UIManager:show(InfoMessage:new{
|
||||
text = _("Logging in. Please wait..."),
|
||||
timeout = 1,
|
||||
})
|
||||
end,
|
||||
},
|
||||
{
|
||||
text = _("Register"),
|
||||
enabled = true,
|
||||
callback = function()
|
||||
local username, password = self:getCredential()
|
||||
self:closeDialog()
|
||||
UIManager:scheduleIn(0.5, function()
|
||||
self:doRegister(username, password)
|
||||
end)
|
||||
|
||||
UIManager:show(InfoMessage:new{
|
||||
text = _("Registering. Please wait..."),
|
||||
timeout = 1,
|
||||
})
|
||||
end,
|
||||
},
|
||||
},
|
||||
},
|
||||
width = Screen:getWidth() * 0.8,
|
||||
height = Screen:getHeight() * 0.4,
|
||||
}
|
||||
|
||||
self.login_dialog:onShowKeyboard()
|
||||
UIManager:show(self.login_dialog)
|
||||
end
|
||||
|
||||
function KOSync:closeDialog()
|
||||
self.login_dialog:onClose()
|
||||
UIManager:close(self.login_dialog)
|
||||
end
|
||||
|
||||
function KOSync:getCredential()
|
||||
return self.login_dialog:getCredential()
|
||||
end
|
||||
|
||||
function KOSync:doRegister(username, password)
|
||||
local KOSyncClient = require("KOSyncClient")
|
||||
local client = KOSyncClient:new{
|
||||
service_spec = self.path .. "/api.json"
|
||||
}
|
||||
local userkey = md5:sum(password)
|
||||
local ok, status, body = pcall(client.register, client, username, userkey)
|
||||
if not ok and status then
|
||||
UIManager:show(InfoMessage:new{
|
||||
text = _("An error occurred while registering:") ..
|
||||
"\n" .. status,
|
||||
})
|
||||
elseif ok then
|
||||
if status then
|
||||
self.kosync_username = username
|
||||
self.kosync_userkey = userkey
|
||||
UIManager:show(InfoMessage:new{
|
||||
text = _("Registered to Koreader server successfully."),
|
||||
})
|
||||
else
|
||||
UIManager:show(InfoMessage:new{
|
||||
text = _(body.message or "Unknown server error"),
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
self:onSaveSettings()
|
||||
end
|
||||
|
||||
function KOSync:doLogin(username, password)
|
||||
local KOSyncClient = require("KOSyncClient")
|
||||
local client = KOSyncClient:new{
|
||||
service_spec = self.path .. "/api.json"
|
||||
}
|
||||
local userkey = md5:sum(password)
|
||||
local ok, status, body = pcall(client.authorize, client, username, userkey)
|
||||
if not ok and status then
|
||||
UIManager:show(InfoMessage:new{
|
||||
text = _("An error occurred while logging in:") ..
|
||||
"\n" .. status,
|
||||
})
|
||||
elseif ok then
|
||||
if status then
|
||||
self.kosync_username = username
|
||||
self.kosync_userkey = userkey
|
||||
UIManager:show(InfoMessage:new{
|
||||
text = _("Logged in to Koreader server successfully."),
|
||||
})
|
||||
else
|
||||
UIManager:show(InfoMessage:new{
|
||||
text = _(body.message or "Unknown server error"),
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
self:onSaveSettings()
|
||||
end
|
||||
|
||||
function KOSync:logout()
|
||||
self.kosync_userkey = nil
|
||||
self.kosync_auto_sync = true
|
||||
self:onSaveSettings()
|
||||
end
|
||||
|
||||
function KOSync:getLastPercent()
|
||||
if self.ui.document.info.has_pages then
|
||||
return self.ui.paging:getLastPercent()
|
||||
else
|
||||
return self.ui.rolling:getLastPercent()
|
||||
end
|
||||
end
|
||||
|
||||
function KOSync:getLastProgress()
|
||||
if self.ui.document.info.has_pages then
|
||||
return self.ui.paging:getLastProgress()
|
||||
else
|
||||
return self.ui.rolling:getLastProgress()
|
||||
end
|
||||
end
|
||||
|
||||
function KOSync:syncToProgress(progress)
|
||||
DEBUG("sync to", progress)
|
||||
if self.ui.document.info.has_pages then
|
||||
self.ui:handleEvent(Event:new("GotoPage", tonumber(progress)))
|
||||
else
|
||||
self.ui:handleEvent(Event:new("GotoXPointer", progress))
|
||||
end
|
||||
end
|
||||
|
||||
function KOSync:updateProgress()
|
||||
if self.kosync_username and self.kosync_userkey then
|
||||
local KOSyncClient = require("KOSyncClient")
|
||||
local client = KOSyncClient:new{
|
||||
service_spec = self.path .. "/api.json"
|
||||
}
|
||||
local doc_digest = self.view.document:fastDigest()
|
||||
local progress = self:getLastProgress()
|
||||
local percentage = self:getLastPercent()
|
||||
local ok, err = pcall(client.update_progress, client,
|
||||
self.kosync_username, self.kosync_userkey,
|
||||
doc_digest, progress, percentage, Device.model,
|
||||
function(ok, body)
|
||||
DEBUG("update progress for", self.view.document.file, ok)
|
||||
end)
|
||||
if not ok and err then
|
||||
DEBUG("err:", err)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function KOSync:getProgress(manual)
|
||||
if self.kosync_username and self.kosync_userkey then
|
||||
local KOSyncClient = require("KOSyncClient")
|
||||
local client = KOSyncClient:new{
|
||||
service_spec = self.path .. "/api.json"
|
||||
}
|
||||
local doc_digest = self.view.document:fastDigest()
|
||||
local ok, err = pcall(client.get_progress, client,
|
||||
self.kosync_username, self.kosync_userkey,
|
||||
doc_digest, function(ok, body)
|
||||
DEBUG("get progress for", self.view.document.file, ok, body)
|
||||
if body and body.percentage then
|
||||
local progress = self:getLastProgress()
|
||||
local percentage = self:getLastPercent()
|
||||
DEBUG("current progress", percentage)
|
||||
if body.percentage > percentage and body.progress ~= progress then
|
||||
UIManager:show(ConfirmBox:new{
|
||||
text = T(_("Sync to furthest location %1% from device '%2'?"),
|
||||
Math.round(body.percentage*100), body.device),
|
||||
ok_callback = function()
|
||||
self:syncToProgress(body.progress)
|
||||
end,
|
||||
})
|
||||
elseif manual and body.progress == progress then
|
||||
UIManager:show(InfoMessage:new{
|
||||
text = _("We are already synchronized."),
|
||||
timeout = 3,
|
||||
})
|
||||
end
|
||||
end
|
||||
end)
|
||||
if not ok and err then
|
||||
DEBUG("err:", err)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function KOSync:onSaveSettings()
|
||||
local settings = {
|
||||
username = self.kosync_username,
|
||||
userkey = self.kosync_userkey,
|
||||
auto_sync = self.kosync_auto_sync,
|
||||
}
|
||||
G_reader_settings:saveSetting("kosync", settings)
|
||||
end
|
||||
|
||||
function KOSync:onCloseDocument()
|
||||
DEBUG("on close document")
|
||||
if self.kosync_auto_sync then
|
||||
self:updateProgress()
|
||||
end
|
||||
end
|
||||
|
||||
return KOSync
|
@ -0,0 +1,178 @@
|
||||
package.path = "rocks/share/lua/5.1/?.lua;" .. package.path
|
||||
package.cpath = "rocks/lib/lua/5.1/?.so;" .. package.cpath
|
||||
require("commonrequire")
|
||||
local UIManager = require("ui/uimanager")
|
||||
local HTTPClient = require("httpclient")
|
||||
local DEBUG = require("dbg")
|
||||
local md5 = require("MD5")
|
||||
--DEBUG:turnOn()
|
||||
|
||||
local service = [[
|
||||
{
|
||||
"base_url" : "https://192.168.1.101:7200",
|
||||
"name" : "api",
|
||||
"methods" : {
|
||||
"register" : {
|
||||
"path" : "/users/create",
|
||||
"method" : "POST",
|
||||
"required_params" : [
|
||||
"username",
|
||||
"password",
|
||||
],
|
||||
"payload" : [
|
||||
"username",
|
||||
"password",
|
||||
],
|
||||
"expected_status" : [201, 402]
|
||||
},
|
||||
"authorize" : {
|
||||
"path" : "/users/auth",
|
||||
"method" : "GET",
|
||||
"expected_status" : [200, 401]
|
||||
},
|
||||
"update_progress" : {
|
||||
"path" : "/syncs/progress",
|
||||
"method" : "PUT",
|
||||
"required_params" : [
|
||||
"document",
|
||||
"progress",
|
||||
"percentage",
|
||||
"device",
|
||||
],
|
||||
"payload" : [
|
||||
"document",
|
||||
"progress",
|
||||
"percentage",
|
||||
"device",
|
||||
],
|
||||
"expected_status" : [200, 202, 401]
|
||||
},
|
||||
"get_progress" : {
|
||||
"path" : "/syncs/progress/:document",
|
||||
"method" : "GET",
|
||||
"required_params" : [
|
||||
"document",
|
||||
],
|
||||
"expected_status" : [200, 401]
|
||||
},
|
||||
}
|
||||
}
|
||||
]]
|
||||
|
||||
describe("KOSync modules #notest #nocov", function()
|
||||
local Spore = require("Spore")
|
||||
local client = Spore.new_from_string(service)
|
||||
package.loaded['Spore.Middleware.GinClient'] = {}
|
||||
require('Spore.Middleware.GinClient').call = function(self, req)
|
||||
req.headers['accept'] = "application/vnd.koreader.v1+json"
|
||||
end
|
||||
package.loaded['Spore.Middleware.KOSyncAuth'] = {}
|
||||
require('Spore.Middleware.KOSyncAuth').call = function(args, req)
|
||||
req.headers['x-auth-user'] = args.username
|
||||
req.headers['x-auth-key'] = args.userkey
|
||||
end
|
||||
-- password should be hashed before submitting to server
|
||||
local username, password = "koreader", md5:sum("koreader")
|
||||
-- fake progress data
|
||||
local doc, percentage, progress, device =
|
||||
"41cce710f34e5ec21315e19c99821415", -- fast digest of the document
|
||||
0.356, -- percentage of the progress
|
||||
"69", -- page number or xpointer
|
||||
"my kpw" -- device name
|
||||
it("should create new user", function()
|
||||
client:reset_middlewares()
|
||||
client:enable('Format.JSON')
|
||||
client:enable("GinClient")
|
||||
local ok, res = pcall(function()
|
||||
return client:register({
|
||||
username = username,
|
||||
password = password,
|
||||
})
|
||||
end)
|
||||
if ok then
|
||||
if res.status == 200 then
|
||||
DEBUG("register successful to ", res.body.username)
|
||||
elseif res.status == 402 then
|
||||
DEBUG("register unsuccessful: ", res.body.message)
|
||||
end
|
||||
else
|
||||
DEBUG("Please retry later", res)
|
||||
end
|
||||
end)
|
||||
it("should authorize user", function()
|
||||
client:reset_middlewares()
|
||||
client:enable('Format.JSON')
|
||||
client:enable("GinClient")
|
||||
client:enable("KOSyncAuth", {
|
||||
username = username,
|
||||
userkey = password,
|
||||
})
|
||||
local ok, res = pcall(function()
|
||||
return client:authorize()
|
||||
end)
|
||||
if ok then
|
||||
if res.status == 200 then
|
||||
assert.are.same("OK", res.body.authorized)
|
||||
else
|
||||
DEBUG(res.body)
|
||||
end
|
||||
else
|
||||
DEBUG("Please retry later", res)
|
||||
end
|
||||
end)
|
||||
it("should update progress", function()
|
||||
client:reset_middlewares()
|
||||
client:enable('Format.JSON')
|
||||
client:enable("GinClient")
|
||||
client:enable("KOSyncAuth", {
|
||||
username = username,
|
||||
userkey = password,
|
||||
})
|
||||
local ok, res = pcall(function()
|
||||
return client:update_progress({
|
||||
document = doc,
|
||||
progress = progress,
|
||||
percentage = percentage,
|
||||
device = device,
|
||||
})
|
||||
end)
|
||||
if ok then
|
||||
if res.status == 200 then
|
||||
local result = res.body
|
||||
assert.are.same(progress, result.progress)
|
||||
assert.are.same(percentage, result.percentage)
|
||||
assert.are.same(device, result.device)
|
||||
else
|
||||
DEBUG(res.body.message)
|
||||
end
|
||||
else
|
||||
DEBUG("Please retry later", res)
|
||||
end
|
||||
end)
|
||||
it("should get progress", function()
|
||||
client:reset_middlewares()
|
||||
client:enable('Format.JSON')
|
||||
client:enable("GinClient")
|
||||
client:enable("KOSyncAuth", {
|
||||
username = username,
|
||||
userkey = password,
|
||||
})
|
||||
local ok, res = pcall(function()
|
||||
return client:get_progress({
|
||||
document = doc,
|
||||
})
|
||||
end)
|
||||
if ok then
|
||||
if res.status == 200 then
|
||||
local result = res.body
|
||||
assert.are.same(progress, result.progress)
|
||||
assert.are.same(percentage, result.percentage)
|
||||
assert.are.same(device, result.device)
|
||||
else
|
||||
DEBUG(res.body.message)
|
||||
end
|
||||
else
|
||||
DEBUG("Please retry later", res)
|
||||
end
|
||||
end)
|
||||
end)
|
@ -0,0 +1,115 @@
|
||||
package.path = "rocks/share/lua/5.1/?.lua;" .. package.path
|
||||
package.cpath = "rocks/lib/lua/5.1/?.so;" .. package.cpath
|
||||
require("commonrequire")
|
||||
local UIManager = require("ui/uimanager")
|
||||
local HTTPClient = require("httpclient")
|
||||
local DEBUG = require("dbg")
|
||||
--DEBUG:turnOn()
|
||||
|
||||
local service = [[
|
||||
{
|
||||
"base_url" : "http://httpbin.org",
|
||||
"name" : "api",
|
||||
"methods" : {
|
||||
"get_info" : {
|
||||
"path" : "/get",
|
||||
"method" : "GET",
|
||||
"required_params" : [
|
||||
"user"
|
||||
],
|
||||
"optional_params" : [
|
||||
"age"
|
||||
],
|
||||
},
|
||||
"post_info" : {
|
||||
"path" : "/post",
|
||||
"method" : "POST",
|
||||
"required_params" : [
|
||||
"user"
|
||||
],
|
||||
"optional_params" : [
|
||||
"age"
|
||||
],
|
||||
"payload" : [
|
||||
"user",
|
||||
"age",
|
||||
],
|
||||
},
|
||||
}
|
||||
}
|
||||
]]
|
||||
|
||||
describe("Lua Spore modules #nocov", function()
|
||||
local Spore = require("Spore")
|
||||
local client = Spore.new_from_string(service)
|
||||
client:enable('Format.JSON')
|
||||
it("should complete GET request", function()
|
||||
local info = {user = 'john', age = '25'}
|
||||
local res = client:get_info(info)
|
||||
assert.are.same(res.body.args, info)
|
||||
end)
|
||||
it("should complete POST request", function()
|
||||
local info = {user = 'sam', age = '26'}
|
||||
local res = client:post_info(info)
|
||||
assert.are.same(res.body.json, info)
|
||||
end)
|
||||
end)
|
||||
|
||||
describe("Lua Spore modules with async http request #nocov", function()
|
||||
local Spore = require("Spore")
|
||||
local client = Spore.new_from_string(service)
|
||||
local async_http_client = HTTPClient:new()
|
||||
package.loaded['Spore.Middleware.AsyncHTTP'] = {}
|
||||
require('Spore.Middleware.AsyncHTTP').call = function(args, req)
|
||||
req:finalize()
|
||||
local result
|
||||
async_http_client:request({
|
||||
url = req.url,
|
||||
method = req.method,
|
||||
body = req.env.spore.payload,
|
||||
on_headers = function(headers)
|
||||
for header, value in pairs(req.headers) do
|
||||
if type(header) == 'string' then
|
||||
headers:add(header, value)
|
||||
end
|
||||
end
|
||||
end,
|
||||
}, function(res)
|
||||
result = res
|
||||
-- Turbo HTTP client uses code instead of status
|
||||
-- change to status so that Spore can understand
|
||||
result.status = res.code
|
||||
coroutine.resume(args.thread)
|
||||
UIManager.INPUT_TIMEOUT = 100 -- no need in production
|
||||
end)
|
||||
return coroutine.create(function() coroutine.yield(result) end)
|
||||
end
|
||||
it("should complete GET request", function()
|
||||
UIManager:quit()
|
||||
local co = coroutine.create(function()
|
||||
local info = {user = 'john', age = '25'}
|
||||
local res = client:get_info(info)
|
||||
UIManager:quit()
|
||||
assert.are.same(res.body.args, info)
|
||||
end)
|
||||
client:reset_middlewares()
|
||||
client:enable("Format.JSON")
|
||||
client:enable("AsyncHTTP", {thread = co})
|
||||
coroutine.resume(co)
|
||||
UIManager:runForever()
|
||||
end)
|
||||
it("should complete POST request", function()
|
||||
UIManager:quit()
|
||||
local co = coroutine.create(function()
|
||||
local info = {user = 'sam', age = '26'}
|
||||
local res = client:post_info(info)
|
||||
UIManager:quit()
|
||||
assert.are.same(res.body.json, info)
|
||||
end)
|
||||
client:reset_middlewares()
|
||||
client:enable("Format.JSON")
|
||||
client:enable("AsyncHTTP", {thread = co})
|
||||
coroutine.resume(co)
|
||||
UIManager:runForever()
|
||||
end)
|
||||
end)
|
Loading…
Reference in New Issue