0
0
mirror of https://github.com/mongodb/mongo.git synced 2024-12-01 09:32:32 +01:00
mongodb/util/miniwebserver.cpp

207 lines
5.6 KiB
C++
Raw Normal View History

2008-11-30 02:01:58 +01:00
// miniwebserver.cpp
/* Copyright 2009 10gen Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
2008-11-30 02:01:58 +01:00
2010-04-27 21:27:52 +02:00
#include "pch.h"
2008-11-30 02:01:58 +01:00
#include "miniwebserver.h"
#include "hex.h"
2008-11-30 02:01:58 +01:00
2009-01-30 21:05:28 +01:00
#include <pcrecpp.h>
2009-01-14 23:09:51 +01:00
namespace mongo {
2010-04-05 14:57:44 +02:00
MiniWebServer::MiniWebServer(const string &ip, int port)
: Listener(ip, port, false)
2010-04-05 14:57:44 +02:00
{}
2008-11-30 02:01:58 +01:00
string MiniWebServer::parseURL( const char * buf ) {
2010-04-20 21:41:47 +02:00
const char * urlStart = strchr( buf , ' ' );
if ( ! urlStart )
return "/";
2009-01-14 23:17:24 +01:00
urlStart++;
2009-01-14 23:17:24 +01:00
2010-04-20 21:41:47 +02:00
const char * end = strchr( urlStart , ' ' );
2009-01-14 23:17:24 +01:00
if ( ! end ) {
2010-04-20 18:29:00 +02:00
end = strchr( urlStart , '\r' );
if ( ! end ) {
2010-04-20 18:29:00 +02:00
end = strchr( urlStart , '\n' );
}
2008-12-31 03:58:36 +01:00
}
2009-01-14 23:17:24 +01:00
if ( ! end )
return "/";
2009-01-14 23:17:24 +01:00
int diff = (int)(end-urlStart);
if ( diff < 0 || diff > 255 )
return "/";
2009-01-14 23:17:24 +01:00
return string( urlStart , (int)(end-urlStart) );
}
2008-12-31 03:58:36 +01:00
void MiniWebServer::parseParams( BSONObj & params , string query ) {
if ( query.size() == 0 )
return;
2011-01-04 06:40:41 +01:00
BSONObjBuilder b;
while ( query.size() ) {
2011-01-04 06:40:41 +01:00
string::size_type amp = query.find( "&" );
2009-01-14 23:17:24 +01:00
string cur;
if ( amp == string::npos ) {
cur = query;
query = "";
}
else {
cur = query.substr( 0 , amp );
query = query.substr( amp + 1 );
}
string::size_type eq = cur.find( "=" );
if ( eq == string::npos )
continue;
2010-07-20 18:58:58 +02:00
b.append( urlDecode(cur.substr(0,eq)) , urlDecode(cur.substr(eq+1) ) );
2008-12-31 20:58:42 +01:00
}
2011-01-04 06:40:41 +01:00
params = b.obj();
}
2008-12-31 20:58:42 +01:00
string MiniWebServer::parseMethod( const char * headers ) {
2010-04-20 21:41:47 +02:00
const char * end = strchr( headers , ' ' );
if ( ! end )
return "GET";
return string( headers , (int)(end-headers) );
}
2009-01-14 23:17:24 +01:00
const char *MiniWebServer::body( const char *buf ) {
const char *ret = strstr( buf, "\r\n\r\n" );
return ret ? ret + 4 : ret;
2008-12-31 20:58:42 +01:00
}
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(int s, const SockAddr &from) {
setSockTimeouts(s, 8);
char buf[4096];
int len = 0;
while ( 1 ) {
2010-06-27 03:29:07 +02:00
int left = sizeof(buf) - 1 - len;
if( left == 0 )
break;
int x = ::recv(s, buf + len, left, 0);
if ( x <= 0 ) {
closesocket(s);
return;
}
len += x;
buf[ len ] = 0;
2010-06-27 03:29:07 +02:00
if ( fullReceive( buf ) ) {
break;
2010-06-27 03:29:07 +02:00
}
}
buf[len] = 0;
string responseMsg;
int responseCode = 599;
vector<string> headers;
2011-01-04 06:40:41 +01:00
try {
doRequest(buf, parseURL( buf ), responseMsg, responseCode, headers, from);
}
2011-01-04 06:40:41 +01:00
catch ( std::exception& e ) {
responseCode = 500;
responseMsg = "error loading page: ";
responseMsg += e.what();
}
2011-01-04 06:40:41 +01:00
catch ( ... ) {
responseCode = 500;
2010-01-19 16:09:13 +01:00
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 {
2010-04-20 03:05:46 +02:00
for ( vector<string>::iterator i = headers.begin(); i != headers.end(); i++ ) {
assert( strncmp("Content-Length", i->c_str(), 14) );
ss << *i << "\r\n";
2010-04-20 03:05:46 +02:00
}
}
2010-04-20 03:05:46 +02:00
ss << "Connection: close\r\n";
ss << "Content-Length: " << responseMsg.size() << "\r\n";
ss << "\r\n";
ss << responseMsg;
string response = ss.str();
::send(s, response.c_str(), response.size(), 0);
2010-04-05 14:57:44 +02:00
closesocket(s);
2008-11-30 02:01:58 +01:00
}
2011-01-04 06:40:41 +01:00
string MiniWebServer::getHeader( const char * req , string wanted ) {
2010-04-20 18:29:00 +02:00
const char * headers = strchr( req , '\n' );
2009-01-30 21:05:28 +01:00
if ( ! headers )
return "";
pcrecpp::StringPiece input( headers + 1 );
2011-01-04 06:40:41 +01:00
2009-01-30 21:05:28 +01:00
string name;
string val;
pcrecpp::RE re("([\\w\\-]+): (.*?)\r?\n");
2011-01-04 06:40:41 +01:00
while ( re.Consume( &input, &name, &val) ) {
2009-01-30 21:05:28 +01:00
if ( name == wanted )
return val;
}
return "";
}
2009-01-14 23:09:51 +01:00
2011-01-04 06:40:41 +01:00
string MiniWebServer::urlDecode(const char* s) {
stringstream out;
2011-01-04 06:40:41 +01:00
while(*s) {
if (*s == '+') {
out << ' ';
2011-01-04 06:40:41 +01:00
}
else if (*s == '%') {
out << fromHex(s+1);
s+=2;
2011-01-04 06:40:41 +01:00
}
else {
out << *s;
}
s++;
}
return out.str();
}
2009-01-14 23:09:51 +01:00
} // namespace mongo