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

游戏引擎

开发平台:

C++ Builder

  1. /** 
  2.  * @file llhttpnode.h
  3.  * @brief Declaration 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. #ifndef LL_LLHTTPNODE_H
  33. #define LL_LLHTTPNODE_H
  34. #include "llpointer.h"
  35. #include "llrefcount.h"
  36. #include "llsd.h"
  37. class LLChainIOFactory;
  38. /**
  39.  * These classes represent the HTTP framework: The URL tree, and the LLSD
  40.  * REST interface that such nodes implement.
  41.  * 
  42.  * To implement a service, in most cases, subclass LLHTTPNode, implement
  43.  * get() or post(), and create a global instance of LLHTTPRegistration<>.
  44.  * This can all be done in a .cpp file, with no publically declared parts.
  45.  * 
  46.  * To implement a server see lliohttpserver.h
  47.  * @see LLHTTPWireServer
  48.  */
  49. /** 
  50.  * @class LLHTTPNode
  51.  * @brief Base class which handles url traversal, response routing
  52.  * and support for standard LLSD services
  53.  *
  54.  * Users of the HTTP responder will typically derive a class from this
  55.  * one, implement the get(), put() and/or post() methods, and then
  56.  * use LLHTTPRegistration to insert it into the URL tree.
  57.  *
  58.  * The default implementation handles servicing the request and creating
  59.  * the pipe fittings needed to read the headers, manage them, convert
  60.  * to and from LLSD, etc.
  61.  */
  62. class LLHTTPNode
  63. {
  64. public:
  65. LLHTTPNode();
  66. virtual ~LLHTTPNode();
  67. /** @name Responses
  68. Most subclasses override one or more of these methods to provide
  69. the service.  By default, the rest of the LLHTTPNode architecture
  70. will handle requests, create the needed LLIOPump, parse the input
  71. to LLSD, and format the LLSD result to the output.
  72. The default implementation of each of these is to call
  73. response->methodNotAllowed();  The "simple" versions can be
  74. overridden instead in those cases where the service can return
  75. an immediately computed response.
  76. */
  77. //@{
  78. public:
  79. virtual LLSD simpleGet() const;
  80. virtual LLSD simplePut(const LLSD& input) const;
  81. virtual LLSD simplePost(const LLSD& input) const;
  82. virtual LLSD simpleDel(const LLSD& context) const;
  83. /**
  84. * @brief Abstract Base Class declaring Response interface.
  85. */
  86. class Response : public LLRefCount
  87. {
  88. protected:
  89. virtual ~Response();
  90. public:
  91. /**
  92. * @brief Return the LLSD content and a 200 OK.
  93. */
  94. virtual void result(const LLSD&) = 0;
  95. /**
  96.  * @brief return status code and message with headers.
  97.  */
  98. virtual void extendedResult(S32 code, const std::string& message, const LLSD& headers) = 0;
  99. /**
  100.  * @brief return status code and reason string on http header,
  101.  * but do not return a payload.
  102.  */
  103. virtual void status(S32 code, const std::string& message) = 0;
  104. /**
  105. * @brief Return no body, just status code and 'UNKNOWN ERROR'.
  106. */
  107. virtual void statusUnknownError(S32 code);
  108. virtual void notFound(const std::string& message);
  109. virtual void notFound();
  110. virtual void methodNotAllowed();
  111. /**
  112. * @breif Add a name: value http header.
  113. *
  114. * No effort is made to ensure the response is a valid http
  115. * header.
  116. * The headers are stored as a map of header name : value.
  117. * Though HTTP allows the same header name to be transmitted
  118. * more than once, this implementation only stores a header
  119. * name once.
  120. * @param name The name of the header, eg, "Content-Encoding"
  121. * @param value The value of the header, eg, "gzip"
  122. */
  123. virtual void addHeader(const std::string& name, const std::string& value);
  124. protected:
  125. /**
  126. * @brief Headers to be sent back with the HTTP response.
  127. *
  128. * Protected class membership since derived classes are
  129. * expected to use it and there is no use case yet for other
  130. * uses. If such a use case arises, I suggest making a
  131. * headers() public method, and moving this member data into
  132. * private.
  133. */
  134. LLSD mHeaders;
  135. };
  136. typedef LLPointer<Response> ResponsePtr;
  137. virtual void get(ResponsePtr, const LLSD& context) const;
  138. virtual void put(
  139. ResponsePtr,
  140. const LLSD& context,
  141. const LLSD& input) const;
  142. virtual void post(
  143. ResponsePtr,
  144. const LLSD& context,
  145. const LLSD& input) const;
  146. virtual void del(ResponsePtr, const LLSD& context) const;
  147. virtual void options(ResponsePtr, const LLSD& context) const;
  148. //@}
  149. /** @name URL traversal
  150.  The tree is traversed by calling getChild() with successive
  151.  path components, on successive results.  When getChild() returns
  152.  null, or there are no more components, the last child responds to
  153.  the request.
  154.  
  155.  The default behavior is generally correct, though wildcard nodes
  156.  will want to implement validate().
  157. */
  158. //@{
  159. public:
  160. virtual LLHTTPNode* getChild(const std::string& name, LLSD& context) const;
  161. /**< returns a child node, if any, at the given name
  162.  default looks at children and wildcard child (see below)
  163. */
  164. virtual bool handles(const LLSD& remainder, LLSD& context) const;
  165. /**< return true if this node can service the remaining components;
  166.  default returns true if there are no remaining components
  167. */
  168. virtual bool validate(const std::string& name, LLSD& context) const;
  169. /**< called only on wildcard nodes, to check if they will handle
  170.  the name; default is false;  overrides will want to check
  171.  name, and return true if the name will construct to a valid url.
  172.  For convenience, the <code>getChild()</code> method above will
  173.  automatically insert the name in
  174.  context["request"]["wildcard"][key] if this method returns true.
  175.  For example, the node "agent/<agent_id>/detail" will set
  176.  context["request"]["wildcard"]["agent_id"] eqaul to the value 
  177.  found during traversal.
  178. */
  179. const LLHTTPNode* traverse(const std::string& path, LLSD& context) const;
  180. /**< find a node, if any, that can service this path
  181.  set up context["request"] information 
  182.   */
  183.   //@}
  184.  
  185. /** @name Child Nodes
  186.  The standard node can have any number of child nodes under
  187.  fixed names, and optionally one "wildcard" node that can
  188.  handle all other names.
  189.  
  190.  Usually, child nodes are add through LLHTTPRegistration, not
  191.  by calling this interface directly.
  192.  
  193.  The added node will be now owned by the parent node.
  194. */
  195. //@{
  196. virtual void addNode(const std::string& path, LLHTTPNode* nodeToAdd);
  197. LLSD allNodePaths() const;
  198. ///< Returns an arrary of node paths at and under this node
  199. const LLHTTPNode* rootNode() const;
  200. const LLHTTPNode* findNode(const std::string& name) const;
  201. enum EHTTPNodeContentType
  202. {
  203. CONTENT_TYPE_LLSD,
  204. CONTENT_TYPE_TEXT
  205. };
  206. virtual EHTTPNodeContentType getContentType() const { return CONTENT_TYPE_LLSD; }
  207. //@}
  208. /* @name Description system
  209. The Description object contains information about a service.
  210. All subclasses of LLHTTPNode should override describe() and use
  211. the methods of the Description class to set the various properties.
  212.  */
  213. //@{
  214. class Description
  215. {
  216. public:
  217. void shortInfo(const std::string& s){ mInfo["description"] = s; }
  218. void longInfo(const std::string& s) { mInfo["details"] = s; }
  219. // Call this method when the service supports the specified verb.
  220. void getAPI() { mInfo["api"].append("GET"); }
  221. void putAPI() { mInfo["api"].append("PUT");  }
  222. void postAPI() { mInfo["api"].append("POST"); }
  223. void delAPI() { mInfo["api"].append("DELETE"); }
  224. void input(const std::string& s) { mInfo["input"] = s; }
  225. void output(const std::string& s) { mInfo["output"] = s; }
  226. void source(const char* f, int l) { mInfo["__file__"] = f;
  227.   mInfo["__line__"] = l; }
  228. LLSD getInfo() const { return mInfo; }
  229. private:
  230. LLSD mInfo;
  231. };
  232. virtual void describe(Description&) const;
  233. //@}
  234. virtual const LLChainIOFactory* getProtocolHandler() const;
  235. /**< Return a factory object for handling wire protocols.
  236.  *   The base class returns NULL, as it doesn't know about
  237.  *   wire protocols at all.  This is okay for most nodes
  238.  *   as LLIOHTTPServer is smart enough to use a default
  239.  *   wire protocol for HTTP for such nodes.  Specialized
  240.  *   subclasses that handle things like XML-RPC will want
  241.  *   to implement this.  (See LLXMLSDRPCServerFactory.)
  242.  */
  243. private:
  244. class Impl;
  245. Impl& impl;
  246. };
  247. class LLSimpleResponse : public LLHTTPNode::Response
  248. {
  249. public:
  250. static LLPointer<LLSimpleResponse> create();
  251. void result(const LLSD& result);
  252. void extendedResult(S32 code, const std::string& body, const LLSD& headers);
  253. void status(S32 code, const std::string& message);
  254. void print(std::ostream& out) const;
  255. S32 mCode;
  256. std::string mMessage;
  257. protected:
  258. ~LLSimpleResponse();
  259. private:
  260.         LLSimpleResponse() : mCode(0) {} // Must be accessed through LLPointer.
  261. };
  262. std::ostream& operator<<(std::ostream& out, const LLSimpleResponse& resp);
  263. /** 
  264.  * @name Automatic LLHTTPNode registration 
  265.  *
  266.  * To register a node type at a particular url path, construct a global instance
  267.  * of LLHTTPRegistration:
  268.  *
  269.  * LLHTTPRegistration<LLMyNodeType> gHTTPServiceAlphaBeta("/alpha/beta");
  270.  *
  271.  * (Note the naming convention carefully.)  This object must be global and not
  272.  * static.  However, it needn't be declared in your .h file.  It can exist
  273.  * solely in the .cpp file.  The same is true of your subclass of LLHTTPNode:
  274.  * it can be declared and defined wholly within the .cpp file.
  275.  *
  276.  * When constructing a web server, use LLHTTPRegistrar to add all the registered
  277.  * nodes to the url tree:
  278.  *
  279.  * LLHTTPRegistrar::buidlAllServices(mRootNode);
  280.  */
  281. //@{
  282. class LLHTTPRegistrar
  283. {
  284. public:
  285. class NodeFactory
  286. {
  287. public:
  288. virtual ~NodeFactory();
  289. virtual LLHTTPNode* build() const = 0;
  290. };
  291. static void buildAllServices(LLHTTPNode& root);
  292. static void registerFactory(const std::string& path, NodeFactory& factory);
  293. ///< construct an LLHTTPRegistration below to call this
  294. };
  295. template < class NodeType >
  296. class LLHTTPRegistration
  297. {
  298. public:
  299. LLHTTPRegistration(const std::string& path)
  300. {
  301. LLHTTPRegistrar::registerFactory(path, mFactory);
  302. }
  303. private:
  304. class ThisNodeFactory : public LLHTTPRegistrar::NodeFactory
  305. {
  306. public:
  307. virtual LLHTTPNode* build() const { return new NodeType; }
  308. };
  309. ThisNodeFactory mFactory;
  310. };
  311. template < class NodeType>
  312. class LLHTTPParamRegistration
  313. {
  314. public:
  315. LLHTTPParamRegistration(const std::string& path, LLSD params) :
  316. mFactory(params)
  317. {
  318. LLHTTPRegistrar::registerFactory(path, mFactory);
  319. }
  320. private:
  321. class ThisNodeFactory : public LLHTTPRegistrar::NodeFactory
  322. {
  323. public:
  324. ThisNodeFactory(LLSD params) : mParams(params) {}
  325. virtual LLHTTPNode* build() const { return new NodeType(mParams); }
  326. private:
  327. LLSD mParams;
  328. };
  329. ThisNodeFactory mFactory;
  330. };
  331. //@}
  332. #endif // LL_LLHTTPNODE_H