X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=simgear%2Fio%2FHTTPRequest.hxx;h=0def08880162c667d9f714f490dc99dbdd0ecbd4;hb=8d93206dd33ed0079af6670a0ecd41a3b203d9a0;hp=0e346419d12632abd535f99782e370120d149467;hpb=7525fd5e3ee741ea323df5811647faa5c5763a4b;p=simgear.git diff --git a/simgear/io/HTTPRequest.hxx b/simgear/io/HTTPRequest.hxx index 0e346419..0def0888 100644 --- a/simgear/io/HTTPRequest.hxx +++ b/simgear/io/HTTPRequest.hxx @@ -1,103 +1,270 @@ +///@file +// +// Copyright (C) 2011 James Turner +// Copyright (C) 2013 Thomas Geymayer +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + #ifndef SG_HTTP_REQUEST_HXX #define SG_HTTP_REQUEST_HXX #include +#include +#include #include #include #include +#include + +class SGPropertyNode; + namespace simgear { - namespace HTTP { -class Request : public SGReferenced +class Client; + +/** + * Base class for HTTP request (and answer). + */ +class Request: + public SGReferenced { public: + typedef boost::function Callback; + + enum ReadyState + { + UNSENT = 0, + OPENED, + STATUS_RECEIVED, + HEADERS_RECEIVED, + LOADING, + DONE, + FAILED + }; + virtual ~Request(); - + + /** + * + */ + StringMap& requestHeaders() { return _request_headers; } + const StringMap& requestHeaders() const { return _request_headers; } + std::string& requestHeader(const std::string& key) + { return _request_headers[key]; } + const std::string requestHeader(const std::string& key) const + { return _request_headers.get(key); } + + /** + * Add a handler to be called when the request successfully completes. + * + * @note If the request is already complete, the handler is called + * immediately. + */ + Request* done(const Callback& cb); + + template + Request* done(C* instance, void (C::*mem_func)(Request*)) + { + return done(boost::bind(mem_func, instance, _1)); + } + + /** + * Add a handler to be called when the request completes or aborts with an + * error. + * + * @note If the request has already failed, the handler is called + * immediately. + */ + Request* fail(const Callback& cb); + + template + Request* fail(C* instance, void (C::*mem_func)(Request*)) + { + return fail(boost::bind(mem_func, instance, _1)); + } + + /** + * Add a handler to be called when the request either successfully completes + * or fails. + * + * @note If the request is already complete or has already failed, the + * handler is called immediately. + */ + Request* always(const Callback& cb); + + template + Request* always(C* instance, void (C::*mem_func)(Request*)) + { + return always(boost::bind(mem_func, instance, _1)); + } + + /** + * Set the data for the body of the request. The request is automatically + * send using the POST method. + * + * @param data Body data + * @param type Media Type (aka MIME) of the body data + */ + void setBodyData( const std::string& data, + const std::string& type = "text/plain" ); + void setBodyData( const SGPropertyNode* data ); + virtual void setUrl(const std::string& url); - + virtual std::string method() const { return _method; } virtual std::string url() const { return _url; } - + + Client* http() const + { return _client; } + virtual std::string scheme() const; virtual std::string path() const; virtual std::string host() const; virtual std::string hostAndPort() const; virtual unsigned short port() const; - - virtual string_list requestHeaders() const; - virtual std::string header(const std::string& name) const; + virtual std::string query() const; + + StringMap const& responseHeaders() const + { return _responseHeaders; } + + std::string responseMime() const; virtual int responseCode() const { return _responseStatus; } - + virtual std::string responseReason() const { return _responseReason; } - - void setResponseLength(unsigned int l); + + void setResponseLength(unsigned int l); virtual unsigned int responseLength() const; - + + /** + * Check if request contains body data. + */ + virtual bool hasBodyData() const; + + /** + * Retrieve the request body content type. + */ + virtual std::string bodyType() const; + + /** + * Retrieve the size of the request body. + */ + virtual size_t bodyLength() const; + + /** + * Retrieve the body data bytes. Will be passed the maximum body bytes + * to return in the buffer, and must return the actual number + * of bytes written. + */ + virtual size_t getBodyData(char* s, size_t offset, size_t max_count) const; + /** * running total of body bytes received so far. Can be used * to generate a completion percentage, if the response length is - * known. + * known. */ unsigned int responseBytesReceived() const { return _receivedBodyBytes; } - + enum HTTPVersion { HTTP_VERSION_UNKNOWN = 0, HTTP_0_x, // 0.9 or similar HTTP_1_0, HTTP_1_1 }; - + HTTPVersion responseVersion() const { return _responseVersion; } - - static HTTPVersion decodeVersion(const std::string& v); - + + ReadyState readyState() const { return _ready_state; } + bool closeAfterComplete() const; + bool isComplete() const; + + /** + * Check if the server response indicates pipelining should be continued. + * Currently tests that HTTP_1_1 is explicitly supported, and that the + * server/proxy did not request Connection: close + */ + bool serverSupportsPipelining() const; + protected: Request(const std::string& url, const std::string method = "GET"); + virtual void requestStart(); virtual void responseStart(const std::string& r); virtual void responseHeader(const std::string& key, const std::string& value); virtual void responseHeadersComplete(); virtual void responseComplete(); - virtual void failed(); virtual void gotBodyData(const char* s, int n); + + virtual void onDone(); + virtual void onFail(); + virtual void onAlways(); + + void setFailure(int code, const std::string& reason); + private: friend class Client; friend class Connection; - + friend class ContentDecoder; + + Request(const Request&); // = delete; + Request& operator=(const Request&); // = delete; + void processBodyBytes(const char* s, int n); - void setFailure(int code, const std::string& reason); + void setReadyState(ReadyState state); + + void setCloseAfterComplete(); + + Client* _client; // HTTP client we're active on + + std::string _method; + std::string _url; + StringMap _request_headers; + std::string _request_data; + std::string _request_media_type; - std::string _method; - std::string _url; - HTTPVersion _responseVersion; - int _responseStatus; - std::string _responseReason; - unsigned int _responseLength; - unsigned int _receivedBodyBytes; - bool _willClose; - - typedef std::map HeaderDict; - HeaderDict _responseHeaders; + HTTPVersion _responseVersion; + int _responseStatus; + std::string _responseReason; + StringMap _responseHeaders; + unsigned int _responseLength; + unsigned int _receivedBodyBytes; + + function_list _cb_done, + _cb_fail, + _cb_always; + + ReadyState _ready_state; + bool _willClose; + bool _connectionCloseHeader; }; typedef SGSharedPtr Request_ptr; } // of namespace HTTP - } // of namespace simgear #endif // of SG_HTTP_REQUEST_HXX -