summaryrefslogtreecommitdiff
path: root/src/net
diff options
context:
space:
mode:
authorOleg Morozenkov <m@oleg.rocks>2018-07-23 01:56:42 +0300
committerOleg Morozenkov <m@oleg.rocks>2018-07-23 01:56:42 +0300
commitd47ee877be5d1175bdc36f2d87881ddaf875a8e9 (patch)
tree7fd20cdc1236fe6b832ae980de12afd7071ebab9 /src/net
parentcea20d4078f2088dea0dd589f1cc9dd7ee22461b (diff)
Refactor http clients, fix webhook server, add more samples, change tabs to 4 spaces
Diffstat (limited to 'src/net')
-rw-r--r--src/net/BoostHttpOnlySslClient.cpp92
-rw-r--r--src/net/CurlHttpClient.cpp94
-rw-r--r--src/net/HttpClient.cpp162
-rw-r--r--src/net/HttpParser.cpp314
-rw-r--r--src/net/TgLongPoll.cpp18
-rw-r--r--src/net/Url.cpp88
6 files changed, 389 insertions, 379 deletions
diff --git a/src/net/BoostHttpOnlySslClient.cpp b/src/net/BoostHttpOnlySslClient.cpp
new file mode 100644
index 0000000..fd69986
--- /dev/null
+++ b/src/net/BoostHttpOnlySslClient.cpp
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2015 Oleg Morozenkov
+ * Copyright (c) 2018 JellyBrick
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "tgbot/net/BoostHttpOnlySslClient.h"
+
+#include <boost/asio/ssl.hpp>
+
+using namespace std;
+using namespace boost::asio;
+using namespace boost::asio::ip;
+
+namespace TgBot {
+
+BoostHttpOnlySslClient::BoostHttpOnlySslClient() : _httpParser() {
+}
+
+BoostHttpOnlySslClient::~BoostHttpOnlySslClient() {
+}
+
+string BoostHttpOnlySslClient::makeRequest(const Url& url, const vector<HttpReqArg>& args) const {
+ tcp::resolver resolver(_ioService);
+ tcp::resolver::query query(url.host, "443");
+
+ ssl::context context(ssl::context::tlsv12_client);
+ context.set_default_verify_paths();
+
+ ssl::stream<tcp::socket> socket(_ioService, context);
+
+ connect(socket.lowest_layer(), resolver.resolve(query));
+
+ #ifdef TGBOT_DISABLE_NAGLES_ALGORITHM
+ socket.lowest_layer().set_option(tcp::no_delay(true));
+ #endif //TGBOT_DISABLE_NAGLES_ALGORITHM
+ #ifdef TGBOT_CHANGE_SOCKET_BUFFER_SIZE
+ #if _WIN64 || __amd64__ || __x86_64__ || __MINGW64__ || __aarch64__ || __powerpc64__
+ socket.lowest_layer().set_option(socket_base::send_buffer_size(65536));
+ socket.lowest_layer().set_option(socket_base::receive_buffer_size(65536));
+ #else //for 32-bit
+ socket.lowest_layer().set_option(socket_base::send_buffer_size(32768));
+ socket.lowest_layer().set_option(socket_base::receive_buffer_size(32768));
+ #endif //Processor architecture
+ #endif //TGBOT_CHANGE_SOCKET_BUFFER_SIZE
+ socket.set_verify_mode(ssl::verify_none);
+ socket.set_verify_callback(ssl::rfc2818_verification(url.host));
+
+ socket.handshake(ssl::stream<tcp::socket>::client);
+
+ string requestText = _httpParser.generateRequest(url, args, false);
+ write(socket, buffer(requestText.c_str(), requestText.length()));
+
+ string response;
+
+ #ifdef TGBOT_CHANGE_READ_BUFFER_SIZE
+ #if _WIN64 || __amd64__ || __x86_64__ || __MINGW64__ || __aarch64__ || __powerpc64__
+ char buff[65536];
+ #else //for 32-bit
+ char buff[32768];
+ #endif //Processor architecture
+ #else
+ char buff[1024];
+ #endif //TGBOT_CHANGE_READ_BUFFER_SIZE
+
+ boost::system::error_code error;
+ while (!error) {
+ size_t bytes = read(socket, buffer(buff), error);
+ response += string(buff, bytes);
+ }
+
+ return _httpParser.extractBody(response);
+}
+
+}
diff --git a/src/net/CurlHttpClient.cpp b/src/net/CurlHttpClient.cpp
new file mode 100644
index 0000000..932fd68
--- /dev/null
+++ b/src/net/CurlHttpClient.cpp
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2018 Egor Pugin
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifdef HAVE_CURL
+
+#include "tgbot/net/CurlHttpClient.h"
+
+#include <boost/asio/ssl.hpp>
+
+namespace TgBot {
+
+CurlHttpClient::CurlHttpClient() : _httpParser() {
+ curlSettings = curl_easy_init();
+}
+
+CurlHttpClient::~CurlHttpClient() {
+ curl_easy_cleanup(curlSettings);
+}
+
+static size_t curlWriteString(char* ptr, size_t size, size_t nmemb, void* userdata) {
+ std::string &s = *(std::string *)userdata;
+ auto read = size * nmemb;
+ s.append(ptr, ptr + read);
+ return read;
+};
+
+std::string CurlHttpClient::makeRequest(const Url& url, const std::vector<HttpReqArg>& args) const {
+ // Copy settings for each call because we change CURLOPT_URL and other stuff.
+ // This also protects multithreaded case.
+ auto curl = curl_easy_duphandle(curlSettings);
+
+ std::string u = url.protocol + "://" + url.host + url.path;
+ curl_easy_setopt(curl, CURLOPT_URL, u.c_str());
+
+ // disable keep-alive
+ struct curl_slist* headers = nullptr;
+ headers = curl_slist_append(headers, "Connection: close");
+ curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
+
+ std::string data;
+ std::vector<char*> escaped;
+ if (!args.empty()) {
+ for (const HttpReqArg& a : args) {
+ escaped.push_back(curl_easy_escape(curl, a.name.c_str(), a.name.size()));
+ data += escaped.back() + std::string("=");
+ escaped.push_back(curl_easy_escape(curl, a.value.c_str(), a.value.size()));
+ data += escaped.back() + std::string("&");
+ }
+ data.resize(data.size() - 1);
+ curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data.c_str());
+ curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, (long)data.size());
+ }
+
+ std::string response;
+ curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response);
+ curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curlWriteString);
+
+ auto res = curl_easy_perform(curl);
+ curl_slist_free_all(headers);
+ curl_easy_cleanup(curl);
+
+ for (auto& e : escaped) {
+ curl_free(e);
+ }
+
+ if (res != CURLE_OK) {
+ throw std::runtime_error(std::string("curl error: ") + curl_easy_strerror(res));
+ }
+
+ return _httpParser.extractBody(response);
+}
+
+}
+
+#endif
diff --git a/src/net/HttpClient.cpp b/src/net/HttpClient.cpp
deleted file mode 100644
index 528d988..0000000
--- a/src/net/HttpClient.cpp
+++ /dev/null
@@ -1,162 +0,0 @@
-/*
- * Copyright (c) 2015 Oleg Morozenkov
- * Copyright (c) 2018 Egor Pugin
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#include "tgbot/net/HttpClient.h"
-
-#include <boost/asio/ssl.hpp>
-
-using namespace std;
-using namespace boost::asio;
-using namespace boost::asio::ip;
-
-namespace TgBot {
-
-BoostHttpClient& BoostHttpClient::getInstance() {
- static BoostHttpClient result;
- return result;
-}
-
-string BoostHttpClient::makeRequest(const Url& url, const vector<HttpReqArg>& args) const {
- ssl::context context(ssl::context::sslv23);
- context.set_default_verify_paths();
-
- ssl::stream<tcp::socket> socket(_ioService, context);
- tcp::resolver resolver(_ioService);
- tcp::resolver::query query(url.host, url.protocol);
-
- connect(socket.lowest_layer(), resolver.resolve(query));
-
- #ifdef TGBOT_DISABLE_NAGLES_ALGORITHM
- socket.lowest_layer().set_option(tcp::no_delay(true));
- #endif //TGBOT_DISABLE_NAGLES_ALGORITHM
-
- #ifdef TGBOT_CHANGE_SOCKET_BUFFER_SIZE
- #if _WIN64 || __amd64__ || __x86_64__ || __MINGW64__ || __aarch64__ || __powerpc64__
- socket.lowest_layer().set_option(socket_base::send_buffer_size(65536));
- socket.lowest_layer().set_option(socket_base::receive_buffer_size(65536));
- #else //for 32-bit
- socket.lowest_layer().set_option(socket_base::send_buffer_size(32768));
- socket.lowest_layer().set_option(socket_base::receive_buffer_size(32768));
- #endif //Processor architecture
- #endif //TGBOT_CHANGE_SOCKET_BUFFER_SIZE
-
- socket.set_verify_mode(ssl::verify_none);
- socket.set_verify_callback(ssl::rfc2818_verification(url.host));
- socket.handshake(ssl::stream<tcp::socket>::client);
-
- string requestText = HttpParser::getInstance().generateRequest(url, args, false);
- write(socket, buffer(requestText.c_str(), requestText.length()));
-
- string response;
-
- #ifdef TGBOT_CHANGE_READ_BUFFER_SIZE
- #if _WIN64 || __amd64__ || __x86_64__ || __MINGW64__ || __aarch64__ || __powerpc64__
- char buff[65536];
- #else //for 32-bit
- char buff[32768];
- #endif //Processor architecture
- #else
- char buff[1024];
- #endif //TGBOT_CHANGE_READ_BUFFER_SIZE
-
- boost::system::error_code error;
- while (!error) {
- size_t bytes = read(socket, buffer(buff), error);
- response += string(buff, bytes);
- }
-
- return HttpParser::getInstance().parseResponse(response);
-}
-
-#ifdef HAVE_CURL
-
-CurlHttpClient::CurlHttpClient() {
- curlSettings = curl_easy_init();
-}
-
-CurlHttpClient::~CurlHttpClient() {
- curl_easy_cleanup(curlSettings);
-}
-
-CurlHttpClient& CurlHttpClient::getInstance() {
- static CurlHttpClient result;
- return result;
-}
-
-static size_t curl_write_string(char *ptr, size_t size, size_t nmemb, void *userdata)
-{
- std::string &s = *(std::string *)userdata;
- auto read = size * nmemb;
- s.append(ptr, ptr + read);
- return read;
-};
-
-string CurlHttpClient::makeRequest(const Url& url, const vector<HttpReqArg>& args) const {
- // Copy settings for each call because we change CURLOPT_URL and other stuff.
- // This also protects multithreaded case.
- auto curl = curl_easy_duphandle(curlSettings);
-
- auto u = url.protocol + "://" + url.host + url.path;
- curl_easy_setopt(curl, CURLOPT_URL, u.c_str());
-
- // disable keep-alive
- struct curl_slist *headers = NULL;
- headers = curl_slist_append(headers, "Connection: close");
- curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
-
- std::string data;
- std::vector<char *> escaped;
- if (!args.empty())
- {
- for (auto &a : args)
- {
- escaped.push_back(curl_easy_escape(curl, a.name.c_str(), a.name.size()));
- data += escaped.back() + std::string("=");
- escaped.push_back(curl_easy_escape(curl, a.value.c_str(), a.value.size()));
- data += escaped.back() + std::string("&");
- }
- data.resize(data.size() - 1);
- curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data.c_str());
- curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, (long)data.size());
- }
-
- std::string response;
- curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response);
- curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curl_write_string);
-
- auto res = curl_easy_perform(curl);
- curl_slist_free_all(headers);
- curl_easy_cleanup(curl);
-
- for (auto &e : escaped)
- curl_free(e);
-
- if (res != CURLE_OK)
- throw std::runtime_error(std::string("curl error: ") + curl_easy_strerror(res));
-
- return HttpParser::getInstance().parseResponse(response);
-}
-
-#endif
-
-}
diff --git a/src/net/HttpParser.cpp b/src/net/HttpParser.cpp
index 3dd9215..41dec14 100644
--- a/src/net/HttpParser.cpp
+++ b/src/net/HttpParser.cpp
@@ -31,182 +31,168 @@ using namespace boost;
namespace TgBot {
-HttpParser& HttpParser::getInstance() {
- static HttpParser result;
- return result;
+string HttpParser::generateRequest(const Url& url, const vector<HttpReqArg>& args, bool isKeepAlive) const {
+ string result;
+ if (args.empty()) {
+ result += "GET ";
+ } else {
+ result += "POST ";
+ }
+ result += url.path;
+ result += url.query.empty() ? "" : "?" + url.query;
+ result += " HTTP/1.1\r\n";
+ result += "Host: ";
+ result += url.host;
+ result += "\r\nConnection: ";
+ if (isKeepAlive) {
+ result += "keep-alive";
+ } else {
+ result += "close";
+ }
+ result += "\r\n";
+ if (args.empty()) {
+ result += "\r\n";
+ } else {
+ string requestData;
+
+ string bondary = generateMultipartBoundary(args);
+ if (bondary.empty()) {
+ result += "Content-Type: application/x-www-form-urlencoded\r\n";
+ requestData = generateWwwFormUrlencoded(args);
+ } else {
+ result += "Content-Type: multipart/form-data; boundary=";
+ result += bondary;
+ result += "\r\n";
+ requestData = generateMultipartFormData(args, bondary);
+ }
+
+ result += "Content-Length: ";
+ result += std::to_string(requestData.length());
+ result += "\r\n\r\n";
+ result += requestData;
+ }
+ return result;
}
-string HttpParser::generateRequest(const Url& url, const vector<HttpReqArg>& args, bool isKeepAlive) {
- string result;
- if (args.empty()) {
- result += "GET ";
- } else {
- result += "POST ";
- }
- result += url.path;
- result += url.query.empty() ? "" : "?" + url.query;
- result += " HTTP/1.1\r\n";
- result += "Host: ";
- result += url.host;
- result += "\r\nConnection: ";
- if (isKeepAlive) {
- result += "keep-alive";
- } else {
- result += "close";
- }
- result += "\r\n";
- if (args.empty()) {
- result += "\r\n";
- } else {
- string requestData;
-
- string bondary = generateMultipartBoundary(args);
- if (bondary.empty()) {
- result += "Content-Type: application/x-www-form-urlencoded\r\n";
- requestData = generateWwwFormUrlencoded(args);
- } else {
- result += "Content-Type: multipart/form-data; boundary=";
- result += bondary;
- result += "\r\n";
- requestData = generateMultipartFormData(args, bondary);
- }
-
- result += "Content-Length: ";
- result += lexical_cast<string>(requestData.length());
- result += "\r\n\r\n";
- result += requestData;
- }
- return result;
+string HttpParser::generateMultipartFormData(const vector<HttpReqArg>& args, const string& bondary) const {
+ string result;
+ for (const HttpReqArg& item : args) {
+ result += "--";
+ result += bondary;
+ result += "\r\nContent-Disposition: form-data; name=\"";
+ result += item.name;
+ if (item.isFile) {
+ result += "\"; filename=\"" + item.fileName;
+ }
+ result += "\"\r\n";
+ if (item.isFile) {
+ result += "Content-Type: ";
+ result += item.mimeType;
+ result += "\r\n";
+ }
+ result += "\r\n";
+ result += item.value;
+ result += "\r\n";
+ }
+ result += "--" + bondary + "--\r\n";
+ return result;
}
-string HttpParser::generateMultipartFormData(const vector<HttpReqArg>& args, const string& bondary) {
- string result;
- for (const HttpReqArg& item : args) {
- result += "--";
- result += bondary;
- result += "\r\nContent-Disposition: form-data; name=\"";
- result += item.name;
- if (item.isFile) {
- result += "\"; filename=\"" + item.fileName;
- }
- result += "\"\r\n";
- if (item.isFile) {
- result += "Content-Type: ";
- result += item.mimeType;
- result += "\r\n";
- }
- result += "\r\n";
- result += item.value;
- result += "\r\n";
- }
- result += "--" + bondary + "--\r\n";
- return result;
+string HttpParser::generateMultipartBoundary(const vector<HttpReqArg>& args) const {
+ string result;
+ srand((unsigned int) time(nullptr));
+ for (const HttpReqArg& item : args) {
+ if (item.isFile) {
+ while (result.empty() || item.value.find(result) != string::npos) {
+ result += StringTools::generateRandomString(4);
+ }
+ }
+ }
+ return result;
}
-string HttpParser::generateMultipartBoundary(const vector<HttpReqArg>& args) {
- string result;
- srand((unsigned int) time(nullptr));
- for (const HttpReqArg& item : args) {
- if (item.isFile) {
- while (result.empty() || item.value.find(result) != item.value.npos) {
- result += StringTools::generateRandomString(4);
- }
- }
- }
- return result;
+string HttpParser::generateWwwFormUrlencoded(const vector<HttpReqArg>& args) const {
+ string result;
+
+ bool firstRun = true;
+ for (const HttpReqArg& item : args) {
+ if (firstRun) {
+ firstRun = false;
+ } else {
+ result += '&';
+ }
+ result += StringTools::urlEncode(item.name);
+ result += '=';
+ result += StringTools::urlEncode(item.value);
+ }
+
+ return result;
}
-string HttpParser::generateWwwFormUrlencoded(const vector<HttpReqArg>& args) {
- string result;
-
- bool firstRun = true;
- for (const HttpReqArg& item : args) {
- if (firstRun) {
- firstRun = false;
- } else {
- result += '&';
- }
- result += StringTools::urlEncode(item.name);
- result += '=';
- result += StringTools::urlEncode(item.value);
- }
-
- return result;
+string HttpParser::generateResponse(const string& data, const string& mimeType, unsigned short statusCode, const string& statusStr, bool isKeepAlive) const {
+ string result;
+ result += "HTTP/1.1 ";
+ result += std::to_string(statusCode);
+ result += ' ';
+ result += statusStr;
+ result += "\r\nContent-Type: ";
+ result += mimeType;
+ result += "\r\nContent-Length: ";
+ result += std::to_string(data.length());
+ result += "\r\nConnection: ";
+ if (isKeepAlive) {
+ result += "keep-alive";
+ } else {
+ result += "close";
+ }
+ result += "\r\n\r\n";
+ result += data;
+ return result;
}
-string HttpParser::generateResponse(const string& data, const string& mimeType, unsigned short statusCode, const string& statusStr, bool isKeepAlive) {
- string result;
- result += "HTTP/1.1 ";
- result += lexical_cast<string>(statusCode);
- result += ' ';
- result += statusStr;
- result += "\r\nContent-Type: ";
- result += mimeType;
- result += "\r\nContent-Length: ";
- result += lexical_cast<string>(data.length());
- result += "\r\n\r\n";
- result += data;
- return result;
+unordered_map<string, string> HttpParser::parseHeader(const string& data, bool isRequest) const {
+ unordered_map<string, string> headers;
+
+ size_t lineStart = 0;
+ size_t lineEnd = 0;
+ size_t lineSepPos = 0;
+ size_t lastLineEnd = string::npos;
+ while (lastLineEnd != lineEnd) {
+ lastLineEnd = lineEnd;
+ bool isFirstLine = lineEnd == 0;
+ if (isFirstLine) {
+ if (isRequest) {
+ lineSepPos = data.find(' ');
+ lineEnd = data.find("\r\n");
+ headers["_method"] = data.substr(0, lineSepPos);
+ headers["_path"] = data.substr(lineSepPos + 1, data.find(' ', lineSepPos + 1) - lineSepPos - 1);
+ } else {
+ lineSepPos = data.find(' ');
+ lineEnd = data.find("\r\n");
+ headers["_status"] = data.substr(lineSepPos + 1, data.find(' ', lineSepPos + 1) - lineSepPos - 1);
+ }
+ } else {
+ lineStart = lineEnd;
+ lineStart += 2;
+ lineEnd = data.find("\r\n", lineStart);
+ lineSepPos = data.find(':', lineStart);
+ if (lastLineEnd == lineEnd || lineEnd == string::npos) {
+ break;
+ }
+ headers[data.substr(lineStart, lineSepPos - lineStart)] = trim_copy(data.substr(lineSepPos + 1, lineEnd - lineSepPos - 1));
+ }
+ }
+
+ return headers;
}
-string HttpParser::parseHttp(bool isRequest, const string& data, unordered_map<string, string>& headers) {
- bool onlyNewLineChar = false;
- size_t headerEnd = data.find("\r\n\r\n");
- if (headerEnd == data.npos) {
- headerEnd = data.find("\n\n");
- if (headerEnd != data.npos) {
- onlyNewLineChar = true;
- headerEnd += 2;
- }
- } else {
- headerEnd += 4;
- }
-
- size_t lineStart = 0;
- size_t lineEnd = 0;
- size_t lineSepPos = 0;
- size_t lastLineEnd = data.npos;
- while (lastLineEnd != lineEnd) {
- lastLineEnd = lineEnd;
- if (lineEnd == 0) {
- if (isRequest) {
- lineSepPos = data.find(' ');
- lineEnd = data.find(onlyNewLineChar ? "\n" : "\r\n");
- headers["method"] = data.substr(0, lineSepPos);
- headers["path"] = data.substr(lineSepPos + 1, data.find(' ', lineSepPos + 1) - lineSepPos - 1);
- } else {
- lineSepPos = data.find(' ');
- lineEnd = data.find(onlyNewLineChar ? "\n" : "\r\n");
- headers["status"] = data.substr(lineSepPos + 1, data.find(' ', lineSepPos + 1) - lineSepPos - 1);
- }
- } else {
- lineStart = lineEnd;
- lineStart += onlyNewLineChar ? 1 : 2;
- lineEnd = data.find(onlyNewLineChar ? "\n" : "\r\n", lineStart);
- lineSepPos = data.find(':', lineStart);
- if (lineEnd >= headerEnd || lastLineEnd == lineEnd || lineSepPos >= headerEnd) {
- break;
- }
- headers[to_lower_copy(data.substr(lineStart, lineSepPos - lineStart))] = trim_copy(data.substr(lineSepPos + 1, lineEnd - lineSepPos - 1));
- }
- }
-
- return headerEnd == data.npos ? "" : data.substr(headerEnd);
-}
-
-string HttpParser::parseHttp(bool isRequest, const string& data) {
- size_t headerEnd = data.find("\r\n\r\n");
- if (headerEnd != data.npos) {
- headerEnd += 4;
- } else {
- headerEnd = data.find("\n\n");
- if (headerEnd != data.npos) {
- headerEnd += 2;
- } else {
- headerEnd = 0;
- }
- }
- return data.substr(headerEnd);
+string HttpParser::extractBody(const string& data) const {
+ size_t headerEnd = data.find("\r\n\r\n");
+ if (headerEnd == string::npos) {
+ return data;
+ }
+ headerEnd += 4;
+ return data.substr(headerEnd);
}
}
diff --git a/src/net/TgLongPoll.cpp b/src/net/TgLongPoll.cpp
index 30ce815..6af8a62 100644
--- a/src/net/TgLongPoll.cpp
+++ b/src/net/TgLongPoll.cpp
@@ -25,21 +25,21 @@
namespace TgBot {
TgLongPoll::TgLongPoll(const Api* api, const EventHandler* eventHandler, int32_t limit, int32_t timeout, const std::shared_ptr<std::vector<std::string>>& allowupdates)
- : _api(api), _eventHandler(eventHandler), _limit(limit), _timeout(timeout), _allowupdates(allowupdates) {
+ : _api(api), _eventHandler(eventHandler), _limit(limit), _timeout(timeout), _allowupdates(allowupdates) {
}
TgLongPoll::TgLongPoll(const Bot& bot, int32_t limit, int32_t timeout, const std::shared_ptr<std::vector<std::string>>& allowupdates) :
- TgLongPoll(&bot.getApi(), &bot.getEventHandler(), limit, timeout, allowupdates) {
+ TgLongPoll(&bot.getApi(), &bot.getEventHandler(), limit, timeout, allowupdates) {
}
void TgLongPoll::start() {
- std::vector<Update::Ptr> updates = _api->getUpdates(_lastUpdateId, _limit, _timeout, _allowupdates);
- for (Update::Ptr& item : updates) {
- if (item->updateId >= _lastUpdateId) {
- _lastUpdateId = item->updateId + 1;
- }
- _eventHandler->handleUpdate(item);
- }
+ std::vector<Update::Ptr> updates = _api->getUpdates(_lastUpdateId, _limit, _timeout, _allowupdates);
+ for (Update::Ptr& item : updates) {
+ if (item->updateId >= _lastUpdateId) {
+ _lastUpdateId = item->updateId + 1;
+ }
+ _eventHandler->handleUpdate(item);
+ }
}
}
diff --git a/src/net/Url.cpp b/src/net/Url.cpp
index 005506c..1c7aae6 100644
--- a/src/net/Url.cpp
+++ b/src/net/Url.cpp
@@ -29,52 +29,52 @@ using namespace std;
namespace TgBot {
Url::Url(const string& url) {
- bool isProtocolParsed = false;
- bool isHostParsed = false;
- bool isPathParsed = false;
- bool isQueryParsed = false;
+ bool isProtocolParsed = false;
+ bool isHostParsed = false;
+ bool isPathParsed = false;
+ bool isQueryParsed = false;
- for (size_t i = 0, count = url.length(); i < count; ++i) {
- char c = url[i];
+ for (size_t i = 0, count = url.length(); i < count; ++i) {
+ char c = url[i];
- if (!isProtocolParsed) {
- if (c == ':') {
- isProtocolParsed = true;
- i += 2;
- } else {
- protocol += c;
- }
- } else if (!isHostParsed) {
- if (c == '/') {
- isHostParsed = true;
- path += '/';
- } else if (c == '?') {
- isHostParsed = isPathParsed = true;
- path += '/';
- } else if (c == '#') {
- isHostParsed = isPathParsed = isQueryParsed = true;
- path += '/';
- } else {
- host += c;
- }
- } else if (!isPathParsed) {
- if (c == '?') {
- isPathParsed = true;
- } else if (c == '#') {
- isPathParsed = isQueryParsed = true;
- } else {
- path += c;
- }
- } else if (!isQueryParsed) {
- if (c == '#') {
- isQueryParsed = true;
- } else {
- query += c;
- }
- } else {
- fragment += c;
- }
- }
+ if (!isProtocolParsed) {
+ if (c == ':') {
+ isProtocolParsed = true;
+ i += 2;
+ } else {
+ protocol += c;
+ }
+ } else if (!isHostParsed) {
+ if (c == '/') {
+ isHostParsed = true;
+ path += '/';
+ } else if (c == '?') {
+ isHostParsed = isPathParsed = true;
+ path += '/';
+ } else if (c == '#') {
+ isHostParsed = isPathParsed = isQueryParsed = true;
+ path += '/';
+ } else {
+ host += c;
+ }
+ } else if (!isPathParsed) {
+ if (c == '?') {
+ isPathParsed = true;
+ } else if (c == '#') {
+ isPathParsed = isQueryParsed = true;
+ } else {
+ path += c;
+ }
+ } else if (!isQueryParsed) {
+ if (c == '#') {
+ isQueryParsed = true;
+ } else {
+ query += c;
+ }
+ } else {
+ fragment += c;
+ }
+ }
}
}