Esempio n. 1
0
am_status_t
BaseService::doRequest(const ServiceInfo& service,
		       const BodyChunk& headerPrefix,
		       const std::string& uriParameters,
		       const Http::CookieList& cookieList,
		       const BodyChunk& headerSuffix,
		       const BodyChunkList& bodyChunkList,
		       Http::Response& response,
		       std::size_t initialBufferLen,
		       const std::string &cert_nick_name,
		       const ServerInfo** serverInfo) const
{
    am_status_t status = AM_SERVICE_NOT_AVAILABLE;
    std::size_t dataLen = 0;
    // Create a temporary buffer for the Content-Line header
    // the extra '2' is for the <CR><LF> at the end.  The
    // sizeof the CONTENT_LENGTH_HDR includes space for the
    // terminating NUL.
    char contentLine[sizeof(CONTENT_LENGTH_HDR) +
		     (sizeof(dataLen) * DIGITS_PER_BYTE) + 2];
    std::size_t contentLineLen;

    for (unsigned int i = 0; i < bodyChunkList.size(); ++i) {
	dataLen += bodyChunkList[i].data.size();
    }

    contentLineLen = snprintf(contentLine, sizeof(contentLine), "%s%d\r\n",
			      CONTENT_LENGTH_HDR, dataLen);
    if (sizeof(contentLine) > contentLineLen) {
	BodyChunk contentLineChunk(contentLine, contentLineLen);
	ServiceInfo::const_iterator iter;

	for (iter = service.begin(); iter != service.end(); ++iter) {
            ServerInfo svrInfo = ServerInfo((const ServerInfo&)(*iter));
	    if (!svrInfo.isHealthy(poll_primary_server)) {
		Log::log(logModule, Log::LOG_WARNING,
			"BaseService::doRequest(): "
			"Server is unavailable: %s.",
			svrInfo.getURL().c_str());
		continue;
	    } else {
		Log::log(logModule, Log::LOG_DEBUG,
			"BaseService::doRequest(): Using server: %s.",
			iter->getURL().c_str());
            }

            Http::HeaderList headerList, proxyHeaderList;
            Http::Cookie hostHeader("Host", svrInfo.getHost());
            headerList.push_back(hostHeader);

            if (useProxy) {
                proxyHeaderList.push_back(hostHeader);
                // Override (temporarily) server credentials if using proxy
                svrInfo.setHost(proxyHost);
                svrInfo.setPort(proxyPort);
                // We don't use SSL for initial proxy connection
		svrInfo.setUseSSL(false);
                Log::log(logModule, Log::LOG_DEBUG,
                         "BaseService::doRequest(): Using proxy: %s:%d",
                         proxyHost.c_str(),proxyPort);
                // Add Proxy-Authorization header if user defined
                if (useProxyAuth) {
                    // allocate enough for a base64-encoded digest
                    int authSize = proxyUser.size() + 
                                   proxyPassword.size() + 1;
                    // 11 extra bytes for prefix and terminator
                    char * digest = (char *)malloc(authSize * 4/3 + 11);
                    strcpy(digest, "Basic ");
                    encode_base64((proxyUser + ":" + proxyPassword).c_str(),
                                   authSize,(digest + 6));
                    Log::log(logModule, Log::LOG_MAX_DEBUG,
                         "BaseService::doRequest(): Using proxy auth as: %s",
                         proxyUser.c_str());
                    hostHeader = Http::Cookie("Proxy-Authorization", digest);
                    proxyHeaderList.push_back(hostHeader);
                    free(digest);
                }
            }

            // retry to connect to server before marking it as down.
            // making the number of attempts configurable may have a negative
            // side effect on performance, if the the value is a high number.
            int retryAttempts = 3;
            int retryCount = 0;
            while(retryCount < retryAttempts) {
                retryCount++;
	        try {
                    Connection conn(svrInfo, certDBPasswd,
                      (cert_nick_name.size()>0)?cert_nick_name:certNickName,
                         alwaysTrustServerCert);
		    const char *operation = "sending to";
                    // in case proxy is defined and target URL is HTTPS, 
                    // establish an SSL tunnel first send 
                    // CONNECT host:port string
                    if (useProxy && iter->useSSL()) {
                        SECStatus   secStatus = SECFailure;
                        // All the other parameters would be empty for a 
                        // proxy CONNECT
                        Http::CookieList emptyCookieList;
                        BodyChunk emptyChunk;
                        BodyChunkList emptyChunkList;

                        // Add a Keep-alive header since we're using HTTP/1.0
                        hostHeader = Http::Cookie("Connection", 
                                                  "Keep-Alive\r\n");
                        proxyHeaderList.push_back(hostHeader);
                        status = sendRequest(conn, 
                                        BodyChunk(std::string("CONNECT ")), 
                                        iter->getHost() + ":" +
					Utils::toString(iter->getPort()), 
                                        std::string(""), proxyHeaderList, 
                                        emptyCookieList, emptyChunk, 
                                        emptyChunk, emptyChunkList);
                        if (status == AM_SUCCESS) {
                            // Retrieve proxie's response if tunnel 
                            // established
                            (void) response.readAndIgnore(logModule, conn);
                            // Secure the tunnel now by upgrading the socket
                            PRFileDesc *sock = conn.secureSocket(
                                                  certDBPasswd, 
                                                  (cert_nick_name.size()>0)?
                                            cert_nick_name:certNickName, 
				            alwaysTrustServerCert, NULL);
                            if (sock != static_cast<PRFileDesc *>(NULL)) {
                                secStatus = SSL_SetURL(sock, 
                                                  iter->getHost().c_str());
                            }
                        }

                        if (status != AM_SUCCESS || SECSuccess != secStatus){
                            Log::log(logModule, Log::LOG_ERROR,
                                "BaseService::doRequest(): could not "
				"establish a secure proxy tunnel");
                            // Can't continue and mark server as down as 
                            // it was a  proxy failure
                            return AM_FAILURE;
                        }
                    }

		    if(Log::isLevelEnabled(logModule, Log::LOG_MAX_DEBUG)) {
		        std::string commString;
		        for(std::size_t i = 0; i<bodyChunkList.size(); ++i) {
			    if(!bodyChunkList[i].secure) {
			        commString.append(bodyChunkList[i].data);
			    } else {
			        commString.append("<secure data>");
			    }
		        }
		        for(std::size_t commPos = commString.find("%");
		    	    commPos != std::string::npos &&
			    commPos < commString.size();
			    commPos = commString.find("%", commPos)) {
			    commString.replace(commPos, 1, "%%");
			    commPos += 2;
		        }
		        Log::log(logModule, Log::LOG_MAX_DEBUG,
			     commString.c_str());
		    }

                    std::string requestString = iter->getURI();
                    /*
                     * In case the following request would go to a proxy
                     * we need to use full URL and special headers.
                     * If the resource is HTTPS, we're not posting our
                     * request to the proxy, but to the server 
                     * through proxy tunnel
                     */

                    if (useProxy && !(iter->useSSL())) {
                        requestString = iter->getURL();
                        headerList = proxyHeaderList;
                    }
		    status = sendRequest(conn, headerPrefix, requestString,
				     uriParameters, headerList, cookieList,
				     contentLineChunk, headerSuffix,
				     bodyChunkList);
		    if (AM_SUCCESS == status) {
		        operation = "receiving from";
		        status = response.readAndParse(logModule, conn,
						   initialBufferLen);
		        if (AM_SUCCESS == status) {
			    Log::log(logModule, Log::LOG_MAX_DEBUG, "%.*s",
				 response.getBodyLen(), response.getBodyPtr());
		        }
		    }

		    if (AM_NSPR_ERROR == status) {
		        PRErrorCode nspr_code = PR_GetError();
		        Log::log(logModule, Log::LOG_ALWAYS,
			     "BaseService::doRequest() NSPR failure while "
			     "%s %s, error = %s", operation,
			     (*iter).toString().c_str(), 
			     PR_ErrorToName(nspr_code));
		    }
		
		    if (AM_SUCCESS == status) {
		        if(serverInfo != NULL) *serverInfo = &(*iter);
		            break;
		    } else {
                        if(retryCount < retryAttempts) {
                            continue;
                        } else {
                           Log::log(logModule, Log::LOG_DEBUG,
                               "BaseService::doRequest() Invoking markSeverDown");
                           svrInfo.markServerDown(poll_primary_server);
                        }
		    }
	        } catch (const NSPRException& exc) {
		    Log::log(logModule, Log::LOG_DEBUG,
			 "BaseService::doRequest() caught %s: %s called by %s "
			 "returned %s", exc.what(), exc.getNsprMethod(),
			 exc.getThrowingMethod(), 
			 PR_ErrorToName(exc.getErrorCode()));

                   if(retryCount < retryAttempts) {
		       status = AM_NSPR_ERROR;
                       continue;
                    } else {
                       Log::log(logModule, Log::LOG_DEBUG,
                           "BaseService::doRequest() Invoking markSeverDown");
                       svrInfo.markServerDown(poll_primary_server);
		       status = AM_NSPR_ERROR;
                    }
	        }
            } //end of while

            if (AM_SUCCESS == status) {
               if(serverInfo != NULL) *serverInfo = &(*iter);
                    break;
            }
            if (status = AM_NSPR_ERROR) {
               continue;
            }

	} // end of for
    } else {
	status = AM_BUFFER_TOO_SMALL;
    }

    return status;
}
Esempio n. 2
0
/**
 * PHP has "EGPCS" processing order of these global variables, and this
 * order is important in preparing $_REQUEST that needs to know which to
 * overwrite what when name happens to be the same.
 */
