llhttpnode.cpp
上传用户:king477883
上传日期:2021-03-01
资源大小:9553k
文件大小:10k
源码类别:

游戏引擎

开发平台:

C++ Builder

  1. /** 
  2.  * @file llhttpnode.cpp
  3.  * @brief Implementation of classes for generic HTTP/LSL/REST handling.
  4.  *
  5.  * $LicenseInfo:firstyear=2006&license=viewergpl$
  6.  * 
  7.  * Copyright (c) 2006-2010, Linden Research, Inc.
  8.  * 
  9.  * Second Life Viewer Source Code
  10.  * The source code in this file ("Source Code") is provided by Linden Lab
  11.  * to you under the terms of the GNU General Public License, version 2.0
  12.  * ("GPL"), unless you have obtained a separate licensing agreement
  13.  * ("Other License"), formally executed by you and Linden Lab.  Terms of
  14.  * the GPL can be found in doc/GPL-license.txt in this distribution, or
  15.  * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  16.  * 
  17.  * There are special exceptions to the terms and conditions of the GPL as
  18.  * it is applied to this Source Code. View the full text of the exception
  19.  * in the file doc/FLOSS-exception.txt in this software distribution, or
  20.  * online at
  21.  * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  22.  * 
  23.  * By copying, modifying or distributing this software, you acknowledge
  24.  * that you have read and understood your obligations described above,
  25.  * and agree to abide by those obligations.
  26.  * 
  27.  * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  28.  * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  29.  * COMPLETENESS OR PERFORMANCE.
  30.  * $/LicenseInfo$
  31.  */
  32. #include "linden_common.h"
  33. #include "llhttpnode.h"
  34. #include <boost/tokenizer.hpp>
  35. #include "llstl.h"
  36. #include "lliohttpserver.h" // for string constants
  37. static const std::string CONTEXT_WILDCARD("wildcard");
  38. /**
  39.  * LLHTTPNode
  40.  */
  41.  
  42. class LLHTTPNode::Impl
  43. {
  44. public:
  45. typedef std::map<std::string, LLHTTPNode*> ChildMap;
  46. ChildMap mNamedChildren;
  47. LLHTTPNode* mWildcardChild;
  48. std::string mWildcardName;
  49. std::string mWildcardKey;
  50. LLHTTPNode* mParentNode;
  51. Impl() : mWildcardChild(NULL), mParentNode(NULL) { }
  52. LLHTTPNode* findNamedChild(const std::string& name) const;
  53. };
  54. LLHTTPNode* LLHTTPNode::Impl::findNamedChild(const std::string& name) const
  55. {
  56. LLHTTPNode* child = get_ptr_in_map(mNamedChildren, name);
  57. if (!child  &&  ((name[0] == '*') || (name == mWildcardName)))
  58. {
  59. child = mWildcardChild;
  60. }
  61. return child;
  62. }
  63. LLHTTPNode::LLHTTPNode()
  64. : impl(* new Impl)
  65. {
  66. }
  67. // virtual
  68. LLHTTPNode::~LLHTTPNode()
  69. {
  70. std::for_each(impl.mNamedChildren.begin(), impl.mNamedChildren.end(),
  71. DeletePairedPointer());
  72. delete impl.mWildcardChild;
  73. delete &impl;
  74. }
  75. namespace {
  76. class NotImplemented
  77. {
  78. };
  79. }
  80. // virtual
  81. LLSD LLHTTPNode::simpleGet() const
  82. {
  83. throw NotImplemented();
  84. }
  85. // virtual
  86. LLSD LLHTTPNode::simplePut(const LLSD& input) const
  87. {
  88. throw NotImplemented();
  89. }
  90. // virtual
  91. LLSD LLHTTPNode::simplePost(const LLSD& input) const
  92. {
  93. throw NotImplemented();
  94. }
  95. // virtual
  96. void LLHTTPNode::get(LLHTTPNode::ResponsePtr response, const LLSD& context) const
  97. {
  98. try
  99. {
  100. response->result(simpleGet());
  101. }
  102. catch (NotImplemented)
  103. {
  104. response->methodNotAllowed();
  105. }
  106. }
  107. // virtual
  108. void LLHTTPNode::put(LLHTTPNode::ResponsePtr response, const LLSD& context, const LLSD& input) const
  109. {
  110. try
  111. {
  112. response->result(simplePut(input));
  113. }
  114. catch (NotImplemented)
  115. {
  116. response->methodNotAllowed();
  117. }
  118. }
  119. // virtual
  120. void LLHTTPNode::post(LLHTTPNode::ResponsePtr response, const LLSD& context, const LLSD& input) const
  121. {
  122. try
  123. {
  124. response->result(simplePost(input));
  125. }
  126. catch (NotImplemented)
  127. {
  128. response->methodNotAllowed();
  129. }
  130. }
  131. // virtual
  132. void LLHTTPNode::del(LLHTTPNode::ResponsePtr response, const LLSD& context) const
  133. {
  134.     try
  135.     {
  136. response->result(simpleDel(context));
  137.     }
  138.     catch (NotImplemented)
  139.     {
  140. response->methodNotAllowed();
  141.     }
  142. }
  143. // virtual
  144. LLSD LLHTTPNode::simpleDel(const LLSD&) const
  145. {
  146. throw NotImplemented();
  147. }
  148. // virtual
  149. void  LLHTTPNode::options(ResponsePtr response, const LLSD& context) const
  150. {
  151. //llinfos << "options context: " << context << llendl;
  152. // default implementation constructs an url to the documentation.
  153. std::string host(
  154. context[CONTEXT_REQUEST][CONTEXT_HEADERS]["host"].asString());
  155. if(host.empty())
  156. {
  157. response->status(400, "Bad Request -- need Host header");
  158. return;
  159. }
  160. std::ostringstream ostr;
  161. ostr << "http://" << host << "/web/server/api";
  162. ostr << context[CONTEXT_REQUEST]["path"].asString();
  163. static const std::string DOC_HEADER("X-Documentation-URL");
  164. response->addHeader(DOC_HEADER, ostr.str());
  165. response->status(200, "OK");
  166. }
  167. // virtual
  168. LLHTTPNode* LLHTTPNode::getChild(const std::string& name, LLSD& context) const
  169. {
  170. LLHTTPNode* namedChild = get_ptr_in_map(impl.mNamedChildren, name);
  171. if (namedChild)
  172. {
  173. return namedChild;
  174. }
  175. if (impl.mWildcardChild
  176. &&  impl.mWildcardChild->validate(name, context))
  177. {
  178. context[CONTEXT_REQUEST][CONTEXT_WILDCARD][impl.mWildcardKey] = name;
  179. return impl.mWildcardChild;
  180. }
  181. return NULL;
  182. }
  183. // virtual
  184. bool LLHTTPNode::handles(const LLSD& remainder, LLSD& context) const
  185. {
  186. return remainder.size() == 0;
  187. }
  188. // virtual
  189. bool LLHTTPNode::validate(const std::string& name, LLSD& context) const
  190. {
  191. return false;
  192. }
  193. const LLHTTPNode* LLHTTPNode::traverse(
  194. const std::string& path, LLSD& context) const
  195. {
  196. typedef boost::tokenizer< boost::char_separator<char> > tokenizer;
  197. boost::char_separator<char> sep("/", "", boost::drop_empty_tokens);
  198. tokenizer tokens(path, sep);
  199. tokenizer::iterator iter = tokens.begin();
  200. tokenizer::iterator end = tokens.end();
  201. const LLHTTPNode* node = this;
  202. for(; iter != end; ++iter)
  203. {
  204. LLHTTPNode* child = node->getChild(*iter, context);
  205. if(!child) 
  206. {
  207. lldebugs << "LLHTTPNode::traverse: Couldn't find '" << *iter << "'" << llendl;
  208. break; 
  209. }
  210. lldebugs << "LLHTTPNode::traverse: Found '" << *iter << "'" << llendl;
  211. node = child;
  212. }
  213. LLSD& remainder = context[CONTEXT_REQUEST]["remainder"];
  214. for(; iter != end; ++iter)
  215. {
  216. remainder.append(*iter);
  217. }
  218. return node->handles(remainder, context) ? node : NULL;
  219. }
  220. void LLHTTPNode::addNode(const std::string& path, LLHTTPNode* nodeToAdd)
  221. {
  222. typedef boost::tokenizer< boost::char_separator<char> > tokenizer;
  223. boost::char_separator<char> sep("/", "", boost::drop_empty_tokens);
  224. tokenizer tokens(path, sep);
  225. tokenizer::iterator iter = tokens.begin();
  226. tokenizer::iterator end = tokens.end();
  227. LLHTTPNode* node = this;
  228. for(; iter != end; ++iter)
  229. {
  230. LLHTTPNode* child = node->impl.findNamedChild(*iter);
  231. if (!child) { break; }
  232. node = child;
  233. }
  234. if (iter == end)
  235. {
  236. llwarns << "LLHTTPNode::addNode: already a node that handles "
  237. << path << llendl;
  238. return;
  239. }
  240. while (true)
  241. {
  242. std::string pathPart = *iter;
  243. ++iter;
  244. bool lastOne = iter == end;
  245. LLHTTPNode* nextNode = lastOne ? nodeToAdd : new LLHTTPNode();
  246. switch (pathPart[0])
  247. {
  248. case '<':
  249. // *NOTE: This should really validate that it is of
  250. // the proper form: <wildcardkey> so that the substr()
  251. // generates the correct key name.
  252. node->impl.mWildcardChild = nextNode;
  253. node->impl.mWildcardName = pathPart;
  254. if(node->impl.mWildcardKey.empty())
  255. {
  256. node->impl.mWildcardKey = pathPart.substr(
  257. 1,
  258. pathPart.size() - 2);
  259. }
  260. break;
  261. case '*':
  262. node->impl.mWildcardChild = nextNode;
  263. if(node->impl.mWildcardName.empty())
  264. {
  265. node->impl.mWildcardName = pathPart;
  266. }
  267. break;
  268. default:
  269. node->impl.mNamedChildren[pathPart] = nextNode;
  270. }
  271. nextNode->impl.mParentNode = node;
  272. if (lastOne) break;
  273. node = nextNode;
  274. }
  275. }
  276. static void append_node_paths(LLSD& result,
  277. const std::string& name, const LLHTTPNode* node)
  278. {
  279. result.append(name);
  280. LLSD paths = node->allNodePaths();
  281. LLSD::array_const_iterator i = paths.beginArray();
  282. LLSD::array_const_iterator end = paths.endArray();
  283. for (; i != end; ++i)
  284. {
  285. result.append(name + "/" + (*i).asString());
  286. }
  287. }
  288. LLSD LLHTTPNode::allNodePaths() const
  289. {
  290. LLSD result;
  291. Impl::ChildMap::const_iterator i = impl.mNamedChildren.begin();
  292. Impl::ChildMap::const_iterator end = impl.mNamedChildren.end();
  293. for (; i != end; ++i)
  294. {
  295. append_node_paths(result, i->first, i->second);
  296. }
  297. if (impl.mWildcardChild)
  298. {
  299. append_node_paths(result, impl.mWildcardName, impl.mWildcardChild);
  300. }
  301. return result;
  302. }
  303. const LLHTTPNode* LLHTTPNode::rootNode() const
  304. {
  305. const LLHTTPNode* node = this;
  306. while (true)
  307. {
  308. const LLHTTPNode* next = node->impl.mParentNode;
  309. if (!next)
  310. {
  311. return node;
  312. }
  313. node = next;
  314. }
  315. }
  316. const LLHTTPNode* LLHTTPNode::findNode(const std::string& name) const
  317. {
  318. return impl.findNamedChild(name);
  319. }
  320. LLHTTPNode::Response::~Response()
  321. {
  322. }
  323. void LLHTTPNode::Response::statusUnknownError(S32 code)
  324. {
  325. status(code, "Unknown Error");
  326. }
  327. void LLHTTPNode::Response::notFound(const std::string& message)
  328. {
  329. status(404, message);
  330. }
  331. void LLHTTPNode::Response::notFound()
  332. {
  333. status(404, "Not Found");
  334. }
  335. void LLHTTPNode::Response::methodNotAllowed()
  336. {
  337. status(405, "Method Not Allowed");
  338. }
  339. void LLHTTPNode::Response::addHeader(
  340. const std::string& name,
  341. const std::string& value)
  342. {
  343. mHeaders[name] = value;
  344. }
  345. void LLHTTPNode::describe(Description& desc) const
  346. {
  347. desc.shortInfo("unknown service (missing describe() method)");
  348. }
  349. const LLChainIOFactory* LLHTTPNode::getProtocolHandler() const
  350. {
  351. return NULL;
  352. }
  353. namespace
  354. {
  355.     typedef std::map<std::string, LLHTTPRegistrar::NodeFactory*>  FactoryMap;
  356.     
  357.     FactoryMap& factoryMap()
  358.     {
  359.         static FactoryMap theMap;
  360.         return theMap;
  361.     }
  362. }
  363. LLHTTPRegistrar::NodeFactory::~NodeFactory() { }
  364. void LLHTTPRegistrar::registerFactory(
  365.     const std::string& path, NodeFactory& factory)
  366. {
  367. factoryMap()[path] = &factory;
  368. }
  369. void LLHTTPRegistrar::buildAllServices(LLHTTPNode& root)
  370. {
  371.     const FactoryMap& map = factoryMap();
  372.     
  373.     FactoryMap::const_iterator i = map.begin();
  374.     FactoryMap::const_iterator end = map.end();
  375.     for (; i != end; ++i)
  376.     {
  377. LL_DEBUGS("AppInit") << "LLHTTPRegistrar::buildAllServices adding node for path "
  378. << i->first << LL_ENDL;
  379.         root.addNode(i->first, i->second->build());
  380.     }
  381. }
  382. LLPointer<LLSimpleResponse> LLSimpleResponse::create()
  383. {
  384. return new LLSimpleResponse();
  385. }
  386. LLSimpleResponse::~LLSimpleResponse()
  387. {
  388. }
  389. void LLSimpleResponse::result(const LLSD& result)
  390. {
  391. status(200, "OK");
  392. }
  393. void LLSimpleResponse::extendedResult(S32 code, const std::string& body, const LLSD& headers)
  394. {
  395. status(code,body);
  396. }
  397. void LLSimpleResponse::status(S32 code, const std::string& message)
  398. {
  399. mCode = code;
  400. mMessage = message;
  401. }
  402. void LLSimpleResponse::print(std::ostream& out) const
  403. {
  404. out << mCode << " " << mMessage;
  405. }
  406. std::ostream& operator<<(std::ostream& out, const LLSimpleResponse& resp)
  407. {
  408. resp.print(out);
  409. return out;
  410. }