Browse Source

Merge branch 'http-improvements'

The base bits of pull req #1982.
0.8
Jeff Garzik 12 years ago committed by Jeff Garzik
parent
commit
8146591a53
  1. 69
      src/bitcoinrpc.cpp

69
src/bitcoinrpc.cpp

@ -360,6 +360,41 @@ static string HTTPReply(int nStatus, const string& strMsg, bool keepalive)
strMsg.c_str()); strMsg.c_str());
} }
bool ReadHTTPRequestLine(std::basic_istream<char>& stream, int &proto,
string& http_method, string& http_uri)
{
string str;
getline(stream, str);
// HTTP request line is space-delimited
vector<string> vWords;
boost::split(vWords, str, boost::is_any_of(" "));
if (vWords.size() < 2)
return false;
// HTTP methods permitted: GET, POST
http_method = vWords[0];
if (http_method != "GET" && http_method != "POST")
return false;
// HTTP URI must be an absolute path, relative to current host
http_uri = vWords[1];
if (http_uri.size() == 0 || http_uri[0] != '/')
return false;
// parse proto, if present
string strProto = "";
if (vWords.size() > 2)
strProto = vWords[2];
proto = 0;
const char *ver = strstr(strProto.c_str(), "HTTP/1.");
if (ver != NULL)
proto = atoi(ver+7);
return true;
}
int ReadHTTPStatus(std::basic_istream<char>& stream, int &proto) int ReadHTTPStatus(std::basic_istream<char>& stream, int &proto)
{ {
string str; string str;
@ -375,7 +410,7 @@ int ReadHTTPStatus(std::basic_istream<char>& stream, int &proto)
return atoi(vWords[1].c_str()); return atoi(vWords[1].c_str());
} }
int ReadHTTPHeader(std::basic_istream<char>& stream, map<string, string>& mapHeadersRet) int ReadHTTPHeaders(std::basic_istream<char>& stream, map<string, string>& mapHeadersRet)
{ {
int nLen = 0; int nLen = 0;
loop loop
@ -400,17 +435,15 @@ int ReadHTTPHeader(std::basic_istream<char>& stream, map<string, string>& mapHea
return nLen; return nLen;
} }
int ReadHTTP(std::basic_istream<char>& stream, map<string, string>& mapHeadersRet, string& strMessageRet) int ReadHTTPMessage(std::basic_istream<char>& stream, map<string,
string>& mapHeadersRet, string& strMessageRet,
int nProto)
{ {
mapHeadersRet.clear(); mapHeadersRet.clear();
strMessageRet = ""; strMessageRet = "";
// Read status
int nProto = 0;
int nStatus = ReadHTTPStatus(stream, nProto);
// Read header // Read header
int nLen = ReadHTTPHeader(stream, mapHeadersRet); int nLen = ReadHTTPHeaders(stream, mapHeadersRet);
if (nLen < 0 || nLen > (int)MAX_SIZE) if (nLen < 0 || nLen > (int)MAX_SIZE)
return HTTP_INTERNAL_SERVER_ERROR; return HTTP_INTERNAL_SERVER_ERROR;
@ -432,7 +465,7 @@ int ReadHTTP(std::basic_istream<char>& stream, map<string, string>& mapHeadersRe
mapHeadersRet["connection"] = "close"; mapHeadersRet["connection"] = "close";
} }
return nStatus; return HTTP_OK;
} }
bool HTTPAuthorized(map<string, string>& mapHeaders) bool HTTPAuthorized(map<string, string>& mapHeaders)
@ -939,10 +972,17 @@ void ThreadRPCServer3(void* parg)
} }
return; return;
} }
int nProto = 0;
map<string, string> mapHeaders; map<string, string> mapHeaders;
string strRequest; string strRequest, strMethod, strURI;
// Read HTTP request line
if (!ReadHTTPRequestLine(conn->stream(), nProto, strMethod, strURI))
break;
ReadHTTP(conn->stream(), mapHeaders, strRequest); // Read HTTP message headers and body
ReadHTTPMessage(conn->stream(), mapHeaders, strRequest, nProto);
// Check authorization // Check authorization
if (mapHeaders.count("authorization") == 0) if (mapHeaders.count("authorization") == 0)
@ -1074,10 +1114,15 @@ Object CallRPC(const string& strMethod, const Array& params)
string strPost = HTTPPost(strRequest, mapRequestHeaders); string strPost = HTTPPost(strRequest, mapRequestHeaders);
stream << strPost << std::flush; stream << strPost << std::flush;
// Receive reply // Receive HTTP reply status
int nProto = 0;
int nStatus = ReadHTTPStatus(stream, nProto);
// Receive HTTP reply message headers and body
map<string, string> mapHeaders; map<string, string> mapHeaders;
string strReply; string strReply;
int nStatus = ReadHTTP(stream, mapHeaders, strReply); ReadHTTPMessage(stream, mapHeaders, strReply, nProto);
if (nStatus == HTTP_UNAUTHORIZED) if (nStatus == HTTP_UNAUTHORIZED)
throw runtime_error("incorrect rpcuser or rpcpassword (authorization failed)"); throw runtime_error("incorrect rpcuser or rpcpassword (authorization failed)");
else if (nStatus >= 400 && nStatus != HTTP_BAD_REQUEST && nStatus != HTTP_NOT_FOUND && nStatus != HTTP_INTERNAL_SERVER_ERROR) else if (nStatus >= 400 && nStatus != HTTP_BAD_REQUEST && nStatus != HTTP_NOT_FOUND && nStatus != HTTP_INTERNAL_SERVER_ERROR)

Loading…
Cancel
Save