diff options
author | Jacek Antonelli | 2008-08-15 23:44:46 -0500 |
---|---|---|
committer | Jacek Antonelli | 2008-08-15 23:44:46 -0500 |
commit | 38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4 (patch) | |
tree | adca584755d22ca041a2dbfc35d4eca01f70b32c /linden/indra/llmessage/llhttpnode.h | |
parent | README.txt (diff) | |
download | meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.zip meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.gz meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.bz2 meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.xz |
Second Life viewer sources 1.13.2.12
Diffstat (limited to 'linden/indra/llmessage/llhttpnode.h')
-rw-r--r-- | linden/indra/llmessage/llhttpnode.h | 325 |
1 files changed, 325 insertions, 0 deletions
diff --git a/linden/indra/llmessage/llhttpnode.h b/linden/indra/llmessage/llhttpnode.h new file mode 100644 index 0000000..bbce091 --- /dev/null +++ b/linden/indra/llmessage/llhttpnode.h | |||
@@ -0,0 +1,325 @@ | |||
1 | /** | ||
2 | * @file llhttpnode.h | ||
3 | * @brief Declaration of classes for generic HTTP/LSL/REST handling. | ||
4 | * | ||
5 | * Copyright (c) 2006-2007, Linden Research, Inc. | ||
6 | * | ||
7 | * The source code in this file ("Source Code") is provided by Linden Lab | ||
8 | * to you under the terms of the GNU General Public License, version 2.0 | ||
9 | * ("GPL"), unless you have obtained a separate licensing agreement | ||
10 | * ("Other License"), formally executed by you and Linden Lab. Terms of | ||
11 | * the GPL can be found in doc/GPL-license.txt in this distribution, or | ||
12 | * online at http://secondlife.com/developers/opensource/gplv2 | ||
13 | * | ||
14 | * There are special exceptions to the terms and conditions of the GPL as | ||
15 | * it is applied to this Source Code. View the full text of the exception | ||
16 | * in the file doc/FLOSS-exception.txt in this software distribution, or | ||
17 | * online at http://secondlife.com/developers/opensource/flossexception | ||
18 | * | ||
19 | * By copying, modifying or distributing this software, you acknowledge | ||
20 | * that you have read and understood your obligations described above, | ||
21 | * and agree to abide by those obligations. | ||
22 | * | ||
23 | * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO | ||
24 | * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, | ||
25 | * COMPLETENESS OR PERFORMANCE. | ||
26 | */ | ||
27 | |||
28 | #ifndef LL_LLHTTPNODE_H | ||
29 | #define LL_LLHTTPNODE_H | ||
30 | |||
31 | #include "llmemory.h" | ||
32 | #include "llsd.h" | ||
33 | |||
34 | class LLChainIOFactory; | ||
35 | |||
36 | |||
37 | /** | ||
38 | * These classes represent the HTTP framework: The URL tree, and the LLSD | ||
39 | * REST interface that such nodes implement. | ||
40 | * | ||
41 | * To implement a service, in most cases, subclass LLHTTPNode, implement | ||
42 | * get() or post(), and create a global instance of LLHTTPRegistration<>. | ||
43 | * This can all be done in a .cpp file, with no publically declared parts. | ||
44 | * | ||
45 | * To implement a server see lliohttpserver.h | ||
46 | * @see LLHTTPWireServer | ||
47 | */ | ||
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 | |||
68 | /** @name Responses | ||
69 | Most subclasses override one or more of these methods to provide | ||
70 | the service. By default, the rest of the LLHTTPNode architecture | ||
71 | will handle requests, create the needed LLIOPump, parse the input | ||
72 | to LLSD, and format the LLSD result to the output. | ||
73 | |||
74 | The default implementation of each of these is to call | ||
75 | response->methodNotAllowed(); The "simple" versions can be | ||
76 | overridden instead in those cases where the service can return | ||
77 | an immediately computed response. | ||
78 | */ | ||
79 | //@{ | ||
80 | public: | ||
81 | virtual LLSD get() const; | ||
82 | virtual LLSD put(const LLSD& input) const; | ||
83 | virtual LLSD post(const LLSD& input) const; | ||
84 | |||
85 | virtual LLSD del() const; | ||
86 | virtual LLSD del(const LLSD& context) const; | ||
87 | |||
88 | class Response : public LLRefCount | ||
89 | { | ||
90 | public: | ||
91 | virtual ~Response(); | ||
92 | |||
93 | virtual void result(const LLSD&) = 0; | ||
94 | virtual void status(S32 code, const std::string& message) = 0; | ||
95 | |||
96 | void status(S32 code); | ||
97 | void notFound(const std::string& message); | ||
98 | void notFound(); | ||
99 | void methodNotAllowed(); | ||
100 | }; | ||
101 | |||
102 | typedef LLPointer<Response> ResponsePtr; | ||
103 | |||
104 | virtual void get(ResponsePtr, const LLSD& context) const; | ||
105 | virtual void put(ResponsePtr, const LLSD& context, const LLSD& input) const; | ||
106 | virtual void post(ResponsePtr, const LLSD& context, const LLSD& input) const; | ||
107 | virtual void del(ResponsePtr, const LLSD& context) const; | ||
108 | //@} | ||
109 | |||
110 | |||
111 | /** @name URL traversal | ||
112 | The tree is traversed by calling getChild() with successive | ||
113 | path components, on successive results. When getChild() returns | ||
114 | null, or there are no more components, the last child responds to | ||
115 | the request. | ||
116 | |||
117 | The default behavior is generally correct, though wildcard nodes | ||
118 | will want to implement validate(). | ||
119 | */ | ||
120 | //@{ | ||
121 | public: | ||
122 | virtual LLHTTPNode* getChild(const std::string& name, LLSD& context) const; | ||
123 | /**< returns a child node, if any, at the given name | ||
124 | default looks at children and wildcard child (see below) | ||
125 | */ | ||
126 | |||
127 | virtual bool handles(const LLSD& remainder, LLSD& context) const; | ||
128 | /**< return true if this node can service the remaining components; | ||
129 | default returns true if there are no remaining components | ||
130 | */ | ||
131 | |||
132 | virtual bool validate(const std::string& name, LLSD& context) const; | ||
133 | /**< called only on wildcard nodes, to check if they will handle | ||
134 | the name; default is false; overrides will want to check | ||
135 | name, and return true if the name will construct to a valid url. | ||
136 | For convenience, the <code>getChild()</code> method above will | ||
137 | automatically insert the name in | ||
138 | context["request"]["wildcard"][key] if this method returns true. | ||
139 | For example, the node "agent/<agent_id>/detail" will set | ||
140 | context["request"]["wildcard"]["agent_id"] eqaul to the value | ||
141 | found during traversal. | ||
142 | */ | ||
143 | |||
144 | const LLHTTPNode* traverse(const std::string& path, LLSD& context) const; | ||
145 | /**< find a node, if any, that can service this path | ||
146 | set up context["request"] information | ||
147 | */ | ||
148 | //@} | ||
149 | |||
150 | /** @name Child Nodes | ||
151 | The standard node can have any number of child nodes under | ||
152 | fixed names, and optionally one "wildcard" node that can | ||
153 | handle all other names. | ||
154 | |||
155 | Usually, child nodes are add through LLHTTPRegistration, not | ||
156 | by calling this interface directly. | ||
157 | |||
158 | The added node will be now owned by the parent node. | ||
159 | */ | ||
160 | //@{ | ||
161 | |||
162 | virtual void addNode(const std::string& path, LLHTTPNode* nodeToAdd); | ||
163 | |||
164 | LLSD allNodePaths() const; | ||
165 | ///< Returns an arrary of node paths at and under this node | ||
166 | |||
167 | const LLHTTPNode* rootNode() const; | ||
168 | const LLHTTPNode* findNode(const std::string& name) const; | ||
169 | |||
170 | //@} | ||
171 | |||
172 | /* @name Description system | ||
173 | The Description object contains information about a service. | ||
174 | All subclasses of LLHTTPNode should override description() and use | ||
175 | the methods of the Description class to set the various properties. | ||
176 | */ | ||
177 | //@{ | ||
178 | class Description | ||
179 | { | ||
180 | public: | ||
181 | void shortInfo(const std::string& s){ mInfo["description"] = s; } | ||
182 | void longInfo(const std::string& s) { mInfo["details"] = s; } | ||
183 | |||
184 | // Call this method when the service supports the specified verb. | ||
185 | void getAPI() { mInfo["api"].append("GET"); } | ||
186 | void putAPI() { mInfo["api"].append("PUT"); } | ||
187 | void postAPI() { mInfo["api"].append("POST"); } | ||
188 | void delAPI() { mInfo["api"].append("DELETE"); } | ||
189 | |||
190 | void input(const std::string& s) { mInfo["input"] = s; } | ||
191 | void output(const std::string& s) { mInfo["output"] = s; } | ||
192 | void source(const char* f, int l) { mInfo["__file__"] = f; | ||
193 | mInfo["__line__"] = l; } | ||
194 | |||
195 | LLSD getInfo() const { return mInfo; } | ||
196 | |||
197 | private: | ||
198 | LLSD mInfo; | ||
199 | }; | ||
200 | |||
201 | virtual void describe(Description&) const; | ||
202 | |||
203 | //@} | ||
204 | |||
205 | |||
206 | virtual const LLChainIOFactory* getProtocolHandler() const; | ||
207 | /**< Return a factory object for handling wire protocols. | ||
208 | * The base class returns NULL, as it doesn't know about | ||
209 | * wire protocols at all. This is okay for most nodes | ||
210 | * as LLIOHTTPServer is smart enough to use a default | ||
211 | * wire protocol for HTTP for such nodes. Specialized | ||
212 | * subclasses that handle things like XML-RPC will want | ||
213 | * to implement this. (See LLXMLSDRPCServerFactory.) | ||
214 | */ | ||
215 | |||
216 | private: | ||
217 | class Impl; | ||
218 | Impl& impl; | ||
219 | }; | ||
220 | |||
221 | |||
222 | |||
223 | class LLSimpleResponse : public LLHTTPNode::Response | ||
224 | { | ||
225 | public: | ||
226 | static LLPointer<LLSimpleResponse> create(); | ||
227 | ~LLSimpleResponse(); | ||
228 | |||
229 | void result(const LLSD& result); | ||
230 | void status(S32 code, const std::string& message); | ||
231 | |||
232 | void print(std::ostream& out) const; | ||
233 | |||
234 | S32 mCode; | ||
235 | std::string mMessage; | ||
236 | |||
237 | private: | ||
238 | LLSimpleResponse() {;} // Must be accessed through LLPointer. | ||
239 | }; | ||
240 | |||
241 | std::ostream& operator<<(std::ostream& out, const LLSimpleResponse& resp); | ||
242 | |||
243 | |||
244 | |||
245 | /** | ||
246 | * @name Automatic LLHTTPNode registration | ||
247 | * | ||
248 | * To register a node type at a particular url path, construct a global instance | ||
249 | * of LLHTTPRegistration: | ||
250 | * | ||
251 | * LLHTTPRegistration<LLMyNodeType> gHTTPServiceAlphaBeta("/alpha/beta"); | ||
252 | * | ||
253 | * (Note the naming convention carefully.) This object must be global and not | ||
254 | * static. However, it needn't be declared in your .h file. It can exist | ||
255 | * solely in the .cpp file. The same is true of your subclass of LLHTTPNode: | ||
256 | * it can be declared and defined wholly within the .cpp file. | ||
257 | * | ||
258 | * When constructing a web server, use LLHTTPRegistrar to add all the registered | ||
259 | * nodes to the url tree: | ||
260 | * | ||
261 | * LLHTTPRegistrar::buidlAllServices(mRootNode); | ||
262 | */ | ||
263 | //@{ | ||
264 | |||
265 | class LLHTTPRegistrar | ||
266 | { | ||
267 | public: | ||
268 | class NodeFactory | ||
269 | { | ||
270 | public: | ||
271 | virtual ~NodeFactory(); | ||
272 | virtual LLHTTPNode* build() const = 0; | ||
273 | }; | ||
274 | |||
275 | static void buildAllServices(LLHTTPNode& root); | ||
276 | |||
277 | static void registerFactory(const std::string& path, NodeFactory& factory); | ||
278 | ///< construct an LLHTTPRegistration below to call this | ||
279 | }; | ||
280 | |||
281 | template < class NodeType > | ||
282 | class LLHTTPRegistration | ||
283 | { | ||
284 | public: | ||
285 | LLHTTPRegistration(const std::string& path) | ||
286 | { | ||
287 | LLHTTPRegistrar::registerFactory(path, mFactory); | ||
288 | } | ||
289 | |||
290 | private: | ||
291 | class ThisNodeFactory : public LLHTTPRegistrar::NodeFactory | ||
292 | { | ||
293 | public: | ||
294 | virtual LLHTTPNode* build() const { return new NodeType; } | ||
295 | }; | ||
296 | |||
297 | ThisNodeFactory mFactory; | ||
298 | }; | ||
299 | |||
300 | template < class NodeType> | ||
301 | class LLHTTPParamRegistration | ||
302 | { | ||
303 | public: | ||
304 | LLHTTPParamRegistration(const std::string& path, LLSD params) : | ||
305 | mFactory(params) | ||
306 | { | ||
307 | LLHTTPRegistrar::registerFactory(path, mFactory); | ||
308 | } | ||
309 | |||
310 | private: | ||
311 | class ThisNodeFactory : public LLHTTPRegistrar::NodeFactory | ||
312 | { | ||
313 | public: | ||
314 | ThisNodeFactory(LLSD params) : mParams(params) {} | ||
315 | virtual LLHTTPNode* build() const { return new NodeType(mParams); } | ||
316 | private: | ||
317 | LLSD mParams; | ||
318 | }; | ||
319 | |||
320 | ThisNodeFactory mFactory; | ||
321 | }; | ||
322 | |||
323 | //@} | ||
324 | |||
325 | #endif // LL_LLHTTPNODE_H | ||