Add system.listMethods RPC method

system.listMethods just returns the available RPC method names.  It
can be executed without secret token, because it just returns the
method names, and does not alter anything.

See GH-437
pull/538/head
Tatsuhiro Tsujikawa 2015-12-26 20:57:33 +09:00
parent b9435f8786
commit d0ccb39880
6 changed files with 115 additions and 0 deletions

View File

@ -2228,6 +2228,10 @@ to provide the token as the first parameter as described above.
interface. Therefore it is recommended to prefer Batch or `system.multicall`
requests when appropriate.
`system.listMethods` can be executed without token. Since it just
returns the all available methods, and does not alter anything, it
is safe without secret token.
Methods
~~~~~~~
@ -3429,6 +3433,36 @@ For information on the *secret* parameter, see :ref:`rpc_auth`.
>>> tuple(r)
('2089b05ecca3d829', 'd2703803b52216d1')
.. function:: system.listMethods()
This method returns the all available RPC methods in an array of
string. Unlike other methods, this method does not require secret
token. This is safe because this method jsut returns the available
method names.
**JSON-RPC Example**
::
>>> import urllib2, json
>>> from pprint import pprint
>>> jsonreq = json.dumps({'jsonrpc':'2.0', 'id':'qwer',
... 'method':'system.listMethods'})
>>> c = urllib2.urlopen('http://localhost:6800/jsonrpc', jsonreq)
>>> pprint(json.loads(c.read()))
{u'id': u'qwer',
u'jsonrpc': u'2.0',
u'result': [u'aria2.addUri',
u'aria2.addTorrent',
...
**XML-RPC Example**
::
>>> import xmlrpclib
>>> s = xmlrpclib.ServerProxy('http://localhost:6800/rpc')
>>> s.system.listMethods()
['aria2.addUri', 'aria2.addTorrent', ...
Error Handling
~~~~~~~~~~~~~~

View File

@ -49,6 +49,30 @@ namespace {
std::unique_ptr<RpcMethod> noSuchRpcMethod;
} // namespace
namespace {
std::vector<std::string> rpcMethodNames = {
"aria2.addUri",
#ifdef ENABLE_BITTORRENT
"aria2.addTorrent", "aria2.getPeers",
#endif // ENABLE_BITTORRENT
#ifdef ENABLE_METALINK
"aria2.addMetalink",
#endif // ENABLE_METALINK
"aria2.remove", "aria2.pause", "aria2.forcePause", "aria2.pauseAll",
"aria2.forcePauseAll", "aria2.unpause", "aria2.unpauseAll",
"aria2.forceRemove", "aria2.changePosition", "aria2.tellStatus",
"aria2.getUris", "aria2.getFiles", "aria2.getServers", "aria2.tellActive",
"aria2.tellWaiting", "aria2.tellStopped", "aria2.getOption",
"aria2.changeUri", "aria2.changeOption", "aria2.getGlobalOption",
"aria2.changeGlobalOption", "aria2.purgeDownloadResult",
"aria2.removeDownloadResult", "aria2.getVersion", "aria2.getSessionInfo",
"aria2.shutdown", "aria2.forceShutdown", "aria2.getGlobalStat",
"aria2.saveSession", "system.multicall", "system.listMethods",
};
} // namespace
const std::vector<std::string>& allMethodNames() { return rpcMethodNames; }
namespace {
std::unique_ptr<RpcMethod> createMethod(const std::string& methodName)
{
@ -192,6 +216,10 @@ std::unique_ptr<RpcMethod> createMethod(const std::string& methodName)
return make_unique<SystemMulticallRpcMethod>();
}
if (methodName == SystemListMethodsRpcMethod::getMethodName()) {
return make_unique<SystemListMethodsRpcMethod>();
}
return nullptr;
}
} // namespace

View File

@ -39,6 +39,7 @@
#include <string>
#include <memory>
#include <vector>
namespace aria2 {
@ -46,6 +47,8 @@ namespace rpc {
class RpcMethod;
const std::vector<std::string>& allMethodNames();
RpcMethod* getMethod(const std::string& methodName);
} // namespace rpc

View File

@ -1429,6 +1429,24 @@ RpcResponse SystemMulticallRpcMethod::execute(RpcRequest req, DownloadEngine *e)
}
}
std::unique_ptr<ValueBase> SystemListMethodsRpcMethod::process
(const RpcRequest&req, DownloadEngine *e) {
auto list = List::g();
for (auto &s : allMethodNames()) {
list->append(s);
}
return list;
}
RpcResponse SystemListMethodsRpcMethod::execute(RpcRequest req,
DownloadEngine* e)
{
auto r = process(req, e);
return RpcResponse(0, RpcResponse::AUTHORIZED, std::move(r),
std::move(req.id));
}
std::unique_ptr<ValueBase> NoSuchMethodRpcMethod::process
(const RpcRequest& req, DownloadEngine* e)
{

View File

@ -596,6 +596,17 @@ public:
}
};
class SystemListMethodsRpcMethod : public RpcMethod {
protected:
virtual std::unique_ptr<ValueBase> process(const RpcRequest& req,
DownloadEngine* e) CXX11_OVERRIDE;
public:
virtual RpcResponse execute(RpcRequest req, DownloadEngine* e) CXX11_OVERRIDE;
static const char* getMethodName() { return "system.listMethods"; }
};
class NoSuchMethodRpcMethod:public RpcMethod {
protected:
virtual std::unique_ptr<ValueBase> process

View File

@ -20,6 +20,7 @@
#include "array_fun.h"
#include "download_helper.h"
#include "FileEntry.h"
#include "RpcMethodFactory.h"
#ifdef ENABLE_BITTORRENT
# include "BtRegistry.h"
# include "BtRuntime.h"
@ -78,6 +79,7 @@ class RpcMethodTest:public CppUnit::TestFixture {
CPPUNIT_TEST(testPause);
CPPUNIT_TEST(testSystemMulticall);
CPPUNIT_TEST(testSystemMulticall_fail);
CPPUNIT_TEST(testSystemListMethods);
CPPUNIT_TEST_SUITE_END();
private:
std::shared_ptr<DownloadEngine> e_;
@ -142,6 +144,7 @@ public:
void testPause();
void testSystemMulticall();
void testSystemMulticall_fail();
void testSystemListMethods();
};
@ -1363,6 +1366,24 @@ void RpcMethodTest::testSystemMulticall_fail()
CPPUNIT_ASSERT_EQUAL(1, res.code);
}
void RpcMethodTest::testSystemListMethods()
{
SystemListMethodsRpcMethod m;
auto res = m.execute(createReq("system.listMethods"), e_.get());
CPPUNIT_ASSERT_EQUAL(0, res.code);
const auto resParams = downcast<List>(res.param);
auto &allNames = allMethodNames();
CPPUNIT_ASSERT_EQUAL(allNames.size(), resParams->size());
for (size_t i = 0; i < allNames.size(); ++i) {
const auto s = downcast<String>(resParams->get(i));
CPPUNIT_ASSERT(s);
CPPUNIT_ASSERT_EQUAL(allNames[i], s->s());
}
}
} // namespace rpc
} // namespace aria2