/** * Check a GET to a url returns a certain code and data. */ static void _checkUrlText( TestRunner& tr, Url* url, int code, const char* expected, int length) { // create client HttpClient client; // connect assertNoException(client.connect(url)); if(tr.getVerbosityLevel() > 1) { printf("Connected to: %s\n", url->toString().c_str()); InternetAddress address(url->getHost().c_str(), url->getPort()); printf("%s\n", address.toString().c_str()); } // do get HttpResponse* response = client.get(url); assert(response != NULL); if(tr.getVerbosityLevel() > 1) { printf("Response header:\n%s\n", response->getHeader()->toString().c_str()); } if(response->getHeader()->getStatusCode() != code) { printf("Expecting response status code: %d, got %d\n", response->getHeader()->getStatusCode(), code); } assert(response->getHeader()->getStatusCode() == code); // receive content HttpTrailer trailer; ByteBuffer b; ByteArrayOutputStream baos(&b); assertNoException(client.receiveContent(&baos, &trailer)); // put data in strings for strcmp since it may not be NULL terminated string strexpected; strexpected.assign(expected, length); string strdata; strdata.assign(b.data(), b.length()); if(tr.getVerbosityLevel() > 1) { printf("Response content (%d bytes):\n%s\n", b.length(), strdata.c_str()); printf("Response trailers:\n%s\n", trailer.toString().c_str()); } // check content assertStrCmp(strdata.c_str(), strexpected.c_str()); assert(b.length() == length); client.disconnect(); assertNoExceptionSet(); }
static void runHttpClientPostTest(TestRunner& tr) { tr.test("Http Client POST"); // create client HttpClient client; // connect Url url("http://www.bitmunk.com"); if(client.connect(&url)) { printf("Connected to: %s\n", url.toString().c_str()); InternetAddress address(url.getHost().c_str(), url.getPort()); printf("%s\n", address.toString().c_str()); char someData[] = "Just some post data."; ByteArrayInputStream baos(someData, strlen(someData)); // do post DynamicObject headers; headers["Content-Type"] = "text/plain"; headers["Transfer-Encoding"] = "chunked"; HttpTrailer trailer; HttpResponse* response = client.post(&url, &headers, &baos, &trailer); if(response != NULL) { printf("Response=\n%s\n", response->getHeader()->toString().c_str()); if(response->getHeader()->getStatusCode() == 200) { // receive content trailer.clearFields(); File file("/tmp/postresponse.txt"); FileOutputStream fos(file); if(client.receiveContent(&fos, &trailer)) { printf("Content downloaded to '%s'\n", file->getAbsolutePath()); printf("HTTP trailers=\n%s\n", trailer.toString().c_str()); } assertNoExceptionSet(); } } else { printf("There was no response!\n"); } client.disconnect(); } tr.passIfNoException(); }
static void runHttpClientGetTest(TestRunner& tr) { tr.test("Http Client GET"); // create client HttpClient client; // connect Url url("http://www.bitmunk.com"); if(client.connect(&url)) { printf("Connected to: %s\n", url.toString().c_str()); InternetAddress address(url.getHost().c_str(), url.getPort()); printf("%s\n", address.toString().c_str()); // do get DynamicObject headers; headers["Test-Header"] = "bacon"; HttpResponse* response = client.get(&url, &headers); if(response != NULL) { printf("Response=\n%s\n", response->getHeader()->toString().c_str()); if(response->getHeader()->getStatusCode() == 200) { // receive content HttpTrailer trailer; File file("/tmp/index.html"); FileOutputStream fos(file); if(client.receiveContent(&fos, &trailer)) { printf("Content downloaded to '%s'\n", file->getAbsolutePath()); printf("HTTP trailers=\n%s\n", trailer.toString().c_str()); } assertNoExceptionSet(); } } else { printf("There was no response!\n"); } client.disconnect(); } tr.passIfNoException(); }
void HttpProtocol::parseHttpResponse(const std::string& res,HttpResponse& http) { string response(res); int pos; if( (pos = res.find("\n\r"))!= -1) response = response.replace(pos,2,"\n\n"); HttpHeader header; http.getHeader(header); string str(response); string delim = "\n"; vector<string> vec; split(str,delim,vec); parseResponseLine(vec[0],http); int i = 1; while(vec[i] != "") { parseHeader(vec[i],header); i++; } i++; for(;i<vec.size();i++) { string tmp(http.getContent()); tmp = tmp+vec[i]; if(i != vec.size()-1) tmp+="\n"; http.setContent(tmp); } }
static void runHttpClientRedirectLoopTest(TestRunner& tr) { tr.test("Http Client Redirect Loop"); // start a kernel Kernel k; k.getEngine()->start(); // create server Server server; InternetAddress address("0.0.0.0", 19123); // create SSL/generic http connection servicer HttpConnectionServicer hcs; server.addConnectionService(&address, &hcs); // create redirect loop http request servicer RedirectLoopHttpRequestServicer loop("/loop"); hcs.addRequestServicer(&loop, false); if(server.start(&k)) { printf("\nServer started on %s\n", address.toString(false).c_str()); // create client HttpClient client; printf("Connecting and expecting a redirect loop...\n"); // do get Url url("http://localhost:19123/loop"); HttpResponse* response = client.get(&url, NULL, 2); if(response != NULL) { printf("Response=\n%s\n", response->getHeader()->toString().c_str()); } else { printf("Correctly detected an exception:\n"); printf("'%s'\n", Exception::get()->getMessage()); } client.disconnect(); } else if(Exception::get() != NULL) { printf("\nServer start failed with errors=%s\n", Exception::get()->getMessage()); } tr.passIfException(); // stop server and kernel server.stop(); k.getEngine()->stop(); Exception::clear(); }
bool HttpServer::sendResponse( SOCKET socket, HttpResponse &response){ sendString( socket, response.getHeader() ); sendString( socket, response.getDocument() ); close( socket ); return true; }
void HttpProtocol::geneHttpResponse(const HttpResponse& http,string& response) { HttpHeader header; http.getHeader(header); char t[10]; sprintf(t, "%d", http.getStatusCode()); string code = t; response = "" + http.getVersion() + " " + code + " " + http.getReason() + "\n"; geneHeader(response,header); response += http.getContent(); }
bool Http11Handler::writeResponse(void* req, void* res, void* context) { HttpRequest* request = (HttpRequest*)req; HttpResponse* response = (HttpResponse*)res; if(isClosed()) { if(request!=NULL) { delete request; } delete response; return true; } if(!response->isDone()) { response->updateContent(request, chunkSize); } if(response->getHeader(HttpRequest::Connection)=="") { if(StringUtil::toLowerCopy(request->getHeader(HttpRequest::Connection))!="keep-alive" || CastUtil::lexical_cast<int>(response->getStatusCode())>307 || request->getHttpVers()<1.1) { response->addHeaderValue(HttpResponse::Connection, "close"); } else { response->addHeaderValue(HttpResponse::Connection, "keep-alive"); } } std::string data = response->generateOnlyHeaderResponse(request); if(!write(data)) { bool isFirst = true; while(response->hasContent && (data = response->getRemainingContent(request->getUrl(), isFirst)) != "") { isFirst = false; if(write(data)) { break; } } } if(request!=NULL) { delete request; } delete response; return true; }
void ProxyResourceHandler::operator()(BtpAction* action) { // get request host HttpRequestHeader* hrh = action->getRequest()->getHeader(); string host = hrh->getFieldValue("X-Forwarded-Host"); if(host.length() == 0) { host = hrh->getFieldValue("Host"); } // find a rule Rule* rule = findRule(action, host); if(rule == NULL) { // delegate to rest resource handler RestResourceHandler::operator()(action); } else { // get URL to proxy or redirect to UrlRef url = rule->url; // get url host string urlHost; HttpResponse* res = action->getResponse(); bool secure = res->getConnection()->isSecure(); // if URL has no host, reuse incoming host if(url->getHost().length() == 0) { urlHost = host; } // if URL has no port or uses a default port number, only use URL host else if( (url->getPort() == 0) || (secure && url->getPort() == 443) || (!secure && url->getPort() == 80)) { urlHost = url->getHost(); } // use URL host and port else { urlHost = url->getHostAndPort(); } // handle 0.0.0.0 (any host) by replacing it with the request host if(strncmp(urlHost.c_str(), "0.0.0.0", 8) == 0) { // 0.0.0.0 is 8 chars long urlHost.replace(0, 8, host.substr(0, host.find(':')).c_str()); } // rewrite the request path if it does not match URL path string path = hrh->getPath(); if(strcmp(path.c_str(), url->getPath().c_str()) != 0) { // check for path wildcard if(strcmp(rule->path, "*") == 0) { // since a wildcard is used, prepend the URL path to the // resource (if the url path isn't '/') string urlPath = url->getPath(); if(urlPath.length() > 1) { path.insert(0, url->getPath().c_str()); } } else { // replace the part of the resource that matched the proxy // rule with the rewrite path from the proxy URL path.replace(0, strlen(rule->path), url->getPath().c_str()); } } // do redirect if appropriate if(rule->type == Rule::Redirect) { // set response code HttpResponseHeader* header = res->getHeader(); if(rule->permanent) { header->setStatus(301, "Moved Permanently"); } else { header->setStatus(302, "Found"); } // build new location url bool secure = res->getConnection()->isSecure(); header->setField("Location", StringTools::format("%s://%s%s", secure ? "https" : "http", urlHost.c_str(), path.c_str())); action->sendResult(); } // do proxy else if(rule->type == Rule::Proxy) { // get client-side request HttpRequest* req = action->getRequest(); // do path rewrite hrh->setPath(path.c_str()); // add X-Forwarded headers hrh->appendFieldValue("X-Forwarded-For", req->getConnection()->getRemoteAddress()->toString(true).c_str()); hrh->appendFieldValue("X-Forwarded-Host", hrh->getFieldValue("Host").c_str()); hrh->appendFieldValue("X-Forwarded-Server", SocketTools::getHostname().c_str()); // rewrite host if rule specifies it if(rule->rewriteHost) { hrh->setField("Host", urlHost.c_str()); } // do proxy: MO_CAT_INFO(BM_NODE_CAT, "ProxyResourceHandler proxying %s%s => %s%s", host.c_str(), hrh->getPath(), urlHost.c_str(), path.c_str()); MO_CAT_DEBUG(BM_NODE_CAT, "ProxyResourceHandler request header for %s%s => %s%s:\n%s", host.c_str(), hrh->getPath(), urlHost.c_str(), path.c_str(), hrh->toString().c_str()); // get a connection BtpClient* btpc = mNode->getMessenger()->getBtpClient(); HttpConnection* conn = btpc->createConnection(false, &(*url)); if(conn == NULL) { // send service unavailable HttpResponseHeader* header = action->getResponse()->getHeader(); header->setStatus(503, "Service Unavailable"); string content = "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\n" "<html><head>\n" "<title>503 Service Unavailable</title>\n" "</head><body>\n" "<h1>Service Unavailable</h1>\n" "<p>The service was not available.</p>\n" "</body></html>"; ByteBuffer b(content.length()); b.put(content.c_str(), content.length(), false); ByteArrayInputStream bais(&b); action->sendResult(&bais); } else { // proxy the client's request and receive server's header (by // writing it into the client's response header) HttpResponse* res = action->getResponse(); if(_proxyHttp(req->getHeader(), req->getConnection(), conn) && conn->receiveHeader(res->getHeader())) { // proxy the server's response, consider result sent _proxyHttp(res->getHeader(), conn, req->getConnection()); action->setResultSent(true); } // close connection conn->close(); // clean up delete conn; } if(!action->isResultSent()) { // send exception (client's fault if code < 500) ExceptionRef e = Exception::get(); action->sendException(e, e->getCode() < 500); } } } }
static int mod_ffeadcpp_method_handler (request_rec *r) { string port = CastUtil::lexical_cast<string>(r->server->port); //signal(SIGSEGV,signalSIGSEGV); string content; apr_bucket_brigade *bb = apr_brigade_create(r->pool, r->connection->bucket_alloc); for ( ; ; ) { apr_bucket* b ; bool done = false; ap_get_brigade(r->input_filters, bb, AP_MODE_READBYTES, APR_BLOCK_READ, HUGE_STRING_LEN); for ( b = APR_BRIGADE_FIRST(bb);b != APR_BRIGADE_SENTINEL(bb);b = APR_BUCKET_NEXT(b) ) { size_t bytes ; const char* buf = "\0"; if ( APR_BUCKET_IS_EOS(b) ) { done = true; } else if (apr_bucket_read(b, &buf, &bytes, APR_BLOCK_READ)== APR_SUCCESS ) { content += string(buf, 0, bytes); } } if (done) break; else apr_brigade_cleanup(bb) ; } apr_brigade_destroy(bb) ; HttpRequest* hreq= new HttpRequest(); string cntpath = serverRootDirectory + "web/"; string webpath = "URL" + cntpath; MyReq* req = new MyReq(); req->r = r; req->htreq = hreq; apr_table_do(iterate_func, req, r->headers_in, NULL); ip_address = hreq->getHeader(HttpRequest::Host); string tipaddr = ip_address; if(port!="80") tipaddr += (":" + port); ConfigurationData::getInstance()->ip_address = tipaddr; string contret; if(content!="") { contret = hreq->buildRequest("Content",content.c_str()); fprintf(stderr,contret.c_str()); fflush(stderr); } hreq->buildRequest(webpath.c_str(),r->uri); hreq->buildRequest("Method",r->method); if(r->args != NULL && r->args[0] != '\0') { hreq->buildRequest("GetArguments",r->args); } hreq->buildRequest("HttpVersion", r->protocol); HttpResponse respo = service(hreq); string h1 = respo.generateResponse(hreq->getMethod(), hreq, false); for (int var = 0; var < (int)respo.getCookies().size(); var++) { apr_table_add(r->headers_out, "Set-cookie", respo.getCookies().at(var).c_str()); } r->status_line = respo.getStatusLine().c_str(); if(respo.getHeader(HttpResponse::ContentType)!="") { r->content_type = respo.getHeader(HttpResponse::ContentType).c_str(); } r->clength = h1.length(); fprintf(stderr,"\n\n\n\n--------------------------------------------\n"); fprintf(stderr,hreq->getUrl().c_str()); fprintf(stderr,"\n"); string star = hreq->toString(); fprintf(stderr,star.c_str()); fprintf(stderr,"\n--------------------------------------------\n"); fprintf(stderr,contret.c_str()); fflush(stderr); fprintf(stderr,"\n\n"); fprintf(stderr,content.c_str()); fprintf(stderr,"\n"); fprintf(stderr,"ip_address = %s", tipaddr.c_str()); fprintf(stderr,"\n"); fprintf(stderr,"\n--------------------------------------------\n\n\n\n"); fflush(stderr); fprintf(stderr, h1.c_str()); fflush(stderr); delete hreq; delete req; if(h1!="") { ap_rwrite (h1.c_str(), h1.length(), r); return OK; } return OK; }
void HttpConnectionServicer::serviceConnection(Connection* c) { // wrap connection, set default timeouts to 30 seconds HttpConnection hc(c, false); hc.setReadTimeout(30000); hc.setWriteTimeout(30000); // monitor connection if(!mConnectionMonitor.isNull()) { mConnectionMonitor->beforeServicingConnection(&hc); } // create request HttpRequest* request = hc.createRequest(); HttpRequestHeader* reqHeader = request->getHeader(); // create response HttpResponse* response = request->createResponse(); HttpResponseHeader* resHeader = response->getHeader(); // handle keep-alive (HTTP/1.1 keep-alive is on by default) bool keepAlive = true; bool noerror = true; while(keepAlive && noerror) { // set defaults resHeader->setVersion("HTTP/1.1"); resHeader->setDate(); resHeader->setField("Server", mServerName); // monitor request waiting if(!mConnectionMonitor.isNull()) { mConnectionMonitor->beforeRequest(&hc); } // receive request header if((noerror = request->receiveHeader())) { // begin new request state hc.getRequestState()->beginRequest(); // monitor received request if(!mConnectionMonitor.isNull()) { mConnectionMonitor->beforeServicingRequest( &hc, request, response); } // do request modification if(mRequestModifier != NULL) { mRequestModifier->modifyRequest(request); } // check http version bool version10 = (strcmp(reqHeader->getVersion(), "HTTP/1.0") == 0); bool version11 = (strcmp(reqHeader->getVersion(), "HTTP/1.1") == 0); // only version 1.0 and 1.1 supported if(version10 || version11) { // set response version according to request version resHeader->setVersion(reqHeader->getVersion()); // use proxy'd host field if one was used // else use host field if one was used string host; if(reqHeader->getField("X-Forwarded-Host", host) || reqHeader->getField("Host", host)) { resHeader->setField("Host", host); } // get connection header string connHeader; if(reqHeader->getField("Connection", connHeader)) { if(strcasecmp(connHeader.c_str(), "close") == 0) { keepAlive = false; } else if(strcasecmp(connHeader.c_str(), "keep-alive") == 0) { keepAlive = true; } } else if(version10) { // if HTTP/1.0 and no keep-alive header, keep-alive is off keepAlive = false; } // get request path and normalize it const char* inPath = reqHeader->getPath(); char outPath[strlen(inPath) + 2]; HttpRequestServicer::normalizePath(inPath, outPath); // find appropriate request servicer for path HttpRequestServicer* hrs = NULL; // find secure/non-secure servicer hrs = findRequestServicer(host, outPath, hc.isSecure()); if(hrs != NULL) { // service request hrs->serviceRequest(request, response); // turn off keep-alive if response has close connection field if(keepAlive) { if(resHeader->getField("Connection", connHeader) && strcasecmp(connHeader.c_str(), "close") == 0) { keepAlive = false; } } // if servicer closed connection, turn off keep-alive if(keepAlive && c->isClosed()) { keepAlive = false; } } else { // no servicer, so send 404 Not Found const char* html = "<html><body><h2>404 Not Found</h2></body></html>"; resHeader->setStatus(404, "Not Found"); resHeader->setField("Content-Type", "text/html"); resHeader->setField("Content-Length", 48); resHeader->setField("Connection", "close"); if((noerror = response->sendHeader())) { ByteArrayInputStream is(html, 48); noerror = response->sendBody(&is); } } } else { // send 505 HTTP Version Not Supported const char* html = "<html><body>" "<h2>505 HTTP Version Not Supported</h2>" "</body></html>"; resHeader->setStatus(505, "HTTP Version Not Supported"); resHeader->setField("Content-Type", "text/html"); resHeader->setField("Content-Length", 65); resHeader->setField("Connection", "close"); if((noerror = response->sendHeader())) { ByteArrayInputStream is(html, 65); noerror = response->sendBody(&is); } } // monitor serviced request if(!mConnectionMonitor.isNull()) { mConnectionMonitor->afterServicingRequest( &hc, request, response); } } else { // begin new request state hc.getRequestState()->beginRequest(); // monitor request error if(!mConnectionMonitor.isNull()) { mConnectionMonitor->beforeRequestError( &hc, request, response); } // exception occurred while receiving header ExceptionRef e = Exception::get(); // if no header then drop through and close connection if(e->isType("monarch.http.NoHeader")) { keepAlive = false; } // for bad header or request set 400 else if(e->isType("monarch.http.BadHeader") || e->isType("monarch.http.BadRequest")) { // send 400 Bad Request const char* html = "<html><body><h2>400 Bad Request</h2></body></html>"; response->getHeader()->setStatus(400, "Bad Request"); response->getHeader()->setField("Content-Type", "text/html"); response->getHeader()->setField("Content-Length", 50); response->getHeader()->setField("Connection", "close"); if(response->sendHeader()) { ByteArrayInputStream is(html, 50); response->sendBody(&is); } } // if the exception was an interruption, then send a 503 else if(e->isType("monarch.io.InterruptedException") || e->isType("monarch.rt.Interrupted")) { // send 503 Service Unavailable const char* html = "<html><body><h2>503 Service Unavailable</h2></body></html>"; resHeader->setStatus(503, "Service Unavailable"); resHeader->setField("Content-Type", "text/html"); resHeader->setField("Content-Length", 58); resHeader->setField("Connection", "close"); if((noerror = response->sendHeader())) { ByteArrayInputStream is(html, 58); noerror = response->sendBody(&is); } } // if the exception was not a socket error then send an internal // server error response else if(!e->isType("monarch.net.Socket", true)) { // send 500 Internal Server Error const char* html = "<html><body><h2>500 Internal Server Error</h2></body></html>"; resHeader->setStatus(500, "Internal Server Error"); resHeader->setField("Content-Type", "text/html"); resHeader->setField("Content-Length", 60); resHeader->setField("Connection", "close"); if((noerror = response->sendHeader())) { ByteArrayInputStream is(html, 60); noerror = response->sendBody(&is); } } else { // log socket error if(e->getDetails()->hasMember("error")) { // build error string string error; DynamicObjectIterator i = e->getDetails()["error"].getIterator(); while(i->hasNext()) { error.append(i->next()->getString()); if(i->hasNext()) { error.push_back(','); } } MO_CAT_ERROR(MO_HTTP_CAT, "Connection error: ['%s','%s','%s']", e->getMessage(), e->getType(), error.c_str()); } else { MO_CAT_ERROR(MO_HTTP_CAT, "Connection error: ['%s','%s']", e->getMessage(), e->getType()); } } // monitor request error if(!mConnectionMonitor.isNull()) { mConnectionMonitor->afterRequestError( &hc, request, response, e); } } // monitor request if(!mConnectionMonitor.isNull()) { mConnectionMonitor->afterRequest(&hc); } if(keepAlive && noerror) { // set keep-alive timeout (defaults to 5 minutes) hc.setReadTimeout(1000 * 60 * 5); // clear request and response header fields reqHeader->clearFields(); resHeader->clearFields(); resHeader->clearStatus(); } } // clean up request and response delete request; delete response; // monitor connection if(!mConnectionMonitor.isNull()) { mConnectionMonitor->afterServicingConnection(&hc); } // close connection hc.close(); }
int main() { #ifdef OS_MINGW // startup WinSock in Windows WSADATA wsa_data; WSAStartup(MAKEWORD(1,1), &wsa_data); #endif PropFileReader propFileReader; propMap props = propFileReader.getProperties("testValues.prop"); CsvFileReader csvFileReader; strVecVec testCases = csvFileReader.getRows("test.csv"); Timer timer, timerc; std::string cookies, result; int total, skipped = 0, passed = 0, failed = 0, header = 0, counter = 0; total = (int)testCases.size(); std::string ip = props["SERVER_IP_ADDRESS"]; if(ip=="") ip = "localhost"; int port = 8080; if(props["SERVER_PORT"]!="") { try{ port = CastUtil::lexical_cast<int>(props["SERVER_PORT"]); } catch(...) { } } bool sslEnabled = false; if(props["SERVER_SSL_ENABLED"]!="") { try{ sslEnabled = CastUtil::lexical_cast<bool>(props["SERVER_SSL_ENABLED"]); } catch(...) { } } std::string sslFile = props["SERVER_SSL_FILE"]; bool isDebug = false; if(StringUtil::toLowerCopy(props["DEBUG"])=="true") { isDebug = true; } std::cout << "Server IP - " << ip <<std::endl; std::cout << "Server Port - " << port <<std::endl; std::cout << "Debug Mode - " << isDebug <<std::endl; std::cout << "Server SSL Enabled - " << CastUtil::lexical_cast<std::string>(sslEnabled) <<std::endl; if(sslEnabled) { std::cout << "Server SSL File - " << sslFile <<std::endl; } timerc.start(); for (int var = 0; var < total; ++var) { ClientInterface* client; if(sslEnabled) { if(sslFile!="") client = new SSLClient(sslFile); else client = new SSLClient; } else client = new Client; if(testCases[var].size()>=4) { if(testCases[var][0]=="ENABLED") { header++; continue; } counter = var; std::string request = testCases[var][2]; if(testCases[var][0]=="N" || testCases[var][0]=="n") { std::cout << "Request " << counter << " " << request << " was Skipped" << std::endl; skipped++; continue; } bool debugCont = false; std::string debugContStr = testCases[var][1]; if(debugContStr=="Y" || debugContStr=="y") debugCont = true; std::string responseCode = testCases[var][3]; std::string file; if(testCases[var].size()>4) file = testCases[var][4]; std::string fileCntlen; if(testCases[var].size()>5) fileCntlen = testCases[var][5]; std::string reqContTyp, content, headers, respCntType; if(testCases[var].size()>6) { reqContTyp = testCases[var][6]; } if(testCases[var].size()>7) { content = testCases[var][7]; } if(testCases[var].size()>8) { headers = testCases[var][8]; if(headers!="" && headers.find("HEADERVALS_")!=std::string::npos) { headers = props[headers]; } else { std::vector<std::string> headerVec; StringUtil::split(headerVec, headers, ";"); headers = ""; for (int var = 0; var < (int)headerVec.size(); ++var) { std::vector<std::string> param; StringUtil::split(param, headerVec.at(var), "="); if(param.size()==2) { headers += param.at(0) + ": " + param.at(1) + "\r\n"; } } } } if(testCases[var].size()>9) { respCntType = testCases[var][9]; } std::string data = request; data += " HTTP/1.1\r\nHost: "+ip+":"+CastUtil::lexical_cast<std::string>(port)+"\r\nUser-Agent: Program\r\n"; if(content!="" && content.find("TSTVALUES_")!=std::string::npos) content = props[content]; if(reqContTyp!="") { data += "Content-Type: " + reqContTyp + "\r\n"; } if(content.length()>0) { data += "Content-Length: " + CastUtil::lexical_cast<std::string>((int)content.length()) + "\r\n"; } if(cookies!="") { data += "Cookie: " + cookies + "\r\n"; } if(headers!="") { data += headers; } data += "\r\n"; if(content!="") { data += content; } timer.start(); if(isDebug) { std::cout << "HTTP Request Is=>\n" << data << "\n\n" << std::endl; } client->connectionUnresolv(ip,port); int bytes = client->sendData(data); std::string tot = client->getTextData("\r\n","content-length"); long long millis = timer.elapsedMilliSeconds(); if(isDebug) { std::cout << "HTTP Response Is=>\n" << tot << "\n\n" << std::endl; } HttpResponse res; HttpResponseParser parser(tot, res); if(res.getHeader("Set-Cookie")!="") { cookies = res.getHeader("Set-Cookie"); cookies = cookies.substr(0, cookies.find(";")); } std::string debugContentValue; if(debugCont) { debugContentValue = ", Content => " + parser.getContent(); } std::string ss; bool passedFlag = false, done = false; if(res.getStatusCode()==responseCode) { if(respCntType!="") { if(res.getHeader("Content-Type")==respCntType) { ss.clear(); ss = "Test " + CastUtil::lexical_cast<std::string>(counter) + " " + request + " was Successfull, Response Time = " + CastUtil::lexical_cast<std::string>(millis) + "ms" + debugContentValue; passedFlag = true; } else { ss.clear(); ss = "Test " + CastUtil::lexical_cast<std::string>(counter) + " " + request + " Failed, Response Time = " + CastUtil::lexical_cast<std::string>(millis) + "ms" + ", Expected ContentType = " + respCntType + ", Actual ContentType = " + res.getHeader("Content-Type"); passedFlag = false; } done = true; } if(!done) { std::string cntlen = res.getHeader("Content-Length"); if(file!="") { std::ifstream myfile (&file[0], std::ios::binary | std::ios::ate); if (myfile.is_open() && cntlen!="" && myfile.tellg()==CastUtil::lexical_cast<int>(cntlen)) { ss.clear(); ss = "Test " + CastUtil::lexical_cast<std::string>(counter) + " " + request + " was Successfull, Response Time = " + CastUtil::lexical_cast<std::string>(millis) + "ms" + debugContentValue; passedFlag = true; } else { ss.clear(); ss = "Test " + CastUtil::lexical_cast<std::string>(counter) + " " + request + ", Invalid Content Length, Response Time = " + CastUtil::lexical_cast<std::string>(millis) + "ms" + debugContentValue; passedFlag = false; } } else if((file=="" && fileCntlen=="") || (fileCntlen!="" && fileCntlen==cntlen)) { ss.clear(); ss = "Test " + CastUtil::lexical_cast<std::string>(counter) + " " + request + " was Successfull, Response Time = " + CastUtil::lexical_cast<std::string>(millis) + "ms" + debugContentValue; passedFlag = true; } else { ss.clear(); ss = "Test " + CastUtil::lexical_cast<std::string>(counter) + " " + request + ", Invalid Content Length, Response Time = " + CastUtil::lexical_cast<std::string>(millis) + "ms" + debugContentValue; passedFlag = false; } } } else { ss.clear(); ss = "Test " + CastUtil::lexical_cast<std::string>(counter) + " " + request + " Failed, Response Time = " + CastUtil::lexical_cast<std::string>(millis) + "ms" + ", Expected Status = " + responseCode + ", Actual Status = " + res.getStatusCode(); passedFlag = false; } std::cout << ss << std::endl; if(passedFlag) passed++; else failed++; } else { skipped++; } if(client!=NULL) { client->closeConnection(); delete client; } } std::cout << "Total Tests = " << total-1 << ", Passed = " << passed << ", Failed = " << failed << ", Skipped = " << skipped << ", Time taken = " << timerc.elapsedMilliSeconds() << "ms" << std::endl; #ifdef OS_MINGW WSACleanup(); #endif return 0; }
/** * A helper function that sends a soap envelope and gets its result. * * @param device the service to connect to. * @param service the service to use. * @param msg the soap message to send. * @param result the result to populate. * * @return true if successful, false if an exception occurred. */ static bool doSoap( Service& service, SoapMessage& msg, ActionResult& result) { bool rval = false; // create the soap envelope SoapEnvelope env; string envelope = env.create(msg); if(envelope.length() > 0) { // get the control url for the service Url url; url.format("%s%s", service["rootURL"]->getString(), service["controlURL"]->getString()); MO_CAT_DEBUG(MO_UPNP_CAT, "Sending SOAP message to url '%s':\n%s", url.toString().c_str(), envelope.c_str()); // do http connection HttpClient client; if((rval = client.connect(&url))) { // create special headers DynamicObject headers; headers["Connection"] = "close"; headers["Content-Length"] = (uint32_t)envelope.length(); headers["Content-Type"] = "text/xml; charset=\"utf-8\""; headers["Soapaction"] = StringTools::format("\"%s#%s\"", service["serviceType"]->getString(), msg["name"]->getString()).c_str(); // do post Url path(url.getPath()); ByteArrayInputStream bais(envelope.c_str(), envelope.length()); HttpResponse* response = client.post(&path, &headers, &bais); if((rval = (response != NULL))) { MO_CAT_DEBUG(MO_UPNP_CAT, "Received response header:\n%s", response->getHeader()->toString().c_str()); // receive response ByteBuffer bb(1024); ByteArrayOutputStream baos(&bb, true); if((rval = client.receiveContent(&baos))) { MO_CAT_DEBUG(MO_UPNP_CAT, "Received SOAP message:\n%s", string(bb.data(), bb.length()).c_str()); // parse soap response ByteArrayInputStream bais2(&bb); SoapResult sr; rval = env.parse(&bais2, sr); if(!rval) { // failure to parse response ExceptionRef e = new Exception( "Could not parse soap response.", "monarch.upnp.InvalidSoapResponse"); Exception::push(e); } else if(sr["fault"]->getBoolean()) { // soap fault received ExceptionRef e = new Exception( "Could not perform SOAP transfer. SOAP fault received.", "monarch.upnp.SoapFault"); e->getDetails()["fault"] = sr["message"]; Exception::set(e); rval = false; result = sr; } else { // return result as soap result result = sr; } } } // disconnect client.disconnect(); } } if(!rval) { MO_CAT_ERROR(MO_UPNP_CAT, "Could not perform SOAP transfer: %s", JsonWriter::writeToString( Exception::getAsDynamicObject()).c_str()); } return rval; }
bool ControlPoint::getDescription(Url* url, string& description) { bool rval = false; MO_CAT_DEBUG(MO_UPNP_CAT, "Getting UPnP description from url '%s'...", url->toString().c_str()); // do http connection HttpClient client; if((rval = client.connect(url))) { // create special headers DynamicObject headers; headers["Connection"] = "close"; // do get Url path(url->getPath()); HttpResponse* response = client.get(&path, &headers); if((rval = (response != NULL))) { MO_CAT_DEBUG(MO_UPNP_CAT, "Get UPnP description response header:\n%s", response->getHeader()->toString().c_str()); // receive response ByteBuffer bb(2048); ByteArrayOutputStream baos(&bb, true); if((rval = client.receiveContent(&baos))) { MO_CAT_DEBUG(MO_UPNP_CAT, "Get UPnP description response body:\n%s", string(bb.data(), bb.length()).c_str()); if(response->getHeader()->getStatusCode() < 400) { // get description description.erase(); description.append(bb.data(), bb.length()); } else { // error getting description ExceptionRef e = new Exception( "HTTP transmission error.", "monarch.upnp.HttpError"); e->getDetails()["statusMessage"] = response->getHeader()->getStatusMessage(); e->getDetails()["statusCode"] = response->getHeader()->getStatusCode(); } } } // disconnect client.disconnect(); } if(!rval) { MO_CAT_ERROR(MO_UPNP_CAT, "Failed to get UPnP description from url '%s': %s", url->toString().c_str(), JsonWriter::writeToString( Exception::getAsDynamicObject()).c_str()); } return rval; }