261 lines
No EOL
6.5 KiB
C++
261 lines
No EOL
6.5 KiB
C++
// Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
|
|
// Copyright (C) 2010 Winch Gate Property Limited
|
|
//
|
|
// This program is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU Affero General Public License as
|
|
// published by the Free Software Foundation, either version 3 of the
|
|
// License, or (at your option) any later version.
|
|
//
|
|
// This program is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU Affero General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU Affero General Public License
|
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
#include "stdpch.h"
|
|
#include "game_share/http_client.h"
|
|
|
|
using namespace NLMISC;
|
|
using namespace NLNET;
|
|
using namespace std;
|
|
|
|
|
|
// ***************************************************************************
|
|
bool CHttpClient::connect(std::string server)
|
|
{
|
|
try
|
|
{
|
|
// Convert an URL to a host if needed
|
|
if (server.substr(0, 7) == "http://")
|
|
server = server.substr(7);
|
|
server = server.substr(0, server.find( "/" ));
|
|
|
|
// Add the default port if no port in the cfg, and check if not already connected
|
|
if(server.find(':') == string::npos)
|
|
server+=":80";
|
|
CInetAddress addr = CInetAddress(server);
|
|
if (_Sock.connected())
|
|
{
|
|
if (addr == _Sock.remoteAddr())
|
|
return true;
|
|
else
|
|
_Sock.disconnect();
|
|
}
|
|
|
|
// Actually connect
|
|
_Sock.connect(addr);
|
|
if(!_Sock.connected())
|
|
{
|
|
nlwarning("Can't connect to web server '%s'", server.c_str());
|
|
goto end;
|
|
}
|
|
else
|
|
{
|
|
nldebug("Connected to web server '%s'", server.c_str());
|
|
}
|
|
}
|
|
catch(const Exception &e)
|
|
{
|
|
nlwarning("Can't connect to web server '%s': %s", server.c_str(), e.what());
|
|
goto end;
|
|
}
|
|
|
|
return true;
|
|
|
|
end:
|
|
|
|
if(_Sock.connected())
|
|
_Sock.close ();
|
|
|
|
return false;
|
|
}
|
|
|
|
// ***************************************************************************
|
|
bool CHttpClient::send(const std::string& buffer, bool verbose)
|
|
{
|
|
nlassert(_Sock.connected());
|
|
|
|
if(verbose)
|
|
{
|
|
nldebug("Sending '%s' to '%s'", trim(buffer).c_str(), _Sock.remoteAddr().asString().c_str());
|
|
}
|
|
|
|
uint32 size = (uint32)buffer.size();
|
|
|
|
if(!buffer.empty())
|
|
{
|
|
if(_Sock.send((uint8 *)buffer.c_str(), size, false) != CSock::Ok)
|
|
{
|
|
nlwarning ("Can't send data to the server");
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
// ***************************************************************************
|
|
bool CHttpClient::sendRequest(const std::string& methodWB, const std::string &url, const std::string &cookieName, const std::string &cookieValue, const std::string& postParams, bool verbose)
|
|
{
|
|
std::string path, host;
|
|
|
|
// Remove the protocol from the URL
|
|
if (url.substr(0, 7) == "http://")
|
|
path = url.substr(7);
|
|
else
|
|
path = url;
|
|
|
|
std::string::size_type pos = path.find("/");
|
|
|
|
// Remove the host from the URL
|
|
if (pos != std::string::npos)
|
|
{
|
|
host = path.substr(0, pos);
|
|
path = path.substr(pos);
|
|
}
|
|
else
|
|
{
|
|
host = path;
|
|
path.clear();
|
|
}
|
|
|
|
// build HTTP request
|
|
std::string request;
|
|
request += methodWB + " " + path + " HTTP/1.1\r\n";
|
|
request += "Host: " + host + "\r\n";
|
|
request += "Connection: close\r\n";
|
|
|
|
// Send
|
|
if (cookieName.empty() && postParams.empty())
|
|
{
|
|
request += "\r\n";
|
|
|
|
return send(request, verbose);
|
|
}
|
|
else
|
|
{
|
|
if (!cookieName.empty())
|
|
request += "Cookie: " + cookieName + "=" + cookieValue + "\r\n";
|
|
|
|
if (!postParams.empty())
|
|
{
|
|
request += "Content-Type: application/x-www-form-urlencoded\r\n";
|
|
request += "Content-Length: " + toString(postParams.size()) + "\r\n";
|
|
request += "\r\n";
|
|
request += postParams;
|
|
}
|
|
|
|
request += "\r\n";
|
|
|
|
return send(request, verbose);
|
|
}
|
|
}
|
|
|
|
// ***************************************************************************
|
|
bool CHttpClient::sendGet(const string &url, const string& params, bool verbose)
|
|
{
|
|
return sendRequest("GET", url + (params.empty() ? "" : ("?" + params)), string(), string(), string(), verbose);
|
|
}
|
|
|
|
// ***************************************************************************
|
|
bool CHttpClient::sendGetWithCookie(const string &url, const string &name, const string &value, const string& params, bool verbose)
|
|
{
|
|
return sendRequest("GET", url + (params.empty() ? "" : ("?" + params)), name, value, string(), verbose);
|
|
}
|
|
|
|
// ***************************************************************************
|
|
bool CHttpClient::sendPost(const string &url, const string& params, bool verbose)
|
|
{
|
|
return sendRequest("POST", url, string(), string(), params, verbose);
|
|
}
|
|
|
|
// ***************************************************************************
|
|
bool CHttpClient::sendPostWithCookie(const string &url, const string &name, const string &value, const string& params, bool verbose)
|
|
{
|
|
return sendRequest("POST", url, name, value, params, verbose);
|
|
}
|
|
|
|
// ***************************************************************************
|
|
bool CHttpClient::receive(string &res, bool verbose)
|
|
{
|
|
nlassert(_Sock.connected());
|
|
|
|
uint32 size;
|
|
res.clear();
|
|
|
|
uint8 buf[1024];
|
|
|
|
if(verbose) nlinfo("Receiving");
|
|
|
|
for(;;)
|
|
{
|
|
size = 1023;
|
|
|
|
if (_Sock.receive((uint8*)buf, size, false) == CSock::Ok)
|
|
{
|
|
if (verbose) nlinfo("Received OK %u bytes", size);
|
|
buf[1023] = '\0';
|
|
res += (char*)buf;
|
|
//nlinfo("block received '%s'", buf);
|
|
}
|
|
else
|
|
{
|
|
if (verbose) nlinfo("Received CLOSE %u bytes", size);
|
|
buf[size] = '\0';
|
|
res += (char*)buf;
|
|
//nlwarning ("server connection closed");
|
|
break;
|
|
}
|
|
}
|
|
|
|
//nlinfo("all received '%s'", res.c_str());
|
|
|
|
// only keep content (delimited by two \r\n) and discard server headers
|
|
std::string::size_type pos = res.find("\r\n\r\n");
|
|
|
|
if (pos != std::string::npos)
|
|
{
|
|
res = res.substr(pos + 4);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
// ***************************************************************************
|
|
void CHttpClient::disconnect()
|
|
{
|
|
//if(_Sock.connected())
|
|
// NB Nico : close all the time, to avoid printing into the log after release
|
|
// in CSock dtor -> causes a crash
|
|
_Sock.close ();
|
|
}
|
|
|
|
|
|
// ***************************************************************************
|
|
CHttpPostTask::CHttpPostTask(const std::string &host, const std::string &page, const std::string ¶ms)
|
|
: _Host(host)
|
|
, _Page(page)
|
|
, _Params(params)
|
|
{
|
|
}
|
|
|
|
// ***************************************************************************
|
|
void CHttpPostTask::run(void)
|
|
{
|
|
CHttpClient httpClient;
|
|
std::string ret;
|
|
|
|
if ( ! httpClient.connect(_Host))
|
|
{
|
|
return;
|
|
}
|
|
|
|
if ( ! httpClient.sendPost(_Host + _Page, _Params))
|
|
{
|
|
return;
|
|
}
|
|
|
|
httpClient.receive(ret);
|
|
httpClient.disconnect();
|
|
} |