0
0
mirror of https://github.com/mongodb/mongo.git synced 2024-11-30 00:56:44 +01:00
mongodb/util/miniwebserver.cpp

199 lines
5.5 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
#include "stdafx.h"
#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;
BSONObjBuilder b;
while ( query.size() ) {
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;
b.append( urlDecode(cur.substr(0,eq)).c_str() , urlDecode(cur.substr(eq+1) ) );
2008-12-31 20:58:42 +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) {
char buf[4096];
int len = 0;
while ( 1 ) {
int x = ::recv(s, buf + len, sizeof(buf) - 1 - len, 0);
if ( x <= 0 ) {
return;
}
len += x;
buf[ len ] = 0;
if ( fullReceive( buf ) )
break;
}
buf[len] = 0;
string responseMsg;
int responseCode = 599;
vector<string> headers;
try {
doRequest(buf, parseURL( buf ), responseMsg, responseCode, headers, from);
}
catch ( std::exception& e ){
responseCode = 500;
responseMsg = "error loading page: ";
responseMsg += e.what();
}
2010-01-19 16:09:13 +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
}
2009-01-30 21:05:28 +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 );
string name;
string val;
pcrecpp::RE re("([\\w\\-]+): (.*?)\r?\n");
while ( re.Consume( &input, &name, &val) ){
if ( name == wanted )
return val;
}
return "";
}
2009-01-14 23:09:51 +01:00
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++;
}
return out.str();
}
2009-01-14 23:09:51 +01:00
} // namespace mongo