]> git.mxchange.org Git - simgear.git/blob - simgear/io/HTTPRequest.hxx
Optional use libCurl as the HTTP client.
[simgear.git] / simgear / io / HTTPRequest.hxx
1 ///@file
2 //
3 // Copyright (C) 2011  James Turner <zakalawe@mac.com>
4 // Copyright (C) 2013  Thomas Geymayer <tomgey@gmail.com>
5 //
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Library General Public
8 // License as published by the Free Software Foundation; either
9 // version 2 of the License, or (at your option) any later version.
10 //
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 // Library General Public License for more details.
15 //
16 // You should have received a copy of the GNU Library General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA
19
20 #ifndef SG_HTTP_REQUEST_HXX
21 #define SG_HTTP_REQUEST_HXX
22
23 #include <map>
24
25 #include <simgear/structure/function_list.hxx>
26 #include <simgear/structure/map.hxx>
27 #include <simgear/structure/SGReferenced.hxx>
28 #include <simgear/structure/SGSharedPtr.hxx>
29 #include <simgear/math/sg_types.hxx>
30
31 #include <boost/bind.hpp>
32
33 class SGPropertyNode;
34
35 namespace simgear
36 {
37 namespace HTTP
38 {
39
40 /**
41  * Base class for HTTP request (and answer).
42  */
43 class Request:
44   public SGReferenced
45 {
46 public:
47     typedef boost::function<void(Request*)> Callback;
48
49     enum ReadyState
50     {
51       UNSENT = 0,
52       OPENED,
53       STATUS_RECEIVED,
54       HEADERS_RECEIVED,
55       LOADING,
56       DONE,
57       FAILED
58     };
59
60     virtual ~Request();
61
62     /**
63      *
64      */
65     StringMap& requestHeaders()             { return _request_headers; }
66     const StringMap& requestHeaders() const { return _request_headers; }
67     std::string& requestHeader(const std::string& key)
68                                             { return _request_headers[key]; }
69     const std::string requestHeader(const std::string& key) const
70                                             { return _request_headers.get(key); }
71
72     /**
73      * Add a handler to be called when the request successfully completes.
74      *
75      * @note If the request is already complete, the handler is called
76      *       immediately.
77      */
78     Request* done(const Callback& cb);
79
80     template<class C>
81     Request* done(C* instance, void (C::*mem_func)(Request*))
82     {
83       return done(boost::bind(mem_func, instance, _1));
84     }
85
86     /**
87      * Add a handler to be called when the request completes or aborts with an
88      * error.
89      *
90      * @note If the request has already failed, the handler is called
91      *       immediately.
92      */
93     Request* fail(const Callback& cb);
94
95     template<class C>
96     Request* fail(C* instance, void (C::*mem_func)(Request*))
97     {
98       return fail(boost::bind(mem_func, instance, _1));
99     }
100
101     /**
102      * Add a handler to be called when the request either successfully completes
103      * or fails.
104      *
105      * @note If the request is already complete or has already failed, the
106      *       handler is called immediately.
107      */
108     Request* always(const Callback& cb);
109
110     template<class C>
111     Request* always(C* instance, void (C::*mem_func)(Request*))
112     {
113       return always(boost::bind(mem_func, instance, _1));
114     }
115
116     /**
117      * Set the data for the body of the request. The request is automatically
118      * send using the POST method.
119      *
120      * @param data  Body data
121      * @param type  Media Type (aka MIME) of the body data
122      */
123     void setBodyData( const std::string& data,
124                       const std::string& type = "text/plain" );
125     void setBodyData( const SGPropertyNode* data );
126
127     virtual void setUrl(const std::string& url);
128
129     virtual std::string method() const
130         { return _method; }
131     virtual std::string url() const
132         { return _url; }
133
134     virtual std::string scheme() const;
135     virtual std::string path() const;
136     virtual std::string host() const;
137     virtual std::string hostAndPort() const;
138     virtual unsigned short port() const;
139     virtual std::string query() const;
140
141     StringMap const& responseHeaders() const
142         { return _responseHeaders; }
143
144     std::string responseMime() const;
145
146     virtual int responseCode() const
147         { return _responseStatus; }
148
149     virtual std::string responseReason() const
150         { return _responseReason; }
151
152     void setResponseLength(unsigned int l);
153     virtual unsigned int responseLength() const;
154
155     /**
156      * Check if request contains body data.
157      */
158     virtual bool hasBodyData() const;
159
160     /**
161      * Retrieve the request body content type.
162      */
163     virtual std::string bodyType() const;
164
165     /**
166      * Retrieve the size of the request body.
167      */
168     virtual size_t bodyLength() const;
169
170     /**
171      * Retrieve the body data bytes. Will be passed the maximum body bytes
172      * to return in the buffer, and must return the actual number
173      * of bytes written.
174      */
175     virtual size_t getBodyData(char* s, size_t offset, size_t max_count) const;
176
177     /**
178      * running total of body bytes received so far. Can be used
179      * to generate a completion percentage, if the response length is
180      * known.
181      */
182     unsigned int responseBytesReceived() const
183         { return _receivedBodyBytes; }
184
185     enum HTTPVersion {
186         HTTP_VERSION_UNKNOWN = 0,
187         HTTP_0_x, // 0.9 or similar
188         HTTP_1_0,
189         HTTP_1_1
190     };
191
192     HTTPVersion responseVersion() const
193         { return _responseVersion; }
194
195     ReadyState readyState() const { return _ready_state; }
196
197     /**
198      * Request aborting this request.
199      */
200     void abort();
201
202     /**
203      * Request aborting this request and specify the reported reaseon for it.
204      */
205     void abort(const std::string& reason);
206
207     bool closeAfterComplete() const;
208     bool isComplete() const;
209
210 protected:
211     Request(const std::string& url, const std::string method = "GET");
212
213     virtual void requestStart();
214     virtual void responseStart(const std::string& r);
215     virtual void responseHeader(const std::string& key, const std::string& value);
216     virtual void responseHeadersComplete();
217     virtual void responseComplete();
218     virtual void gotBodyData(const char* s, int n);
219
220     virtual void onDone();
221     virtual void onFail();
222     virtual void onAlways();
223
224     void setFailure(int code, const std::string& reason);
225
226 private:
227     friend class Client;
228     friend class Connection;
229     friend class ContentDecoder;
230
231     Request(const Request&); // = delete;
232     Request& operator=(const Request&); // = delete;
233
234     void processBodyBytes(const char* s, int n);
235     void setReadyState(ReadyState state);
236
237     std::string   _method;
238     std::string   _url;
239     StringMap     _request_headers;
240     std::string   _request_data;
241     std::string   _request_media_type;
242
243     HTTPVersion   _responseVersion;
244     int           _responseStatus;
245     std::string   _responseReason;
246     StringMap     _responseHeaders;
247     unsigned int  _responseLength;
248     unsigned int  _receivedBodyBytes;
249
250     function_list<Callback> _cb_done,
251                             _cb_fail,
252                             _cb_always;
253
254     ReadyState    _ready_state;
255     bool          _willClose;
256 };
257
258 typedef SGSharedPtr<Request> Request_ptr;
259
260 } // of namespace HTTP
261 } // of namespace simgear
262
263 #endif // of SG_HTTP_REQUEST_HXX