]> git.mxchange.org Git - simgear.git/blob - simgear/io/HTTPRequest.hxx
Don't use object returned from vector::end()
[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 class Client;
41
42 /**
43  * Base class for HTTP request (and answer).
44  */
45 class Request:
46   public SGReferenced
47 {
48 public:
49     typedef boost::function<void(Request*)> Callback;
50
51     enum ReadyState
52     {
53       UNSENT = 0,
54       OPENED,
55       STATUS_RECEIVED,
56       HEADERS_RECEIVED,
57       LOADING,
58       DONE,
59       FAILED
60     };
61
62     virtual ~Request();
63
64     /**
65      *
66      */
67     StringMap& requestHeaders()             { return _request_headers; }
68     const StringMap& requestHeaders() const { return _request_headers; }
69     std::string& requestHeader(const std::string& key)
70                                             { return _request_headers[key]; }
71     const std::string requestHeader(const std::string& key) const
72                                             { return _request_headers.get(key); }
73
74     /**
75      * Add a handler to be called when the request successfully completes.
76      *
77      * @note If the request is already complete, the handler is called
78      *       immediately.
79      */
80     Request* done(const Callback& cb);
81
82     template<class C>
83     Request* done(C* instance, void (C::*mem_func)(Request*))
84     {
85       return done(boost::bind(mem_func, instance, _1));
86     }
87
88     /**
89      * Add a handler to be called when the request completes or aborts with an
90      * error.
91      *
92      * @note If the request has already failed, the handler is called
93      *       immediately.
94      */
95     Request* fail(const Callback& cb);
96
97     template<class C>
98     Request* fail(C* instance, void (C::*mem_func)(Request*))
99     {
100       return fail(boost::bind(mem_func, instance, _1));
101     }
102
103     /**
104      * Add a handler to be called when the request either successfully completes
105      * or fails.
106      *
107      * @note If the request is already complete or has already failed, the
108      *       handler is called immediately.
109      */
110     Request* always(const Callback& cb);
111
112     template<class C>
113     Request* always(C* instance, void (C::*mem_func)(Request*))
114     {
115       return always(boost::bind(mem_func, instance, _1));
116     }
117
118     /**
119      * Set the data for the body of the request. The request is automatically
120      * send using the POST method.
121      *
122      * @param data  Body data
123      * @param type  Media Type (aka MIME) of the body data
124      */
125     void setBodyData( const std::string& data,
126                       const std::string& type = "text/plain" );
127     void setBodyData( const SGPropertyNode* data );
128
129     virtual void setUrl(const std::string& url);
130
131     virtual std::string method() const
132         { return _method; }
133     virtual std::string url() const
134         { return _url; }
135
136     Client* http() const
137     { return _client; }
138
139     virtual std::string scheme() const;
140     virtual std::string path() const;
141     virtual std::string host() const;
142     virtual std::string hostAndPort() const;
143     virtual unsigned short port() const;
144     virtual std::string query() const;
145
146     StringMap const& responseHeaders() const
147         { return _responseHeaders; }
148
149     std::string responseMime() const;
150
151     virtual int responseCode() const
152         { return _responseStatus; }
153
154     virtual std::string responseReason() const
155         { return _responseReason; }
156
157     void setResponseLength(unsigned int l);
158     virtual unsigned int responseLength() const;
159
160     /**
161      * Check if request contains body data.
162      */
163     virtual bool hasBodyData() const;
164
165     /**
166      * Retrieve the request body content type.
167      */
168     virtual std::string bodyType() const;
169
170     /**
171      * Retrieve the size of the request body.
172      */
173     virtual size_t bodyLength() const;
174
175     /**
176      * Retrieve the body data bytes. Will be passed the maximum body bytes
177      * to return in the buffer, and must return the actual number
178      * of bytes written.
179      */
180     virtual size_t getBodyData(char* s, size_t offset, size_t max_count) const;
181
182     /**
183      * running total of body bytes received so far. Can be used
184      * to generate a completion percentage, if the response length is
185      * known.
186      */
187     unsigned int responseBytesReceived() const
188         { return _receivedBodyBytes; }
189
190     enum HTTPVersion {
191         HTTP_VERSION_UNKNOWN = 0,
192         HTTP_0_x, // 0.9 or similar
193         HTTP_1_0,
194         HTTP_1_1
195     };
196
197     HTTPVersion responseVersion() const
198         { return _responseVersion; }
199
200     ReadyState readyState() const { return _ready_state; }
201
202     bool closeAfterComplete() const;
203     bool isComplete() const;
204
205     /**
206      * Check if the server response indicates pipelining should be continued.
207      * Currently tests that HTTP_1_1 is explicitly supported, and that the
208      * server/proxy did not request Connection: close
209      */
210     bool serverSupportsPipelining() const;
211
212 protected:
213     Request(const std::string& url, const std::string method = "GET");
214
215     virtual void requestStart();
216     virtual void responseStart(const std::string& r);
217     virtual void responseHeader(const std::string& key, const std::string& value);
218     virtual void responseHeadersComplete();
219     virtual void responseComplete();
220     virtual void gotBodyData(const char* s, int n);
221
222     virtual void onDone();
223     virtual void onFail();
224     virtual void onAlways();
225
226     void setFailure(int code, const std::string& reason);
227
228 private:
229     friend class Client;
230     friend class Connection;
231     friend class ContentDecoder;
232
233     Request(const Request&); // = delete;
234     Request& operator=(const Request&); // = delete;
235
236     void processBodyBytes(const char* s, int n);
237     void setReadyState(ReadyState state);
238
239     void setCloseAfterComplete();
240
241     Client*       _client; // HTTP client we're active on
242
243     std::string   _method;
244     std::string   _url;
245     StringMap     _request_headers;
246     std::string   _request_data;
247     std::string   _request_media_type;
248
249     HTTPVersion   _responseVersion;
250     int           _responseStatus;
251     std::string   _responseReason;
252     StringMap     _responseHeaders;
253     unsigned int  _responseLength;
254     unsigned int  _receivedBodyBytes;
255
256     function_list<Callback> _cb_done,
257                             _cb_fail,
258                             _cb_always;
259
260     ReadyState    _ready_state;
261     bool          _willClose;
262     bool          _connectionCloseHeader;
263 };
264
265 typedef SGSharedPtr<Request> Request_ptr;
266
267 } // of namespace HTTP
268 } // of namespace simgear
269
270 #endif // of SG_HTTP_REQUEST_HXX