diff options
Diffstat (limited to 'src/mongo/util/net/miniwebserver.cpp')
-rw-r--r-- | src/mongo/util/net/miniwebserver.cpp | 339 |
1 files changed, 165 insertions, 174 deletions
diff --git a/src/mongo/util/net/miniwebserver.cpp b/src/mongo/util/net/miniwebserver.cpp index 888ca70e4de..fc86f95b24f 100644 --- a/src/mongo/util/net/miniwebserver.cpp +++ b/src/mongo/util/net/miniwebserver.cpp @@ -41,205 +41,196 @@ namespace mongo { - using std::shared_ptr; - using std::endl; - using std::stringstream; - using std::vector; - - MiniWebServer::MiniWebServer(const string& name, const string &ip, int port) - : Listener(name, ip, port, false) - {} - - string MiniWebServer::parseURL( const char * buf ) { - const char * urlStart = strchr( buf , ' ' ); - if ( ! urlStart ) - return "/"; - - urlStart++; - - const char * end = strchr( urlStart , ' ' ); - if ( ! end ) { - end = strchr( urlStart , '\r' ); - if ( ! end ) { - end = strchr( urlStart , '\n' ); - } +using std::shared_ptr; +using std::endl; +using std::stringstream; +using std::vector; + +MiniWebServer::MiniWebServer(const string& name, const string& ip, int port) + : Listener(name, ip, port, false) {} + +string MiniWebServer::parseURL(const char* buf) { + const char* urlStart = strchr(buf, ' '); + if (!urlStart) + return "/"; + + urlStart++; + + const char* end = strchr(urlStart, ' '); + if (!end) { + end = strchr(urlStart, '\r'); + if (!end) { + end = strchr(urlStart, '\n'); } - - if ( ! end ) - return "/"; - - int diff = (int)(end-urlStart); - if ( diff < 0 || diff > 255 ) - return "/"; - - return string( urlStart , (int)(end-urlStart) ); } - void MiniWebServer::parseParams( BSONObj & params , string query ) { - if ( query.size() == 0 ) - return; + if (!end) + return "/"; - BSONObjBuilder b; - while ( query.size() ) { + int diff = (int)(end - urlStart); + if (diff < 0 || diff > 255) + return "/"; - string::size_type amp = query.find( "&" ); + return string(urlStart, (int)(end - urlStart)); +} - string cur; - if ( amp == string::npos ) { - cur = query; - query = ""; - } - else { - cur = query.substr( 0 , amp ); - query = query.substr( amp + 1 ); - } +void MiniWebServer::parseParams(BSONObj& params, string query) { + if (query.size() == 0) + return; - string::size_type eq = cur.find( "=" ); - if ( eq == string::npos ) - continue; + BSONObjBuilder b; + while (query.size()) { + string::size_type amp = query.find("&"); - b.append( urlDecode(cur.substr(0,eq)) , urlDecode(cur.substr(eq+1) ) ); + string cur; + if (amp == string::npos) { + cur = query; + query = ""; + } else { + cur = query.substr(0, amp); + query = query.substr(amp + 1); } - params = b.obj(); - } + string::size_type eq = cur.find("="); + if (eq == string::npos) + continue; - string MiniWebServer::parseMethod( const char * headers ) { - const char * end = strchr( headers , ' ' ); - if ( ! end ) - return "GET"; - return string( headers , (int)(end-headers) ); + b.append(urlDecode(cur.substr(0, eq)), urlDecode(cur.substr(eq + 1))); } - const char *MiniWebServer::body( const char *buf ) { - const char *ret = strstr( buf, "\r\n\r\n" ); - return ret ? ret + 4 : ret; - } + params = b.obj(); +} - bool MiniWebServer::fullReceive( const char *buf ) { - const char *bod = body( buf ); - if ( !bod ) - return false; - const char *lenString = "Content-Length:"; - const char *lengthLoc = strstr( buf, lenString ); - if ( !lengthLoc ) - return true; - lengthLoc += strlen( lenString ); - long len = strtol( lengthLoc, 0, 10 ); - if ( long( strlen( bod ) ) == len ) - return true; - return false; - } +string MiniWebServer::parseMethod(const char* headers) { + const char* end = strchr(headers, ' '); + if (!end) + return "GET"; + return string(headers, (int)(end - headers)); +} - void MiniWebServer::accepted(std::shared_ptr<Socket> psock, long long connectionId ) { - char buf[4096]; - int len = 0; - try { +const char* MiniWebServer::body(const char* buf) { + const char* ret = strstr(buf, "\r\n\r\n"); + return ret ? ret + 4 : ret; +} + +bool MiniWebServer::fullReceive(const char* buf) { + const char* bod = body(buf); + if (!bod) + return false; + const char* lenString = "Content-Length:"; + const char* lengthLoc = strstr(buf, lenString); + if (!lengthLoc) + return true; + lengthLoc += strlen(lenString); + long len = strtol(lengthLoc, 0, 10); + if (long(strlen(bod)) == len) + return true; + return false; +} + +void MiniWebServer::accepted(std::shared_ptr<Socket> psock, long long connectionId) { + char buf[4096]; + int len = 0; + try { #ifdef MONGO_CONFIG_SSL - psock->doSSLHandshake(); + psock->doSSLHandshake(); #endif - psock->setTimeout(8); - while ( 1 ) { - int left = sizeof(buf) - 1 - len; - if( left == 0 ) - break; - int x; - try { - x = psock->unsafe_recv( buf + len , left ); - } catch (const SocketException&) { - psock->close(); - return; - } - len += x; - buf[ len ] = 0; - if ( fullReceive( buf ) ) { - break; - } + psock->setTimeout(8); + while (1) { + int left = sizeof(buf) - 1 - len; + if (left == 0) + break; + int x; + try { + x = psock->unsafe_recv(buf + len, left); + } catch (const SocketException&) { + psock->close(); + return; } - } - catch (const SocketException& e) { - LOG(1) << "couldn't recv data via http client: " << e << endl; - return; - } - buf[len] = 0; - - string responseMsg; - int responseCode = 599; - vector<string> headers; - - try { - doRequest(buf, parseURL( buf ), responseMsg, responseCode, headers, psock->remoteAddr() ); - } - catch ( std::exception& e ) { - responseCode = 500; - responseMsg = "error loading page: "; - responseMsg += e.what(); - } - catch ( ... ) { - responseCode = 500; - responseMsg = "unknown error loading page"; - } - - stringstream ss; - ss << "HTTP/1.0 " << responseCode; - if ( responseCode == 200 ) ss << " OK"; - ss << "\r\n"; - if ( headers.empty() ) { - ss << "Content-Type: text/html\r\n"; - } - else { - for ( vector<string>::iterator i = headers.begin(); i != headers.end(); i++ ) { - verify( strncmp("Content-Length", i->c_str(), 14) ); - ss << *i << "\r\n"; + len += x; + buf[len] = 0; + if (fullReceive(buf)) { + break; } } - ss << "Connection: close\r\n"; - ss << "Content-Length: " << responseMsg.size() << "\r\n"; - ss << "\r\n"; - ss << responseMsg; - string response = ss.str(); - - try { - psock->send( response.c_str(), response.size() , "http response" ); - psock->close(); - } - catch ( SocketException& e ) { - LOG(1) << "couldn't send data to http client: " << e << endl; - } + } catch (const SocketException& e) { + LOG(1) << "couldn't recv data via http client: " << e << endl; + return; + } + buf[len] = 0; + + string responseMsg; + int responseCode = 599; + vector<string> headers; + + try { + doRequest(buf, parseURL(buf), responseMsg, responseCode, headers, psock->remoteAddr()); + } catch (std::exception& e) { + responseCode = 500; + responseMsg = "error loading page: "; + responseMsg += e.what(); + } catch (...) { + responseCode = 500; + responseMsg = "unknown error loading page"; } - string MiniWebServer::getHeader( const char * req , const std::string& wanted ) { - const char * headers = strchr( req , '\n' ); - if ( ! headers ) - return ""; - pcrecpp::StringPiece input( headers + 1 ); - - string name; - string val; - pcrecpp::RE re("([\\w\\-]+): (.*?)\r?\n"); - while ( re.Consume( &input, &name, &val) ) { - if ( name == wanted ) - return val; + stringstream ss; + ss << "HTTP/1.0 " << responseCode; + if (responseCode == 200) + ss << " OK"; + ss << "\r\n"; + if (headers.empty()) { + ss << "Content-Type: text/html\r\n"; + } else { + for (vector<string>::iterator i = headers.begin(); i != headers.end(); i++) { + verify(strncmp("Content-Length", i->c_str(), 14)); + ss << *i << "\r\n"; } - return ""; } + ss << "Connection: close\r\n"; + ss << "Content-Length: " << responseMsg.size() << "\r\n"; + ss << "\r\n"; + ss << responseMsg; + string response = ss.str(); + + try { + psock->send(response.c_str(), response.size(), "http response"); + psock->close(); + } catch (SocketException& e) { + LOG(1) << "couldn't send data to http client: " << e << endl; + } +} - string MiniWebServer::urlDecode(const char* s) { - stringstream out; - while(*s) { - if (*s == '+') { - out << ' '; - } - else if (*s == '%') { - out << fromHex(s+1); - s+=2; - } - else { - out << *s; - } - s++; +string MiniWebServer::getHeader(const char* req, const std::string& wanted) { + const char* headers = strchr(req, '\n'); + if (!headers) + return ""; + pcrecpp::StringPiece input(headers + 1); + + string name; + string val; + pcrecpp::RE re("([\\w\\-]+): (.*?)\r?\n"); + while (re.Consume(&input, &name, &val)) { + if (name == wanted) + return val; + } + return ""; +} + +string MiniWebServer::urlDecode(const char* s) { + stringstream out; + while (*s) { + if (*s == '+') { + out << ' '; + } else if (*s == '%') { + out << fromHex(s + 1); + s += 2; + } else { + out << *s; } - return out.str(); + s++; } + return out.str(); +} -} // namespace mongo +} // namespace mongo |