+ queuedRequests.push_back(r);
+ tryStartNextRequest();
+ }
+
+ void beginResponse()
+ {
+ assert(!sentRequests.empty());
+
+ activeRequest = sentRequests.front();
+ activeRequest->responseStart(buffer);
+ state = STATE_GETTING_HEADERS;
+ buffer.clear();
+ if (activeRequest->responseCode() == 204) {
+ noMessageBody = true;
+ } else if (activeRequest->method() == "HEAD") {
+ noMessageBody = true;
+ } else {
+ noMessageBody = false;
+ }
+
+ bodyTransferSize = -1;
+ chunkedTransfer = false;
+ contentGZip = contentDeflate = false;
+ }
+
+ void tryStartNextRequest()
+ {
+ if (queuedRequests.empty()) {
+ idleTime.stamp();
+ return;
+ }
+
+ if (sentRequests.size() > MAX_INFLIGHT_REQUESTS) {
+ return;
+ }
+
+ if (state == STATE_CLOSED) {
+ if (!connectToHost()) {
+ return;
+ }
+
+ setTerminator("\r\n");
+ state = STATE_IDLE;
+ }
+
+ Request_ptr r = queuedRequests.front();
+ requestBodyBytesToSend = r->requestBodyLength();
+
+ stringstream headerData;
+ string path = r->path();
+ string query = r->query();
+ string bodyData;
+
+ if (!client->proxyHost().empty()) {
+ path = r->scheme() + "://" + r->host() + r->path();
+ }
+
+ if (r->method() == "POST") {
+ headerData << r->method() << " " << path << " HTTP/1.1\r\n";
+ bodyData = query.substr(1); // URL-encode, drop the leading '?'
+ headerData << "Content-Type:" << CONTENT_TYPE_URL_ENCODED << "\r\n";
+ headerData << "Content-Length:" << bodyData.size() << "\r\n";
+ } else {
+ headerData << r->method() << " " << path << query << " HTTP/1.1\r\n";
+ if (requestBodyBytesToSend >= 0) {
+ headerData << "Content-Length:" << requestBodyBytesToSend << "\r\n";
+ headerData << "Content-Type:" << r->requestBodyType() << "\r\n";
+ }
+ }
+
+ headerData << "Host: " << r->hostAndPort() << "\r\n";
+ headerData << "User-Agent:" << client->userAgent() << "\r\n";
+ headerData << "Accept-Encoding: deflate, gzip\r\n";
+ if (!client->proxyAuth().empty()) {
+ headerData << "Proxy-Authorization: " << client->proxyAuth() << "\r\n";
+ }
+
+ BOOST_FOREACH(string h, r->requestHeaders()) {
+ headerData << h << ": " << r->header(h) << "\r\n";
+ }
+
+ headerData << "\r\n"; // final CRLF to terminate the headers
+ if (!bodyData.empty()) {
+ headerData << bodyData;
+ }
+
+ bool ok = push(headerData.str().c_str());
+ if (!ok) {
+ // we've over-stuffed the socket, give up for now, let things
+ // drain down before trying to start any more requests.
+ return;
+ }
+
+ while (requestBodyBytesToSend > 0) {
+ char buf[4096];
+ int len = 4096;
+ r->getBodyData(buf, len);
+ if (len > 0) {
+ requestBodyBytesToSend -= len;
+ if (!bufferSend(buf, len)) {
+ SG_LOG(SG_IO, SG_WARN, "overflow the HTTP::Connection output buffer");
+ state = STATE_SOCKET_ERROR;
+ return;
+ }