X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=simgear%2Fio%2FHTTPRequest.cxx;h=6b06785ad00bf57d79fb12e77b971a9475362138;hb=72bb9f4d5d6d861902a5779381e4ebe977db1df1;hp=900b7fc29f9178ea9d2a572752e8af0b2bbe9bc5;hpb=e302ad092eb52efce99f74327ede5fa00e03a3ef;p=simgear.git diff --git a/simgear/io/HTTPRequest.cxx b/simgear/io/HTTPRequest.cxx index 900b7fc2..6b06785a 100644 --- a/simgear/io/HTTPRequest.cxx +++ b/simgear/io/HTTPRequest.cxx @@ -1,3 +1,20 @@ +// 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 + #include "HTTPRequest.hxx" #include @@ -15,6 +32,7 @@ extern const int DEFAULT_HTTP_PORT; //------------------------------------------------------------------------------ Request::Request(const std::string& url, const std::string method): + _client(0), _method(method), _url(url), _responseVersion(HTTP_VERSION_UNKNOWN), @@ -22,7 +40,8 @@ Request::Request(const std::string& url, const std::string method): _responseLength(0), _receivedBodyBytes(0), _ready_state(UNSENT), - _willClose(false) + _willClose(false), + _connectionCloseHeader(false) { } @@ -39,7 +58,7 @@ Request* Request::done(const Callback& cb) if( _ready_state == DONE ) cb(this); else - _cb_done = cb; + _cb_done.push_back(cb); return this; } @@ -50,7 +69,7 @@ Request* Request::fail(const Callback& cb) if( _ready_state == FAILED ) cb(this); else - _cb_fail = cb; + _cb_fail.push_back(cb); return this; } @@ -61,7 +80,7 @@ Request* Request::always(const Callback& cb) if( isComplete() ) cb(this); else - _cb_always = cb; + _cb_always.push_back(cb); return this; } @@ -116,19 +135,28 @@ void Request::responseStart(const std::string& r) const int maxSplit = 2; // HTTP/1.1 nnn reason-string string_list parts = strutils::split(r, NULL, maxSplit); if (parts.size() != 3) { - throw sg_io_exception("bad HTTP response"); + throw sg_io_exception("bad HTTP response:" + r); } - + _responseVersion = decodeHTTPVersion(parts[0]); _responseStatus = strutils::to_int(parts[1]); _responseReason = parts[2]; + + setReadyState(STATUS_RECEIVED); } //------------------------------------------------------------------------------ void Request::responseHeader(const std::string& key, const std::string& value) { - if( key == "connection" ) - _willClose = (value.find("close") != std::string::npos); + if( key == "connection" ) { + _connectionCloseHeader = (value.find("close") != std::string::npos); + // track willClose seperately because other conditions (abort, for + // example) can also set it + _willClose = _connectionCloseHeader; + } else if (key == "content-length") { + int sz = strutils::to_int(value); + setResponseLength(sz); + } _responseHeaders[key] = value; } @@ -190,7 +218,7 @@ std::string Request::scheme() const if (firstColon > 0) { return url().substr(0, firstColon); } - + return ""; // couldn't parse scheme } @@ -202,20 +230,20 @@ std::string Request::path() const if (schemeEnd < 0) { return ""; // couldn't parse scheme } - + int hostEnd = u.find('/', schemeEnd + 3); if (hostEnd < 0) { -// couldn't parse host, or URL looks like 'http://foo.com' (no trailing '/') -// fixup to root resource path: '/' - return "/"; +// couldn't parse host, or URL looks like 'http://foo.com' (no trailing '/') +// fixup to root resource path: '/' + return "/"; } - + int query = u.find('?', hostEnd + 1); if (query < 0) { // all remainder of URL is path return u.substr(hostEnd); } - + return u.substr(hostEnd, query - hostEnd); } @@ -227,7 +255,7 @@ std::string Request::query() const if (query < 0) { return ""; //no query string found } - + return u.substr(query); //includes question mark } @@ -302,6 +330,7 @@ unsigned int Request::responseLength() const //------------------------------------------------------------------------------ void Request::setFailure(int code, const std::string& reason) { + SG_LOG(SG_IO, SG_WARN, "HTTP request: set failure:" << code << " reason " << reason); _responseStatus = code; _responseReason = reason; @@ -321,42 +350,39 @@ void Request::setReadyState(ReadyState state) onDone(); onAlways(); - if( _cb_done ) - _cb_done(this); + _cb_done(this); } else if( state == FAILED ) { onFail(); onAlways(); - if( _cb_fail ) - _cb_fail(this); + _cb_fail(this); } else return; - if( _cb_always ) - _cb_always(this); + _cb_always(this); } //------------------------------------------------------------------------------ -void Request::abort() +bool Request::closeAfterComplete() const { - abort("Request aborted."); + // for non HTTP/1.1 connections, assume server closes + return _willClose || (_responseVersion != HTTP_1_1); } -//---------------------------------------------------------------------------- -void Request::abort(const std::string& reason) +//------------------------------------------------------------------------------ + +void Request::setCloseAfterComplete() { - setFailure(-1, reason); - _willClose = true; + _willClose = true; } //------------------------------------------------------------------------------ -bool Request::closeAfterComplete() const +bool Request::serverSupportsPipelining() const { - // for non HTTP/1.1 connections, assume server closes - return _willClose || (_responseVersion != HTTP_1_1); + return (_responseVersion == HTTP_1_1) && !_connectionCloseHeader; } //------------------------------------------------------------------------------