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` interface. Therefore it is recommended to prefer Batch or `system.multicall`
requests when appropriate. 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 Methods
~~~~~~~ ~~~~~~~
@ -3429,6 +3433,36 @@ For information on the *secret* parameter, see :ref:`rpc_auth`.
>>> tuple(r) >>> tuple(r)
('2089b05ecca3d829', 'd2703803b52216d1') ('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 Error Handling
~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~

View File

@ -49,6 +49,30 @@ namespace {
std::unique_ptr<RpcMethod> noSuchRpcMethod; std::unique_ptr<RpcMethod> noSuchRpcMethod;
} // namespace } // 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 { namespace {
std::unique_ptr<RpcMethod> createMethod(const std::string& methodName) 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>(); return make_unique<SystemMulticallRpcMethod>();
} }
if (methodName == SystemListMethodsRpcMethod::getMethodName()) {
return make_unique<SystemListMethodsRpcMethod>();
}
return nullptr; return nullptr;
} }
} // namespace } // namespace

View File

@ -39,6 +39,7 @@
#include <string> #include <string>
#include <memory> #include <memory>
#include <vector>
namespace aria2 { namespace aria2 {
@ -46,6 +47,8 @@ namespace rpc {
class RpcMethod; class RpcMethod;
const std::vector<std::string>& allMethodNames();
RpcMethod* getMethod(const std::string& methodName); RpcMethod* getMethod(const std::string& methodName);
} // namespace rpc } // 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 std::unique_ptr<ValueBase> NoSuchMethodRpcMethod::process
(const RpcRequest& req, DownloadEngine* e) (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 { class NoSuchMethodRpcMethod:public RpcMethod {
protected: protected:
virtual std::unique_ptr<ValueBase> process virtual std::unique_ptr<ValueBase> process

View File

@ -20,6 +20,7 @@
#include "array_fun.h" #include "array_fun.h"
#include "download_helper.h" #include "download_helper.h"
#include "FileEntry.h" #include "FileEntry.h"
#include "RpcMethodFactory.h"
#ifdef ENABLE_BITTORRENT #ifdef ENABLE_BITTORRENT
# include "BtRegistry.h" # include "BtRegistry.h"
# include "BtRuntime.h" # include "BtRuntime.h"
@ -78,6 +79,7 @@ class RpcMethodTest:public CppUnit::TestFixture {
CPPUNIT_TEST(testPause); CPPUNIT_TEST(testPause);
CPPUNIT_TEST(testSystemMulticall); CPPUNIT_TEST(testSystemMulticall);
CPPUNIT_TEST(testSystemMulticall_fail); CPPUNIT_TEST(testSystemMulticall_fail);
CPPUNIT_TEST(testSystemListMethods);
CPPUNIT_TEST_SUITE_END(); CPPUNIT_TEST_SUITE_END();
private: private:
std::shared_ptr<DownloadEngine> e_; std::shared_ptr<DownloadEngine> e_;
@ -142,6 +144,7 @@ public:
void testPause(); void testPause();
void testSystemMulticall(); void testSystemMulticall();
void testSystemMulticall_fail(); void testSystemMulticall_fail();
void testSystemListMethods();
}; };
@ -1363,6 +1366,24 @@ void RpcMethodTest::testSystemMulticall_fail()
CPPUNIT_ASSERT_EQUAL(1, res.code); 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 rpc
} // namespace aria2 } // namespace aria2