X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=simgear%2Fio%2FHTTPRequest.cxx;h=4b7a11bf607fb31c5f776ac0119a22372a6aff18;hb=bc9b3f6ff1fcc5caa67c07ad99f971c0faacf91a;hp=e38f7aae101383456204ff6fe497a56f575c27d5;hpb=f06f25532ca06b7edb948131f45f8efea2268589;p=simgear.git diff --git a/simgear/io/HTTPRequest.cxx b/simgear/io/HTTPRequest.cxx index e38f7aae..4b7a11bf 100644 --- a/simgear/io/HTTPRequest.cxx +++ b/simgear/io/HTTPRequest.cxx @@ -7,21 +7,22 @@ using std::string; using std::map; -#include - -using std::cout; -using std::cerr; -using std::endl; - namespace simgear { namespace HTTP { +extern const int DEFAULT_HTTP_PORT; + Request::Request(const string& url, const string method) : _method(method), - _url(url) + _url(url), + _responseVersion(HTTP_VERSION_UNKNOWN), + _responseStatus(0), + _responseLength(0), + _receivedBodyBytes(0), + _willClose(false) { } @@ -31,6 +32,11 @@ Request::~Request() } +void Request::setUrl(const string& url) +{ + _url = url; +} + string_list Request::requestHeaders() const { string_list r; @@ -44,14 +50,25 @@ string Request::header(const std::string& name) const void Request::responseStart(const string& r) { - const int maxSplit = 2; // HTTP/1.1 nnn status code + const int maxSplit = 2; // HTTP/1.1 nnn reason-string string_list parts = strutils::split(r, NULL, maxSplit); + if (parts.size() != 3) { + SG_LOG(SG_IO, SG_WARN, "HTTP::Request: malformed response start:" << r); + setFailure(400, "malformed HTTP response header"); + return; + } + + _responseVersion = decodeVersion(parts[0]); _responseStatus = strutils::to_int(parts[1]); _responseReason = parts[2]; } void Request::responseHeader(const string& key, const string& value) { + if (key == "connection") { + _willClose = (value.find("close") >= 0); + } + _responseHeaders[key] = value; } @@ -60,6 +77,12 @@ void Request::responseHeadersComplete() // no op } +void Request::processBodyBytes(const char* s, int n) +{ + _receivedBodyBytes += n; + gotBodyData(s, n); +} + void Request::gotBodyData(const char* s, int n) { @@ -103,6 +126,28 @@ string Request::path() const } string Request::host() const +{ + string hp(hostAndPort()); + int colonPos = hp.find(':'); + if (colonPos >= 0) { + return hp.substr(0, colonPos); // trim off the colon and port + } else { + return hp; // no port specifier + } +} + +unsigned short Request::port() const +{ + string hp(hostAndPort()); + int colonPos = hp.find(':'); + if (colonPos >= 0) { + return (unsigned short) strutils::to_int(hp.substr(colonPos + 1)); + } else { + return DEFAULT_HTTP_PORT; + } +} + +string Request::hostAndPort() const { string u(url()); int schemeEnd = u.find("://"); @@ -118,14 +163,46 @@ string Request::host() const return u.substr(schemeEnd + 3, hostEnd - (schemeEnd + 3)); } -int Request::contentLength() const +void Request::setResponseLength(unsigned int l) { - HeaderDict::const_iterator it = _responseHeaders.find("content-length"); - if (it == _responseHeaders.end()) { - return 0; + _responseLength = l; +} + +unsigned int Request::responseLength() const +{ +// if the server didn't supply a content length, use the number +// of bytes we actually received (so far) + if ((_responseLength == 0) && (_receivedBodyBytes > 0)) { + return _receivedBodyBytes; } - return strutils::to_int(it->second); + return _responseLength; +} + +void Request::setFailure(int code, const std::string& reason) +{ + _responseStatus = code; + _responseReason = reason; + failed(); +} + +void Request::failed() +{ + // no-op in base class +} + +Request::HTTPVersion Request::decodeVersion(const string& v) +{ + if (v == "HTTP/1.1") return HTTP_1_1; + if (v == "HTTP/1.0") return HTTP_1_0; + if (strutils::starts_with(v, "HTTP/0.")) return HTTP_0_x; + return HTTP_VERSION_UNKNOWN; +} + +bool Request::closeAfterComplete() const +{ +// for non HTTP/1.1 connections, assume server closes + return _willClose || (_responseVersion != HTTP_1_1); } } // of namespace HTTP