3 // Copyright (C) 2011 James Turner <zakalawe@mac.com>
4 // Copyright (C) 2013 Thomas Geymayer <tomgey@gmail.com>
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.
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.
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
20 #ifndef SG_HTTP_REQUEST_HXX
21 #define SG_HTTP_REQUEST_HXX
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>
31 #include <boost/bind.hpp>
41 * Base class for HTTP request (and answer).
47 typedef boost::function<void(Request*)> Callback;
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); }
73 * Add a handler to be called when the request successfully completes.
75 * @note If the request is already complete, the handler is called
78 Request* done(const Callback& cb);
81 Request* done(C* instance, void (C::*mem_func)(Request*))
83 return done(boost::bind(mem_func, instance, _1));
87 * Add a handler to be called when the request completes or aborts with an
90 * @note If the request has already failed, the handler is called
93 Request* fail(const Callback& cb);
96 Request* fail(C* instance, void (C::*mem_func)(Request*))
98 return fail(boost::bind(mem_func, instance, _1));
102 * Add a handler to be called when the request either successfully completes
105 * @note If the request is already complete or has already failed, the
106 * handler is called immediately.
108 Request* always(const Callback& cb);
111 Request* always(C* instance, void (C::*mem_func)(Request*))
113 return always(boost::bind(mem_func, instance, _1));
117 * Set the data for the body of the request. The request is automatically
118 * send using the POST method.
120 * @param data Body data
121 * @param type Media Type (aka MIME) of the body data
123 void setBodyData( const std::string& data,
124 const std::string& type = "text/plain" );
125 void setBodyData( const SGPropertyNode* data );
127 virtual void setUrl(const std::string& url);
129 virtual std::string method() const
131 virtual std::string url() const
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;
141 StringMap const& responseHeaders() const
142 { return _responseHeaders; }
144 std::string responseMime() const;
146 virtual int responseCode() const
147 { return _responseStatus; }
149 virtual std::string responseReason() const
150 { return _responseReason; }
152 void setResponseLength(unsigned int l);
153 virtual unsigned int responseLength() const;
156 * Check if request contains body data.
158 virtual bool hasBodyData() const;
161 * Retrieve the request body content type.
163 virtual std::string bodyType() const;
166 * Retrieve the size of the request body.
168 virtual size_t bodyLength() const;
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
175 virtual size_t getBodyData(char* s, size_t offset, size_t max_count) const;
178 * running total of body bytes received so far. Can be used
179 * to generate a completion percentage, if the response length is
182 unsigned int responseBytesReceived() const
183 { return _receivedBodyBytes; }
186 HTTP_VERSION_UNKNOWN = 0,
187 HTTP_0_x, // 0.9 or similar
192 HTTPVersion responseVersion() const
193 { return _responseVersion; }
195 ReadyState readyState() const { return _ready_state; }
198 * Request aborting this request.
203 * Request aborting this request and specify the reported reaseon for it.
205 void abort(const std::string& reason);
207 bool closeAfterComplete() const;
208 bool isComplete() const;
211 * Check if the server response indicates pipelining should be continued.
212 * Currently tests that HTTP_1_1 is explicitly supported, and that the
213 * server/proxy did not request Connection: close
215 bool serverSupportsPipelining() const;
218 Request(const std::string& url, const std::string method = "GET");
220 virtual void requestStart();
221 virtual void responseStart(const std::string& r);
222 virtual void responseHeader(const std::string& key, const std::string& value);
223 virtual void responseHeadersComplete();
224 virtual void responseComplete();
225 virtual void gotBodyData(const char* s, int n);
227 virtual void onDone();
228 virtual void onFail();
229 virtual void onAlways();
231 void setFailure(int code, const std::string& reason);
235 friend class Connection;
236 friend class ContentDecoder;
238 Request(const Request&); // = delete;
239 Request& operator=(const Request&); // = delete;
241 void processBodyBytes(const char* s, int n);
242 void setReadyState(ReadyState state);
246 StringMap _request_headers;
247 std::string _request_data;
248 std::string _request_media_type;
250 HTTPVersion _responseVersion;
252 std::string _responseReason;
253 StringMap _responseHeaders;
254 unsigned int _responseLength;
255 unsigned int _receivedBodyBytes;
257 function_list<Callback> _cb_done,
261 ReadyState _ready_state;
263 bool _connectionCloseHeader;
266 typedef SGSharedPtr<Request> Request_ptr;
268 } // of namespace HTTP
269 } // of namespace simgear
271 #endif // of SG_HTTP_REQUEST_HXX