*m = Command::webCommands();
if( m && m->count(cmd) ) {
Command *c = m->find(cmd)->second;
Client& client = cc();
BSONObjBuilder result;
BSONObjBuilder b;
b.append(c->name, 1);
BSONObj cmdObj = b.obj();
bool ok =
execCommand(c, client, 0, "admin.", cmdObj, result, false);
responseCode = 200;
string j = result.done().jsonString(JS, h != 0 ? 1 : 0);
if( h == 0 ) {
headers.push_back( "Content-Type: application/json" );
}
else {
headers.push_back( "Content-Type: text/plain" );
}
responseMsg = j;
return;
}
}
if ( url.find( "/_status" ) == 0 ){
if ( ! allowed( rq , headers, from ) ){
responseCode = 401;
responseMsg = "not allowed\n";
return;
}
headers.push_back( "Content-Type: application/json" );
generateServerStatus( url , responseMsg );
responseCode = 200;
return;
}
if ( ! cmdLine.rest ){
responseCode = 403;
responseMsg = "rest is not enabled. use --rest to turn on";
return;
}
if ( ! allowed( rq , headers, from ) ){
responseCode = 401;
responseMsg = "not allowed\n";
return;
}
handleRESTRequest( rq , url , responseMsg , responseCode , headers );
return;
}
responseCode = 200;
stringstream ss;
ss << "";
string dbname;
{
stringstream z;
z << "mongod " << "host:" << getHostName() << " port:" << mongo::cmdLine.port << ' ';
dbname = z.str();
}
ss << dbname << "" << dbname << "
\n";
ss << "
";
//ss << "_status";
{
const map *m = Command::webCommands();
if( m ) {
for( map::const_iterator i = m->begin(); i != m->end(); i++ ) {
ss << "first << "?text\">" << i->first << " ";
}
ss << "\n";
}
}
ss << "\n";
doUnlockedStuff(ss);
{
Timer t;
readlocktry lk( "" , 2000 );
if ( lk.got() ){
ss << "time to get dblock: " << t.millis() << "ms\n";
doLockedStuff(ss);
}
else {
ss << "\ntimed out getting dblock\n";
}
}
ss << "";
responseMsg = ss.str();
// we want to return SavedContext from before the authentication was performed
if ( ! allowed( rq , headers, from ) ){
responseCode = 401;
responseMsg = "not allowed\n";
return;
}
}
void generateServerStatus( string url , string& responseMsg ){
static vector commands;
if ( commands.size() == 0 ){
commands.push_back( "serverStatus" );
commands.push_back( "buildinfo" );
}
BSONObj params;
if ( url.find( "?" ) != string::npos ) {
parseParams( params , url.substr( url.find( "?" ) + 1 ) );
}
BSONObjBuilder buf(1024);
for ( unsigned i=0; ilocktype() == 0 );
BSONObj co;
{
BSONObjBuilder b;
b.append( cmd.c_str() , 1 );
if ( cmd == "serverStatus" && params["repl"].type() ){
b.append( "repl" , atoi( params["repl"].valuestr() ) );
}
co = b.obj();
}
string errmsg;
BSONObjBuilder sub;
if ( ! c->run( "admin.$cmd" , co , errmsg , sub , false ) )
buf.append( cmd.c_str() , errmsg );
else
buf.append( cmd.c_str() , sub.obj() );
}
responseMsg = buf.obj().jsonString();
}
void handleRESTRequest( const char *rq, // the full request
string url,
string& responseMsg,
int& responseCode,
vector& headers // if completely empty, content-type: text/html will be added
) {
string::size_type first = url.find( "/" , 1 );
if ( first == string::npos ) {
responseCode = 400;
return;
}
string method = parseMethod( rq );
string dbname = url.substr( 1 , first - 1 );
string coll = url.substr( first + 1 );
string action = "";
BSONObj params;
if ( coll.find( "?" ) != string::npos ) {
parseParams( params , coll.substr( coll.find( "?" ) + 1 ) );
coll = coll.substr( 0 , coll.find( "?" ) );
}
string::size_type last = coll.find_last_of( "/" );
if ( last == string::npos ) {
action = coll;
coll = "_defaultCollection";
}
else {
action = coll.substr( last + 1 );
coll = coll.substr( 0 , last );
}
for ( string::size_type i=0; i cursor = db.query( ns.c_str() , query, num , skip );
uassert( 13085 , "query failed for dbwebserver" , cursor.get() );
if ( one ) {
if ( cursor->more() ) {
BSONObj obj = cursor->next();
out << obj.jsonString() << "\n";
}
else {
responseCode = 404;
}
return;
}
out << "{\n";
out << " \"offset\" : " << skip << ",\n";
out << " \"rows\": [\n";
int howMany = 0;
while ( cursor->more() ) {
if ( howMany++ )
out << " ,\n";
BSONObj obj = cursor->next();
out << " " << obj.jsonString();
}
out << "\n ],\n\n";
out << " \"total_rows\" : " << howMany << " ,\n";
out << " \"query\" : " << query.jsonString() << " ,\n";
out << " \"millis\" : " << t.millis() << "\n";
out << "}\n";
}
// TODO Generate id and revision per couch POST spec
void handlePost( string ns, const char *body, BSONObj& params, int & responseCode, stringstream & out ) {
try {
BSONObj obj = fromjson( body );
db.insert( ns.c_str(), obj );
} catch ( ... ) {
responseCode = 400; // Bad Request. Seems reasonable for now.
out << "{ \"ok\" : false }";
return;
}
responseCode = 201;
out << "{ \"ok\" : true }";
}
int _getOption( BSONElement e , int def ) {
if ( e.isNumber() )
return e.numberInt();
if ( e.type() == String )
return atoi( e.valuestr() );
return def;
}
private:
static DBDirectClient db;
};
DBDirectClient DbWebServer::db;
void webServerThread() {
Client::initThread("websvr");
const int p = cmdLine.port + 1000;
DbWebServer mini(bind_ip, p);
log() << "web admin interface listening on port " << p << endl;
mini.initAndListen();
cc().shutdown();
}
} // namespace mongo