summaryrefslogtreecommitdiff
path: root/src/mongo/db/dbwebserver.cpp
diff options
context:
space:
mode:
authorKaloian Manassiev <kaloian.manassiev@mongodb.com>2015-03-25 15:17:12 -0400
committerKaloian Manassiev <kaloian.manassiev@mongodb.com>2015-03-26 10:05:05 -0400
commit8136a4d3138ab17188e6eab14c42cf61444f901b (patch)
treea6bceb22084c5711dfd6d8bbfd63bdf00c2d7735 /src/mongo/db/dbwebserver.cpp
parent3ab3f5e76a46d00a6c2d8a9e3464db83aef8d4ab (diff)
downloadmongo-8136a4d3138ab17188e6eab14c42cf61444f901b.tar.gz
SERVER-17653 Early allocate port for the HTTP interface
Diffstat (limited to 'src/mongo/db/dbwebserver.cpp')
-rw-r--r--src/mongo/db/dbwebserver.cpp764
1 files changed, 383 insertions, 381 deletions
diff --git a/src/mongo/db/dbwebserver.cpp b/src/mongo/db/dbwebserver.cpp
index 68c8ee3dd65..66e9ec6e53d 100644
--- a/src/mongo/db/dbwebserver.cpp
+++ b/src/mongo/db/dbwebserver.cpp
@@ -50,11 +50,11 @@
#include "mongo/db/db.h"
#include "mongo/db/global_environment_experiment.h"
#include "mongo/db/instance.h"
+#include "mongo/db/operation_context.h"
#include "mongo/db/stats/snapshots.h"
#include "mongo/util/admin_access.h"
#include "mongo/util/md5.hpp"
#include "mongo/util/mongoutils/html.h"
-#include "mongo/util/net/miniwebserver.h"
#include "mongo/util/ramlog.h"
#include "mongo/util/version.h"
#include "mongo/util/version_reporting.h"
@@ -68,6 +68,25 @@ namespace mongo {
using namespace html;
+namespace {
+
+ void doUnlockedStuff(stringstream& ss) {
+ // This is in the header already ss << "port: " << port << '\n'
+ ss << "<pre>";
+ ss << mongodVersion() << '\n';
+ ss << "git hash: " << gitVersion() << '\n';
+ ss << openSSLVersion("OpenSSL version: ", "\n");
+ ss << "sys info: " << sysInfo() << '\n';
+ ss << "uptime: " << time(0) - serverGlobalParams.started << " seconds\n";
+ ss << "</pre>";
+ }
+
+
+ bool prisort(const Prioritizable* a, const Prioritizable* b) {
+ return a->priority() < b->priority();
+ }
+
+
struct Timing {
Timing() {
start = timeLocked = 0;
@@ -75,254 +94,423 @@ namespace mongo {
unsigned long long start, timeLocked;
};
- class DbWebServer : public MiniWebServer {
- public:
- DbWebServer(const string& ip,
- int port,
- const AdminAccess* webUsers)
- : MiniWebServer("admin web console", ip, port),
- _webUsers(webUsers) {
- WebStatusPlugin::initAll();
+ class LogPlugin : public WebStatusPlugin {
+ public:
+ LogPlugin() : WebStatusPlugin("Log", 100), _log(0) {
+ _log = RamLog::get("global");
}
- private:
- const AdminAccess* _webUsers; // not owned here
-
- void doUnlockedStuff(stringstream& ss) {
- /* this is in the header already ss << "port: " << port << '\n'; */
- ss << "<pre>";
- ss << mongodVersion() << '\n';
- ss << "git hash: " << gitVersion() << '\n';
- ss << openSSLVersion("OpenSSL version: ", "\n");
- ss << "sys info: " << sysInfo() << '\n';
- ss << "uptime: " << time(0)-serverGlobalParams.started << " seconds\n";
- ss << "</pre>";
+ virtual void init() {}
+
+ virtual void run(OperationContext* txn, stringstream& ss) {
+ _log->toHTML(ss);
}
+ RamLog * _log;
+ };
- void _authorizePrincipal(OperationContext* txn, const UserName& userName) {
- Status status = cc().getAuthorizationSession()->addAndAuthorizeUser(txn, userName);
- uassertStatusOK(status);
+
+ class FavIconHandler : public DbWebHandler {
+ public:
+ FavIconHandler() : DbWebHandler("favicon.ico", 0, false) {}
+
+ virtual void handle(OperationContext* txn,
+ const char *rq, const std::string& url, BSONObj params,
+ string& responseMsg, int& responseCode,
+ vector<string>& headers, const SockAddr &from) {
+ responseCode = 404;
+ headers.push_back("Content-Type: text/plain;charset=utf-8");
+ responseMsg = "no favicon\n";
}
- bool allowed(OperationContext* txn,
- const char * rq,
- vector<string>& headers,
- const SockAddr &from) {
+ } faviconHandler;
- if ( !cc().getAuthorizationSession()->getAuthorizationManager().isAuthEnabled() ) {
- return true;
- }
- if ( from.isLocalHost() && !_webUsers->haveAdminUsers(txn) ) {
- cc().getAuthorizationSession()->grantInternalAuthorization();
- return true;
- }
+ class StatusHandler : public DbWebHandler {
+ public:
+ StatusHandler() : DbWebHandler("_status", 1, false) {}
+
+ virtual void handle(OperationContext* txn,
+ const char *rq, const std::string& url, BSONObj params,
+ string& responseMsg, int& responseCode,
+ vector<string>& headers, const SockAddr &from) {
+ headers.push_back("Content-Type: application/json;charset=utf-8");
+ responseCode = 200;
- string auth = getHeader( rq , "Authorization" );
+ static vector<string> commands;
+ if (commands.size() == 0) {
+ commands.push_back("serverStatus");
+ commands.push_back("buildinfo");
+ }
- if ( auth.size() > 0 && auth.find( "Digest " ) == 0 ) {
- auth = auth.substr( 7 ) + ", ";
+ BSONObjBuilder buf(1024);
- map<string,string> parms;
- pcrecpp::StringPiece input( auth );
+ for (unsigned i = 0; i<commands.size(); i++) {
+ string cmd = commands[i];
- string name, val;
- pcrecpp::RE re("(\\w+)=\"?(.*?)\"?,\\s*");
- while ( re.Consume( &input, &name, &val) ) {
- parms[name] = val;
- }
+ Command * c = Command::findCommand(cmd);
+ verify(c);
- // Only users in the admin DB are visible by the webserver
- UserName userName(parms["username"], "admin");
- User* user;
- AuthorizationManager& authzManager =
- cc().getAuthorizationSession()->getAuthorizationManager();
- Status status = authzManager.acquireUser(txn, userName, &user);
- if (!status.isOK()) {
- if (status.code() != ErrorCodes::UserNotFound) {
- uasserted(17051, status.reason());
- }
- } else {
- uassert(17090,
- "External users don't have a password",
- !user->getCredentials().isExternal);
- string ha1 = user->getCredentials().password;
- authzManager.releaseUser(user);
- if (ha1.empty()) {
- return false;
- }
+ BSONObj co;
+ {
+ BSONObjBuilder b;
+ b.append(cmd, 1);
- string ha2 = md5simpledigest( (string)"GET" + ":" + parms["uri"] );
-
- stringstream r;
- r << ha1 << ':' << parms["nonce"];
- if ( parms["nc"].size() && parms["cnonce"].size() && parms["qop"].size() ) {
- r << ':';
- r << parms["nc"];
- r << ':';
- r << parms["cnonce"];
- r << ':';
- r << parms["qop"];
+ if (cmd == "serverStatus" && params["repl"].type()) {
+ b.append("repl", atoi(params["repl"].valuestr()));
}
- r << ':';
- r << ha2;
- string r1 = md5simpledigest( r.str() );
- if ( r1 == parms["response"] ) {
- _authorizePrincipal(txn, userName);
- return true;
- }
+ co = b.obj();
}
+
+ string errmsg;
+
+ BSONObjBuilder sub;
+ if (!c->run(txn, "admin.$cmd", co, 0, errmsg, sub, false))
+ buf.append(cmd, errmsg);
+ else
+ buf.append(cmd, sub.obj());
}
- stringstream authHeader;
- authHeader
- << "WWW-Authenticate: "
- << "Digest realm=\"mongo\", "
- << "nonce=\"abc\", "
- << "algorithm=MD5, qop=\"auth\" "
- ;
+ responseMsg = buf.obj().jsonString();
+ }
- headers.push_back( authHeader.str() );
- return 0;
+ } statusHandler;
+
+
+ class CommandListHandler : public DbWebHandler {
+ public:
+ CommandListHandler() : DbWebHandler("_commands", 1, true) {}
+
+ virtual void handle(OperationContext* txn,
+ const char *rq, const std::string& url, BSONObj params,
+ string& responseMsg, int& responseCode,
+ vector<string>& headers, const SockAddr &from) {
+ headers.push_back("Content-Type: text/html;charset=utf-8");
+ responseCode = 200;
+
+ stringstream ss;
+ ss << start("Commands List");
+ ss << p(a("/", "back", "Home"));
+ ss << p("<b>MongoDB List of "
+ "<a href=\"http://dochub.mongodb.org/core/commands\">Commands</a>"
+ "</b>\n");
+
+ const Command::CommandMap* m = Command::commandsByBestName();
+ ss << "S:slave-ok R:read-lock W:write-lock A:admin-only<br>\n";
+ ss << table();
+ ss << "<tr><th>Command</th><th>Attributes</th><th>Help</th></tr>\n";
+ for (Command::CommandMap::const_iterator i = m->begin(); i != m->end(); ++i) {
+ i->second->htmlHelp(ss);
+ }
+ ss << _table() << _end();
+
+ responseMsg = ss.str();
}
+ } commandListHandler;
- virtual void doRequest(
- const char *rq, // the full request
- string url,
- // set these and return them:
- string& responseMsg,
- int& responseCode,
- vector<string>& headers, // if completely empty, content-type: text/html will be added
- const SockAddr &from
- ) {
- boost::scoped_ptr<OperationContext> txn(getGlobalEnvironment()->newOpCtx());
+ class CommandsHandler : public DbWebHandler {
+ public:
+ CommandsHandler() : DbWebHandler("DUMMY COMMANDS", 2, true) {}
- if ( url.size() > 1 ) {
+ bool _cmd(const string& url, string& cmd, bool& text, bo params) const {
+ cmd = str::after(url, '/');
+ text = params["text"].boolean();
+ return true;
+ }
- if (!allowed(txn.get(), rq, headers, from)) {
- responseCode = 401;
- headers.push_back( "Content-Type: text/plain;charset=utf-8" );
- responseMsg = "not allowed\n";
- return;
- }
+ Command * _cmd(const string& cmd) const {
+ const Command::CommandMap* m = Command::webCommands();
+ if (!m)
+ return 0;
- {
- BSONObj params;
- const size_t pos = url.find( "?" );
- if ( pos != string::npos ) {
- MiniWebServer::parseParams( params , url.substr( pos + 1 ) );
- url = url.substr(0, pos);
- }
+ Command::CommandMap::const_iterator i = m->find(cmd);
+ if (i == m->end())
+ return 0;
- DbWebHandler * handler = DbWebHandler::findHandler( url );
- if ( handler ) {
- if (handler->requiresREST(url) && !serverGlobalParams.rest) {
- _rejectREST( responseMsg , responseCode , headers );
- }
- else {
- string callback = params.getStringField("jsonp");
- uassert(13453, "server not started with --jsonp",
- callback.empty() || serverGlobalParams.jsonp);
+ return i->second;
+ }
- handler->handle( txn.get(), rq , url , params , responseMsg , responseCode , headers , from );
+ virtual bool handles(const string& url) const {
+ string cmd;
+ bool text;
+ if (!_cmd(url, cmd, text, bo()))
+ return false;
+ return _cmd(cmd) != 0;
+ }
- if (responseCode == 200 && !callback.empty()) {
- responseMsg = callback + '(' + responseMsg + ')';
- }
- }
- return;
- }
- }
+ virtual void handle(OperationContext* txn,
+ const char *rq, const std::string& url, BSONObj params,
+ string& responseMsg, int& responseCode,
+ vector<string>& headers, const SockAddr &from) {
+ string cmd;
+ bool text = false;
+ verify(_cmd(url, cmd, text, params));
+ Command * c = _cmd(cmd);
+ verify(c);
+ BSONObj cmdObj = BSON(cmd << 1);
- if (!serverGlobalParams.rest) {
- _rejectREST( responseMsg , responseCode , headers );
- return;
- }
+ BSONObjBuilder result;
+ Command::execCommand(txn, c, 0, "admin.", cmdObj, result, false);
- responseCode = 404;
- headers.push_back( "Content-Type: text/html;charset=utf-8" );
- responseMsg = "<html><body>unknown url</body></html>\n";
- return;
+ responseCode = 200;
+
+ string j = result.done().jsonString(Strict, text);
+ responseMsg = j;
+
+ if (text) {
+ headers.push_back("Content-Type: text/plain;charset=utf-8");
+ responseMsg += '\n';
+ }
+ else {
+ headers.push_back("Content-Type: application/json;charset=utf-8");
}
- // generate home page
+ }
+
+ } commandsHandler;
+
+
+ MONGO_INITIALIZER(WebStatusLogPlugin)(InitializerContext*) {
+ if (serverGlobalParams.isHttpInterfaceEnabled) {
+ new LogPlugin;
+ }
+ return Status::OK();
+ }
+
+} // namespace
- if (!allowed(txn.get(), rq, headers, from)) {
+
+ DbWebServer::DbWebServer(const string& ip, int port, const AdminAccess* webUsers)
+ : MiniWebServer("admin web console", ip, port),
+ _webUsers(webUsers) {
+
+ WebStatusPlugin::initAll();
+ }
+
+ void DbWebServer::doRequest(const char *rq,
+ string url,
+ string& responseMsg,
+ int& responseCode,
+ vector<string>& headers,
+ const SockAddr &from) {
+
+ boost::scoped_ptr<OperationContext> txn(getGlobalEnvironment()->newOpCtx());
+
+ if (url.size() > 1) {
+
+ if (!_allowed(txn.get(), rq, headers, from)) {
responseCode = 401;
- headers.push_back( "Content-Type: text/plain;charset=utf-8" );
+ headers.push_back("Content-Type: text/plain;charset=utf-8");
responseMsg = "not allowed\n";
return;
}
- responseCode = 200;
- stringstream ss;
- string dbname;
{
- stringstream z;
- z << serverGlobalParams.binaryName << ' ' << prettyHostName();
- dbname = z.str();
+ BSONObj params;
+ const size_t pos = url.find("?");
+ if (pos != string::npos) {
+ MiniWebServer::parseParams(params, url.substr(pos + 1));
+ url = url.substr(0, pos);
+ }
+
+ DbWebHandler * handler = DbWebHandler::findHandler(url);
+ if (handler) {
+ if (handler->requiresREST(url) && !serverGlobalParams.rest) {
+ _rejectREST(responseMsg, responseCode, headers);
+ }
+ else {
+ const string callback = params.getStringField("jsonp");
+
+ uassert(13453,
+ "server not started with --jsonp",
+ callback.empty() || serverGlobalParams.jsonp);
+
+ handler->handle(txn.get(),
+ rq,
+ url,
+ params,
+ responseMsg,
+ responseCode,
+ headers,
+ from);
+
+ if (responseCode == 200 && !callback.empty()) {
+ responseMsg = callback + '(' + responseMsg + ')';
+ }
+ }
+
+ return;
+ }
}
- ss << start(dbname) << h2(dbname);
- ss << "<p><a href=\"/_commands\">List all commands</a></p>\n";
- {
- const Command::CommandMap* m = Command::webCommands();
- if( m ) {
- ss <<
- a("",
- "These read-only context-less commands can be executed from the web interface. "
- "Results are json format, unless ?text=1 is appended in which case the result is output as text "
- "for easier human viewing",
- "Commands")
- << ": ";
- for( Command::CommandMap::const_iterator i = m->begin(); i != m->end(); ++i ) {
- stringstream h;
- i->second->help(h);
- string help = h.str();
- ss << "<a href=\"/" << i->first << "?text=1\"";
- if( help != "no help defined" )
- ss << " title=\"" << help << '"';
- ss << ">" << i->first << "</a> ";
+ if (!serverGlobalParams.rest) {
+ _rejectREST(responseMsg, responseCode, headers);
+ return;
+ }
+
+ responseCode = 404;
+ headers.push_back("Content-Type: text/html;charset=utf-8");
+ responseMsg = "<html><body>unknown url</body></html>\n";
+ return;
+ }
+
+ // generate home page
+
+ if (!_allowed(txn.get(), rq, headers, from)) {
+ responseCode = 401;
+ headers.push_back("Content-Type: text/plain;charset=utf-8");
+ responseMsg = "not allowed\n";
+ return;
+ }
+
+ responseCode = 200;
+ stringstream ss;
+ string dbname;
+ {
+ stringstream z;
+ z << serverGlobalParams.binaryName << ' ' << prettyHostName();
+ dbname = z.str();
+ }
+
+ ss << start(dbname) << h2(dbname);
+ ss << "<p><a href=\"/_commands\">List all commands</a></p>\n";
+
+ {
+ const Command::CommandMap* m = Command::webCommands();
+ if (m) {
+ ss << a("",
+ "These read-only context-less commands can be executed from the web "
+ "interface. Results are json format, unless ?text=1 is appended in which "
+ "case the result is output as text for easier human viewing",
+ "Commands")
+ << ": ";
+
+ for (Command::CommandMap::const_iterator i = m->begin(); i != m->end(); ++i) {
+ stringstream h;
+ i->second->help(h);
+
+ const string help = h.str();
+ ss << "<a href=\"/" << i->first << "?text=1\"";
+ if (help != "no help defined") {
+ ss << " title=\"" << help << '"';
}
- ss << '\n';
+
+ ss << ">" << i->first << "</a> ";
}
+ ss << '\n';
}
- ss << '\n';
- /*
- ss << "HTTP <a "
- "title=\"click for documentation on this http interface\""
- "href=\"http://dochub.mongodb.org/core/httpinterface\">admin port</a>:" << _port << "<p>\n";
- */
+ }
- doUnlockedStuff(ss);
+ ss << '\n';
- WebStatusPlugin::runAll(txn.get(), ss);
+ doUnlockedStuff(ss);
- ss << "</body></html>\n";
- responseMsg = ss.str();
- headers.push_back( "Content-Type: text/html;charset=utf-8" );
+ WebStatusPlugin::runAll(txn.get(), ss);
+
+ ss << "</body></html>\n";
+ responseMsg = ss.str();
+ headers.push_back("Content-Type: text/html;charset=utf-8");
+ }
+
+ bool DbWebServer::_allowed(OperationContext* txn,
+ const char * rq,
+ vector<string>& headers,
+ const SockAddr &from) {
+
+ AuthorizationSession* authSess = cc().getAuthorizationSession();
+ if (!authSess->getAuthorizationManager().isAuthEnabled()) {
+ return true;
}
- void _rejectREST( string& responseMsg , int& responseCode, vector<string>& headers ) {
- responseCode = 403;
- stringstream ss;
- ss << "REST is not enabled. use --rest to turn on.\n";
- ss << "check that port " << _port << " is secured for the network too.\n";
- responseMsg = ss.str();
- headers.push_back( "Content-Type: text/plain;charset=utf-8" );
+ if (from.isLocalHost() && !_webUsers->haveAdminUsers(txn)) {
+ authSess->grantInternalAuthorization();
+ return true;
}
- };
- // ---
+ string auth = getHeader(rq, "Authorization");
- bool prisort( const Prioritizable * a , const Prioritizable * b ) {
- return a->priority() < b->priority();
+ if (auth.size() > 0 && auth.find("Digest ") == 0) {
+ auth = auth.substr(7) + ", ";
+
+ map<string, string> parms;
+ pcrecpp::StringPiece input(auth);
+
+ string name, val;
+ pcrecpp::RE re("(\\w+)=\"?(.*?)\"?,\\s*");
+ while (re.Consume(&input, &name, &val)) {
+ parms[name] = val;
+ }
+
+ // Only users in the admin DB are visible by the webserver
+ UserName userName(parms["username"], "admin");
+ User* user;
+ AuthorizationManager& authzManager =
+ cc().getAuthorizationSession()->getAuthorizationManager();
+ Status status = authzManager.acquireUser(txn, userName, &user);
+ if (!status.isOK()) {
+ if (status.code() != ErrorCodes::UserNotFound) {
+ uasserted(17051, status.reason());
+ }
+ }
+ else {
+ uassert(17090,
+ "External users don't have a password",
+ !user->getCredentials().isExternal);
+
+ string ha1 = user->getCredentials().password;
+ authzManager.releaseUser(user);
+ if (ha1.empty()) {
+ return false;
+ }
+
+ const string ha2 = md5simpledigest((string)"GET" + ":" + parms["uri"]);
+
+ stringstream r;
+ r << ha1 << ':' << parms["nonce"];
+ if (parms["nc"].size() && parms["cnonce"].size() && parms["qop"].size()) {
+ r << ':';
+ r << parms["nc"];
+ r << ':';
+ r << parms["cnonce"];
+ r << ':';
+ r << parms["qop"];
+ }
+ r << ':';
+ r << ha2;
+
+ const string r1 = md5simpledigest(r.str());
+
+ if (r1 == parms["response"]) {
+ Status status = authSess->addAndAuthorizeUser(txn, userName);
+ uassertStatusOK(status);
+ return true;
+ }
+ }
+ }
+
+ stringstream authHeader;
+ authHeader << "WWW-Authenticate: "
+ << "Digest realm=\"mongo\", "
+ << "nonce=\"abc\", "
+ << "algorithm=MD5, qop=\"auth\" ";
+
+ headers.push_back(authHeader.str());
+ return 0;
}
+ void DbWebServer::_rejectREST(string& responseMsg, int& responseCode, vector<string>& headers) {
+ responseCode = 403;
+ stringstream ss;
+ ss << "REST is not enabled. use --rest to turn on.\n";
+ ss << "check that port " << _port << " is secured for the network too.\n";
+ responseMsg = ss.str();
+ headers.push_back("Content-Type: text/plain;charset=utf-8");
+ }
+
+
// -- status framework ---
WebStatusPlugin::WebStatusPlugin( const string& secionName , double priority , const string& subheader )
: Prioritizable(priority), _name( secionName ) , _subHeading( subheader ) {
@@ -361,30 +549,6 @@ namespace mongo {
vector<WebStatusPlugin*> * WebStatusPlugin::_plugins = 0;
- // -- basic status plugins --
-
- class LogPlugin : public WebStatusPlugin {
- public:
- LogPlugin() : WebStatusPlugin( "Log" , 100 ), _log(0) {
- _log = RamLog::get( "global" );
- }
-
- virtual void init() {}
-
- virtual void run(OperationContext* txn, stringstream& ss ) {
- _log->toHTML( ss );
- }
- RamLog * _log;
- };
-
- MONGO_INITIALIZER(WebStatusLogPlugin)(InitializerContext*) {
- if (serverGlobalParams.isHttpInterfaceEnabled) {
- new LogPlugin;
- }
- return Status::OK();
- }
-
- // -- handler framework ---
DbWebHandler::DbWebHandler( const string& name , double priority , bool requiresREST )
: Prioritizable(priority), _name(name) , _requiresREST(requiresREST) {
@@ -423,173 +587,11 @@ namespace mongo {
vector<DbWebHandler*> * DbWebHandler::_handlers = 0;
- // --- basic handlers ---
-
- class FavIconHandler : public DbWebHandler {
- public:
- FavIconHandler() : DbWebHandler( "favicon.ico" , 0 , false ) {}
-
- virtual void handle( OperationContext* txn,
- const char *rq, const std::string& url, BSONObj params,
- string& responseMsg, int& responseCode,
- vector<string>& headers, const SockAddr &from ) {
- responseCode = 404;
- headers.push_back( "Content-Type: text/plain;charset=utf-8" );
- responseMsg = "no favicon\n";
- }
-
- } faviconHandler;
-
- class StatusHandler : public DbWebHandler {
- public:
- StatusHandler() : DbWebHandler( "_status" , 1 , false ) {}
-
- virtual void handle( OperationContext* txn,
- const char *rq, const std::string& url, BSONObj params,
- string& responseMsg, int& responseCode,
- vector<string>& headers, const SockAddr &from ) {
- headers.push_back( "Content-Type: application/json;charset=utf-8" );
- responseCode = 200;
-
- static vector<string> commands;
- if ( commands.size() == 0 ) {
- commands.push_back( "serverStatus" );
- commands.push_back( "buildinfo" );
- }
-
- BSONObjBuilder buf(1024);
-
- for ( unsigned i=0; i<commands.size(); i++ ) {
- string cmd = commands[i];
-
- Command * c = Command::findCommand( cmd );
- verify( c );
-
- BSONObj co;
- {
- BSONObjBuilder b;
- b.append( cmd , 1 );
-
- if ( cmd == "serverStatus" && params["repl"].type() ) {
- b.append( "repl" , atoi( params["repl"].valuestr() ) );
- }
-
- co = b.obj();
- }
-
- string errmsg;
-
- BSONObjBuilder sub;
- if ( ! c->run( txn, "admin.$cmd" , co , 0, errmsg , sub , false ) )
- buf.append( cmd , errmsg );
- else
- buf.append( cmd , sub.obj() );
- }
-
- responseMsg = buf.obj().jsonString();
-
- }
-
- } statusHandler;
-
- class CommandListHandler : public DbWebHandler {
- public:
- CommandListHandler() : DbWebHandler( "_commands" , 1 , true ) {}
-
- virtual void handle( OperationContext* txn,
- const char *rq, const std::string& url, BSONObj params,
- string& responseMsg, int& responseCode,
- vector<string>& headers, const SockAddr &from ) {
- headers.push_back( "Content-Type: text/html;charset=utf-8" );
- responseCode = 200;
-
- stringstream ss;
- ss << start("Commands List");
- ss << p( a("/", "back", "Home") );
- ss << p( "<b>MongoDB List of <a href=\"http://dochub.mongodb.org/core/commands\">Commands</a></b>\n" );
- const Command::CommandMap* m = Command::commandsByBestName();
- ss << "S:slave-ok R:read-lock W:write-lock A:admin-only<br>\n";
- ss << table();
- ss << "<tr><th>Command</th><th>Attributes</th><th>Help</th></tr>\n";
- for( Command::CommandMap::const_iterator i = m->begin(); i != m->end(); ++i )
- i->second->htmlHelp(ss);
- ss << _table() << _end();
-
- responseMsg = ss.str();
- }
- } commandListHandler;
-
- class CommandsHandler : public DbWebHandler {
- public:
- CommandsHandler() : DbWebHandler( "DUMMY COMMANDS" , 2 , true ) {}
-
- bool _cmd( const string& url , string& cmd , bool& text, bo params ) const {
- cmd = str::after(url, '/');
- text = params["text"].boolean();
- return true;
- }
-
- Command * _cmd( const string& cmd ) const {
- const Command::CommandMap* m = Command::webCommands();
- if( ! m )
- return 0;
-
- Command::CommandMap::const_iterator i = m->find(cmd);
- if ( i == m->end() )
- return 0;
-
- return i->second;
- }
-
- virtual bool handles( const string& url ) const {
- string cmd;
- bool text;
- if ( ! _cmd( url , cmd , text, bo() ) )
- return false;
- return _cmd(cmd) != 0;
- }
-
- virtual void handle( OperationContext* txn,
- const char *rq, const std::string& url, BSONObj params,
- string& responseMsg, int& responseCode,
- vector<string>& headers, const SockAddr &from ) {
- string cmd;
- bool text = false;
- verify( _cmd( url , cmd , text, params ) );
- Command * c = _cmd( cmd );
- verify( c );
-
- BSONObj cmdObj = BSON( cmd << 1 );
-
- BSONObjBuilder result;
- Command::execCommand(txn, c, 0, "admin.", cmdObj , result, false);
-
- responseCode = 200;
-
- string j = result.done().jsonString(Strict, text );
- responseMsg = j;
-
- if( text ) {
- headers.push_back( "Content-Type: text/plain;charset=utf-8" );
- responseMsg += '\n';
- }
- else {
- headers.push_back( "Content-Type: application/json;charset=utf-8" );
- }
-
- }
-
- } commandsHandler;
+ void webServerListenThread(boost::shared_ptr<DbWebServer> dbWebServer) {
+ Client::initThread("websvr");
- // --- external ----
+ dbWebServer->initAndListen();
- void webServerThread(const AdminAccess* adminAccess) {
- boost::scoped_ptr<const AdminAccess> adminAccessPtr(adminAccess); // adminAccess is owned here
- Client::initThread("websvr");
- const int p = serverGlobalParams.port + 1000;
- DbWebServer mini(serverGlobalParams.bind_ip, p, adminAccessPtr.get());
- mini.setupSockets();
- mini.initAndListen();
cc().shutdown();
}