+// Copyright (C) 2011 James Turner <zakalawe@mac.com>
+// Copyright (C) 2013 Thomas Geymayer <tomgey@gmail.com>
+//
+// 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 <simgear/compiler.h>
//------------------------------------------------------------------------------
Request::Request(const std::string& url, const std::string method):
+ _client(0),
_method(method),
_url(url),
_responseVersion(HTTP_VERSION_UNKNOWN),
_responseLength(0),
_receivedBodyBytes(0),
_ready_state(UNSENT),
- _willClose(false)
+ _willClose(false),
+ _connectionCloseHeader(false)
{
}
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;
}
if (firstColon > 0) {
return url().substr(0, firstColon);
}
-
+
return ""; // couldn't parse scheme
}
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);
}
if (query < 0) {
return ""; //no query string found
}
-
+
return u.substr(query); //includes question mark
}
//------------------------------------------------------------------------------
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;
}
//------------------------------------------------------------------------------
-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;
}
//------------------------------------------------------------------------------