Merge branch 'fixes' into main/rendor-staging
[ryzomcore.git] / ryzom / common / src / game_share / http_client.cpp
blobb21519014e916fd73f138ea8b2fb8f9abdaabf1a
1 // Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
2 // Copyright (C) 2010 Winch Gate Property Limited
3 //
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU Affero General Public License as
6 // published by the Free Software Foundation, either version 3 of the
7 // License, or (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU Affero General Public License for more details.
14 // You should have received a copy of the GNU Affero General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
17 #include "stdpch.h"
18 #include "game_share/http_client.h"
20 using namespace NLMISC;
21 using namespace NLNET;
22 using namespace std;
25 // ***************************************************************************
26 bool CHttpClient::connect(std::string server)
28 try
30 // Convert an URL to a host if needed
31 if (server.substr(0, 7) == "http://")
32 server = server.substr(7);
33 server = server.substr(0, server.find( "/" ));
35 // Add the default port if no port in the cfg, and check if not already connected
36 if(server.find(':') == string::npos)
37 server+=":80";
38 CInetAddress addr = CInetAddress(server);
39 if (_Sock.connected())
41 if (addr == _Sock.remoteAddr())
42 return true;
43 else
44 _Sock.disconnect();
47 // Actually connect
48 _Sock.connect(addr);
49 if(!_Sock.connected())
51 nlwarning("Can't connect to web server '%s'", server.c_str());
52 goto end;
54 else
56 nldebug("Connected to web server '%s'", server.c_str());
59 catch(const Exception &e)
61 nlwarning("Can't connect to web server '%s': %s", server.c_str(), e.what());
62 goto end;
65 return true;
67 end:
69 if(_Sock.connected())
70 _Sock.close ();
72 return false;
75 // ***************************************************************************
76 bool CHttpClient::send(const std::string& buffer, bool verbose)
78 nlassert(_Sock.connected());
80 if(verbose)
82 nldebug("Sending '%s' to '%s'", trim(buffer).c_str(), _Sock.remoteAddr().asString().c_str());
85 uint32 size = (uint32)buffer.size();
87 if(!buffer.empty())
89 if(_Sock.send((uint8 *)buffer.c_str(), size, false) != CSock::Ok)
91 nlwarning ("Can't send data to the server");
92 return false;
95 return true;
98 // ***************************************************************************
99 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)
101 std::string path, host;
103 // Remove the protocol from the URL
104 if (url.substr(0, 7) == "http://")
105 path = url.substr(7);
106 else
107 path = url;
109 std::string::size_type pos = path.find("/");
111 // Remove the host from the URL
112 if (pos != std::string::npos)
114 host = path.substr(0, pos);
115 path = path.substr(pos);
117 else
119 host = path;
120 path.clear();
123 // build HTTP request
124 std::string request;
125 request += methodWB + " " + path + " HTTP/1.1\r\n";
126 request += "Host: " + host + "\r\n";
127 request += "Connection: close\r\n";
129 // Send
130 if (cookieName.empty() && postParams.empty())
132 request += "\r\n";
134 return send(request, verbose);
136 else
138 if (!cookieName.empty())
139 request += "Cookie: " + cookieName + "=" + cookieValue + "\r\n";
141 if (!postParams.empty())
143 request += "Content-Type: application/x-www-form-urlencoded\r\n";
144 request += "Content-Length: " + toString(postParams.size()) + "\r\n";
145 request += "\r\n";
146 request += postParams;
149 request += "\r\n";
151 return send(request, verbose);
155 // ***************************************************************************
156 bool CHttpClient::sendGet(const string &url, const string& params, bool verbose)
158 return sendRequest("GET", url + (params.empty() ? "" : ("?" + params)), string(), string(), string(), verbose);
161 // ***************************************************************************
162 bool CHttpClient::sendGetWithCookie(const string &url, const string &name, const string &value, const string& params, bool verbose)
164 return sendRequest("GET", url + (params.empty() ? "" : ("?" + params)), name, value, string(), verbose);
167 // ***************************************************************************
168 bool CHttpClient::sendPost(const string &url, const string& params, bool verbose)
170 return sendRequest("POST", url, string(), string(), params, verbose);
173 // ***************************************************************************
174 bool CHttpClient::sendPostWithCookie(const string &url, const string &name, const string &value, const string& params, bool verbose)
176 return sendRequest("POST", url, name, value, params, verbose);
179 // ***************************************************************************
180 bool CHttpClient::receive(string &res, bool verbose)
182 nlassert(_Sock.connected());
184 uint32 size;
185 res.clear();
187 uint8 buf[1024];
189 if(verbose) nlinfo("Receiving");
191 for(;;)
193 size = 1023;
195 if (_Sock.receive((uint8*)buf, size, false) == CSock::Ok)
197 if (verbose) nlinfo("Received OK %u bytes", size);
198 buf[1023] = '\0';
199 res += (char*)buf;
200 //nlinfo("block received '%s'", buf);
202 else
204 if (verbose) nlinfo("Received CLOSE %u bytes", size);
205 buf[size] = '\0';
206 res += (char*)buf;
207 //nlwarning ("server connection closed");
208 break;
212 //nlinfo("all received '%s'", res.c_str());
214 // only keep content (delimited by two \r\n) and discard server headers
215 std::string::size_type pos = res.find("\r\n\r\n");
217 if (pos != std::string::npos)
219 res = res.substr(pos + 4);
222 return true;
225 // ***************************************************************************
226 void CHttpClient::disconnect()
228 //if(_Sock.connected())
229 // NB Nico : close all the time, to avoid printing into the log after release
230 // in CSock dtor -> causes a crash
231 _Sock.close ();
235 // ***************************************************************************
236 CHttpPostTask::CHttpPostTask(const std::string &host, const std::string &page, const std::string &params)
237 : _Host(host)
238 , _Page(page)
239 , _Params(params)
243 // ***************************************************************************
244 void CHttpPostTask::run(void)
246 CHttpClient httpClient;
247 std::string ret;
249 if ( ! httpClient.connect(_Host))
251 return;
254 if ( ! httpClient.sendPost(_Host + _Page, _Params))
256 return;
259 httpClient.receive(ret);
260 httpClient.disconnect();