void HttpProtocol::PrepareSystemVariables(Transport *transport,
                                          const RequestURI &r,
                                          const SourceRootInfo &sri) {
  SystemGlobals *g = (SystemGlobals*)get_global_variables();
  const VirtualHost *vhost = VirtualHost::GetCurrent();

  // reset global symbols to nulls or empty arrays
  pm_php$globals$symbols_php();

  Variant &server = g->GV(_SERVER);
  server.set("REQUEST_START_TIME", time(NULL));

  // $_ENV
  process_env_variables(g->GV(_ENV));
  g->GV(_ENV).set("HPHP", 1);
  g->GV(_ENV).set("HPHP_SERVER", 1);
#ifdef HOTPROFILER
  g->GV(_ENV).set("HPHP_HOTPROFILER", 1);
#endif

  Variant &request = g->GV(_REQUEST);

  // $_GET and $_REQUEST
  if (!r.queryString().empty()) {
    DecodeParameters(g->GV(_GET), r.queryString().data(),
                     r.queryString().size());
    CopyParams(request, g->GV(_GET));
  }

  string contentType = transport->getHeader("Content-Type");
  string contentLength = transport->getHeader("Content-Length");
  // $_POST and $_REQUEST
  if (transport->getMethod() == Transport::POST) {
    bool needDelete = false;
    int size = 0;
    const void *data = transport->getPostData(size);
    if (data && size) {
      ASSERT(((char*)data)[size] == 0); // we need a NULL terminated string
      string boundary;
      int content_length = atoi(contentLength.c_str());
      bool rfc1867Post = IsRfc1867(contentType, boundary);
      string files;
      if (rfc1867Post) {
        if (content_length > VirtualHost::GetMaxPostSize()) {
          // $_POST and $_FILES are empty
          Logger::Warning("POST Content-Length of %d bytes exceeds "
                          "the limit of %lld bytes",
                          content_length, VirtualHost::GetMaxPostSize());
          needDelete = read_all_post_data(transport, data, size);
        } else {
          if (transport->hasMorePostData()) {
            needDelete = true;
            data = Util::buffer_duplicate(data, size);
          }
          DecodeRfc1867(transport, g->GV(_POST), g->GV(_FILES),
                        content_length, data, size, boundary);
        }
        ASSERT(!transport->getFiles(files));
      } else {
        needDelete = read_all_post_data(transport, data, size);

        bool decodeData = strncasecmp(contentType.c_str(),
                                       DEFAULT_POST_CONTENT_TYPE,
                                       sizeof(DEFAULT_POST_CONTENT_TYPE)-1) == 0;
        // Always decode data for now. (macvicar)
        decodeData = true;

        if (decodeData) {
          DecodeParameters(g->GV(_POST), (const char*)data, size, true);
        }

        bool ret = transport->getFiles(files);
        if (ret) {
          g->GV(_FILES) = f_unserialize(files);
        }
      }
      CopyParams(request, g->GV(_POST));
      if (needDelete) {
        if (RuntimeOption::AlwaysPopulateRawPostData) {
          g->GV(HTTP_RAW_POST_DATA) = String((char*)data, size, AttachString);
        } else {
          free((void *)data);
        }
      } else {
        // For literal we disregard RuntimeOption::AlwaysPopulateRawPostData
        g->GV(HTTP_RAW_POST_DATA) = String((char*)data, size, AttachLiteral);
      }
    }
  }

  // $_COOKIE
  string cookie_data = transport->getHeader("Cookie");
  if (!cookie_data.empty()) {
    StringBuffer sb;
    sb.append(cookie_data);
    DecodeCookies(g->GV(_COOKIE), (char*)sb.data());
    CopyParams(request, g->GV(_COOKIE));
  }

  // $_SERVER

  // HTTP_ headers -- we don't exclude headers we handle elsewhere (e.g.,
  // Content-Type, Authorization), since the CGI "spec" merely says the server
  // "may" exclude them; this is not what APE does, but it's harmless.
  HeaderMap headers;
  transport->getHeaders(headers);
  for (HeaderMap::const_iterator iter = headers.begin();
       iter != headers.end(); ++iter) {
    const vector<string> &values = iter->second;
    for (unsigned int i = 0; i < values.size(); i++) {
      String key = "HTTP_";
      key += StringUtil::ToUpper(iter->first).replace("-", "_");
      server.set(key, String(values[i]));
    }
  }
  string host = transport->getHeader("Host");
  String hostName(VirtualHost::GetCurrent()->serverName(host));
  string hostHeader(host);
  if (hostHeader.empty()) {
    server.set("HTTP_HOST", hostName);
    StackTraceNoHeap::AddExtraLogging("Server", hostName.data());
  } else {
    StackTraceNoHeap::AddExtraLogging("Server", hostHeader.c_str());
  }
  if (hostName.empty() || RuntimeOption::ForceServerNameToHeader) {
    hostName = hostHeader;
    // _SERVER['SERVER_NAME'] shouldn't contain the port number
    int colonPos = hostName.find(':');
    if (colonPos != String::npos) {
      hostName = hostName.substr(0, colonPos);
    }
  }

  // APE sets CONTENT_TYPE and CONTENT_LENGTH without HTTP_
  if (!contentType.empty()) {
    server.set("CONTENT_TYPE", String(contentType));
  }
  if (!contentLength.empty()) {
    server.set("CONTENT_LENGTH", String(contentLength));
  }

  // APE processes Authorization: Basic into PHP_AUTH_USER and PHP_AUTH_PW
  string authorization = transport->getHeader("Authorization");
  if (!authorization.empty()) {
    if (strncmp(authorization.c_str(), "Basic ", 6) == 0) {
      // it's safe to pass this as a string literal since authorization
      // outlives decodedAuth; this saves us a superfluous copy.
      String decodedAuth =
        StringUtil::Base64Decode(String(authorization.c_str() + 6));
      int colonPos = decodedAuth.find(':');
      if (colonPos != String::npos) {
        server.set("PHP_AUTH_USER", decodedAuth.substr(0, colonPos));
        server.set("PHP_AUTH_PW", decodedAuth.substr(colonPos + 1));
      }
    }
  }

  server.set("REQUEST_URI", String(transport->getUrl(), CopyString));
  server.set("SCRIPT_URL", r.originalURL());
  String prefix(transport->isSSL() ? "https://" : "http://");
  String port_suffix("");

  // Need to append port
  if (!transport->isSSL() && RuntimeOption::ServerPort != 80) {
    port_suffix = ":" + RuntimeOption::ServerPort;
  }
  server.set("SCRIPT_URI", String(prefix +
                                  (hostHeader.empty() ?
                                    hostName + port_suffix : hostHeader)
                                  + r.originalURL()));

  if (r.rewritten()) {
    // when URL is rewritten, PHP decided to put original URL as SCRIPT_NAME
    String name = r.originalURL();
    if (!r.pathInfo().empty()) {
      int pos = name.find(r.pathInfo());
      if (pos >= 0) {
        name = name.substr(0, pos);
      }
    }
    if (r.defaultDoc()) {
      if (!name.empty() && name[name.length() - 1] != '/') {
        name += "/";
      }
      name += String(RuntimeOption::DefaultDocument);
    }
    server.set("SCRIPT_NAME", name);
  } else {
    server.set("SCRIPT_NAME", r.resolvedURL());
  }
  if (!r.rewritten() && r.pathInfo().empty()) {
    server.set("PHP_SELF", r.resolvedURL());
  } else {
    // when URL is rewritten, or pathinfo is not empty, use original URL
    server.set("PHP_SELF", r.originalURL());
  }

  server.set("SCRIPT_FILENAME", r.absolutePath());
  if (r.pathInfo().empty()) {
    server.set("PATH_TRANSLATED", r.absolutePath());
  } else {
    server.set("PATH_TRANSLATED",
               String(vhost->getDocumentRoot() + r.pathInfo().data()));
    server.set("PATH_INFO", r.pathInfo());
  }

  server.set("argv", r.queryString());
  server.set("argc", 0);
  server.set("GATEWAY_INTERFACE", "CGI/1.1");
  server.set("SERVER_ADDR", String(RuntimeOption::ServerPrimaryIP));
  server.set("SERVER_NAME", hostName);
  server.set("SERVER_PORT", RuntimeOption::ServerPort);
  server.set("SERVER_SOFTWARE", "HPHP");
  server.set("SERVER_PROTOCOL", "HTTP/" + transport->getHTTPVersion());
  server.set("SERVER_ADMIN", "");
  server.set("SERVER_SIGNATURE", "");
  switch (transport->getMethod()) {
  case Transport::GET:  server.set("REQUEST_METHOD", "GET");  break;
  case Transport::HEAD: server.set("REQUEST_METHOD", "HEAD"); break;
  case Transport::POST:
    if (transport->getExtendedMethod() == NULL) {
      server.set("REQUEST_METHOD", "POST");
    } else {
      server.set("REQUEST_METHOD", transport->getExtendedMethod());
    }
    break;
  default:              server.set("REQUEST_METHOD", "");     break;
  }
  server.set("HTTPS", transport->isSSL() ? "1" : "");
  server.set("REQUEST_TIME", time(NULL));
  server.set("QUERY_STRING", r.queryString());

  server.set("REMOTE_ADDR", String(transport->getRemoteHost(), CopyString));
  server.set("REMOTE_HOST", ""); // I don't think we need to nslookup
  server.set("REMOTE_PORT", 0);  // TODO: quite useless

  server.set("DOCUMENT_ROOT", String(vhost->getDocumentRoot()));

  for (map<string, string>::const_iterator iter =
         RuntimeOption::ServerVariables.begin();
       iter != RuntimeOption::ServerVariables.end(); ++iter) {
      server.set(String(iter->first), String(iter->second));
  }
  const map<string, string> &vServerVars = vhost->getServerVars();
  for (map<string, string>::const_iterator iter =
         vServerVars.begin();
       iter != vServerVars.end(); ++iter) {
    server.set(String(iter->first), String(iter->second));
  }
  sri.setServerVariables(server);

  const char *threadType = transport->getThreadTypeName();
  server.set("THREAD_TYPE", threadType);
  StackTraceNoHeap::AddExtraLogging("ThreadType", threadType);

#ifdef TAINTED
  taint_array_variant(g->GV(_GET), "$_GET");
  taint_array_variant(g->GV(_POST), "$_POST");
  taint_array_variant(g->GV(_SERVER), "$_SERVER");
  taint_array_variant(g->GV(_COOKIE), "$_COOKIE");
#endif
}
Esempio n. 3
0
am_status_t
BaseService::doRequest(const ServiceInfo& service,
        const BodyChunk& headerPrefix,
        const std::string& uriParameters,
        const Http::CookieList& cookieList,
        const BodyChunk& headerSuffix,
        const BodyChunkList& bodyChunkList,
        Http::Response& response,
        const ServerInfo** serverInfo) const {
    am_status_t status = AM_SERVICE_NOT_AVAILABLE;
    int dataLen = 0;
    BodyChunk emptyContentLine;
    // Create a temporary buffer for the Content-Line header
    // the extra '2' is for the <CR><LF> at the end.  The
    // sizeof the CONTENT_LENGTH_HDR includes space for the
    // terminating NUL.
    const std::size_t contentLineLen_sz = sizeof (CONTENT_LENGTH_HDR) +
            (sizeof (dataLen) * DIGITS_PER_BYTE) + 2;
    char contentLine[contentLineLen_sz + 1];
    std::size_t contentLineLen = 0;

    for (unsigned int i = 0; i < bodyChunkList.size(); ++i) {
        dataLen += bodyChunkList[i].data.size();
    }

    memset(&contentLine[0], 0, contentLineLen_sz);
    contentLineLen = snprintf(contentLine, contentLineLen_sz, "%s%d\r\n",
            CONTENT_LENGTH_HDR, dataLen);

    if (contentLineLen_sz > contentLineLen && contentLineLen > 0) {
        BodyChunk contentLineChunk(contentLine, contentLineLen);
        ServiceInfo::const_iterator iter;
        ServiceInfo svc(service);
        int j = -1, current_index = -1;
        if (am_web_naming_validation_status() < 2 && svc.getNumberOfServers() > 1) {
            /* validation is enabled and number of servers is more than one */
            char *current_value = read_naming_value(AM_NAMING_LOCK, Log::getLockId());
            if (current_value != NULL) {
                current_index = strtol(current_value, NULL, 10);
                if (current_index < 0 || errno == ERANGE) {
                    current_index = 0;
                } else {
                    Log::log(logModule, Log::LOG_MAX_DEBUG,
                            "BaseService::doRequest(): will be using url index: %d",
                            current_index);
                }
                free(current_value);
            } else {
                current_index = 0;
            }
            if ((size_t) current_index >= svc.getNumberOfServers()) {
                Log::log(logModule, Log::LOG_WARNING,
                        "BaseService::doRequest(): invalid url index: %d (out of %d); validation results ignored.",
                        current_index, svc.getNumberOfServers());
                current_index = -1;
            }
        }

        for (iter = svc.begin(); iter != svc.end(); ++iter) {
            const ServerInfo &svrInfo = (*iter);

            if (current_index != -1) {
                if ((++j) != current_index) {
                    Log::log(logModule, Log::LOG_MAX_DEBUG,
                            "BaseService::doRequest(): skipping url(%d) %s",
                            j, svrInfo.getURL().c_str());
                    continue;
                } else {
                    Log::log(logModule, Log::LOG_MAX_DEBUG,
                            "BaseService::doRequest(): using url(%d) %s",
                            j, svrInfo.getURL().c_str());
                }
            }

            Http::HeaderList headerList, proxyHeaderList;
            Http::Cookie hostHeader("Host", svrInfo.getHost());
            headerList.push_back(hostHeader);

#ifdef AGENT_PROXY_SUPPORT
#ifndef _MSC_VER
            if (useProxy) {
                proxyHeaderList.push_back(hostHeader);
                // Override (temporarily) server credentials if using proxy
                //svrInfo.setHost(proxyHost);
                //svrInfo.setPort(proxyPort);
                // We don't use SSL for initial proxy connection
                //svrInfo.setUseSSL(false);
                Log::log(logModule, Log::LOG_DEBUG,
                        "BaseService::doRequest(): Using proxy: %s:%d",
                        proxyHost.c_str(), proxyPort);
                // Add Proxy-Authorization header if user defined
                if (useProxyAuth) {
                    // allocate enough for a base64-encoded digest
                    size_t authSize = proxyUser.size() +
                            proxyPassword.size() + 1;
                    // 11 extra bytes for prefix and terminator
                    char * digest = (char *) malloc(authSize * 4 / 3 + 11);
                    strcpy(digest, "Basic ");
                    encode_base64((proxyUser + ":" + proxyPassword).c_str(),
                            authSize, (digest + 6));
                    Log::log(logModule, Log::LOG_MAX_DEBUG,
                            "BaseService::doRequest(): Using proxy auth as: %s",
                            proxyUser.c_str());
                    hostHeader = Http::Cookie("Proxy-Authorization", digest);
                    proxyHeaderList.push_back(hostHeader);
                    free(digest);
                }
            }
#endif
#endif

            // retry to connect to server before marking it as down.
            // making the number of attempts configurable may have a negative
            // side effect on performance, if the the value is a high number.
            int retryAttempts = 3;
            int retryCount = 0;
            while (retryCount < retryAttempts) {
                retryCount++;
                try {
                    const char *operation = "sending to";
                    Connection conn(svrInfo.getHost().c_str(), svrInfo.getPort(), svrInfo.useSSL());
#ifdef AGENT_PROXY_SUPPORT
                    std::string requestString = svrInfo.getURI().c_str();
                    /*
                     * In case the following request would go to a proxy
                     * we need to use full URL and special headers.
                     */

                    if (useProxy && !(iter->useSSL())) {
                       requestString = iter->getURL();
                       headerList = proxyHeaderList;
                    }
#endif
                    status = sendRequest(conn, headerPrefix, svrInfo.getURI(),
                            uriParameters, headerList, cookieList,
                            dataLen > 0 ? contentLineChunk : emptyContentLine, headerSuffix,
                            bodyChunkList);
                    if (AM_SUCCESS == status) {
                        operation = "receiving from";
                        status = response.readAndParse(logModule, conn);
                        if (AM_SUCCESS == status) {
                            Log::log(logModule, Log::LOG_MAX_DEBUG, "Response::readAndParse() (%d) %s",
                                    response.getBodyLen(), response.getBodyPtr() ? response.getBodyPtr() : "(NULL)");
                        }
                    }

                    if (AM_NSPR_ERROR == status) {
                        Log::log(logModule, Log::LOG_ALWAYS,
                                "BaseService::doRequest() NSPR failure while "
                                "%s %s", operation,
                                svrInfo.getURL().c_str());
                    }

                    if (AM_SUCCESS == status) {
                        break;
                    } else {
                        if (retryCount < retryAttempts) {
                            continue;
                        } else {
                            Log::log(logModule, Log::LOG_DEBUG,
                                    "BaseService::doRequest() Invoking markSeverDown");
                            /*svrInfo.markServerDown(poll_primary_server);*/
                        }
                    }
                } catch (const NSPRException& exc) {
                    Log::log(logModule, Log::LOG_ERROR,
                            "BaseService::doRequest() caught %s: %s called by %s", exc.what(), exc.getNsprMethod(),
                            exc.getThrowingMethod());

                    if (retryCount < retryAttempts) {
                        status = AM_NSPR_ERROR;
                        continue;
                    } else {
                        Log::log(logModule, Log::LOG_ERROR,
                                "BaseService::doRequest() Invoking markSeverDown");
                        /*svrInfo.markServerDown(poll_primary_server);*/
                        status = AM_NSPR_ERROR;
                    }
                }
            } //end of while

            if (AM_SUCCESS == status) {
                break;
            }

        } // end of for
    } else {
        status = AM_BUFFER_TOO_SMALL;
    }

    return status;
}