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)
{
}
string_list parts = strutils::split(r, NULL, maxSplit);
if (parts.size() != 3) {
SG_LOG(SG_IO, SG_WARN, "HTTP::Request: malformed response start:" << r);
- _responseStatus = 400;
- _responseReason = "bad HTTP response header";
+ 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;
}
// no op
}
+void Request::processBodyBytes(const char* s, int n)
+{
+ _receivedBodyBytes += n;
+ gotBodyData(s, n);
+}
+
void Request::gotBodyData(const char* s, int n)
{
return u.substr(schemeEnd + 3, hostEnd - (schemeEnd + 3));
}
-unsigned 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 (unsigned int) 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