diff options
Diffstat (limited to 'include/tgbot/net')
-rw-r--r-- | include/tgbot/net/BoostHttpOnlySslClient.h | 64 | ||||
-rw-r--r-- | include/tgbot/net/CurlHttpClient.h | 71 | ||||
-rw-r--r-- | include/tgbot/net/HttpClient.h | 69 | ||||
-rw-r--r-- | include/tgbot/net/HttpParser.h | 34 | ||||
-rw-r--r-- | include/tgbot/net/HttpReqArg.h | 51 | ||||
-rw-r--r-- | include/tgbot/net/HttpServer.h | 190 | ||||
-rw-r--r-- | include/tgbot/net/TgLongPoll.h | 24 | ||||
-rw-r--r-- | include/tgbot/net/TgWebhookLocalServer.h | 26 | ||||
-rw-r--r-- | include/tgbot/net/TgWebhookServer.h | 43 | ||||
-rw-r--r-- | include/tgbot/net/TgWebhookTcpServer.h | 20 | ||||
-rw-r--r-- | include/tgbot/net/Url.h | 42 |
11 files changed, 393 insertions, 241 deletions
diff --git a/include/tgbot/net/BoostHttpOnlySslClient.h b/include/tgbot/net/BoostHttpOnlySslClient.h new file mode 100644 index 0000000..615abdc --- /dev/null +++ b/include/tgbot/net/BoostHttpOnlySslClient.h @@ -0,0 +1,64 @@ +/* + * 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. + */ + +#ifndef TGBOT_BOOSTHTTPCLIENT_H +#define TGBOT_BOOSTHTTPCLIENT_H + +#include <string> + +#include <boost/asio.hpp> + +#include "tgbot/net/HttpClient.h" +#include "tgbot/net/Url.h" +#include "tgbot/net/HttpReqArg.h" +#include "tgbot/net/HttpParser.h" + +namespace TgBot { + +/** + * @brief This class makes http requests via boost::asio. + * + * @ingroup net + */ +class BoostHttpOnlySslClient : public HttpClient { + +public: + BoostHttpOnlySslClient(); + ~BoostHttpOnlySslClient() override; + + /** + * @brief Sends a request to the url. + * + * If there's no args specified, a GET request will be sent, otherwise a POST request will be sent. + * If at least 1 arg is marked as file, the content type of a request will be multipart/form-data, otherwise it will be application/x-www-form-urlencoded. + */ + std::string makeRequest(const Url& url, const std::vector<HttpReqArg>& args) const override; + +private: + mutable boost::asio::io_service _ioService; + const HttpParser _httpParser; +}; + +} + +#endif //TGBOT_BOOSTHTTPCLIENT_H diff --git a/include/tgbot/net/CurlHttpClient.h b/include/tgbot/net/CurlHttpClient.h new file mode 100644 index 0000000..b0ff6c3 --- /dev/null +++ b/include/tgbot/net/CurlHttpClient.h @@ -0,0 +1,71 @@ +/* + * 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. + */ + +#ifndef TGBOT_CURLHTTPCLIENT_H +#define TGBOT_CURLHTTPCLIENT_H + +#ifdef HAVE_CURL + +#include <string> + +#include <curl/curl.h> + +#include "tgbot/net/HttpClient.h" +#include "tgbot/net/Url.h" +#include "tgbot/net/HttpReqArg.h" +#include "tgbot/net/HttpParser.h" + +namespace TgBot { + +/** + * @brief This class makes http requests via libcurl. + * + * @ingroup net + */ +class CurlHttpClient : public HttpClient { + +public: + CurlHttpClient(); + ~CurlHttpClient() override; + + /** + * @brief Sends a request to the url. + * + * If there's no args specified, a GET request will be sent, otherwise a POST request will be sent. + * If at least 1 arg is marked as file, the content type of a request will be multipart/form-data, otherwise it will be application/x-www-form-urlencoded. + */ + std::string makeRequest(const Url& url, const std::vector<HttpReqArg>& args) const override; + + /** + * @brief Raw curl settings storage for fine tuning. + */ + CURL* curlSettings; + +private: + const HttpParser _httpParser; +}; + +} + +#endif + +#endif //TGBOT_CURLHTTPCLIENT_H diff --git a/include/tgbot/net/HttpClient.h b/include/tgbot/net/HttpClient.h index 4378623..62b1875 100644 --- a/include/tgbot/net/HttpClient.h +++ b/include/tgbot/net/HttpClient.h @@ -1,4 +1,4 @@ -/* + /* * Copyright (c) 2015 Oleg Morozenkov * Copyright (c) 2018 Egor Pugin * @@ -26,14 +26,8 @@ #include <string> -#include <boost/asio.hpp> -#ifdef HAVE_CURL -#include <curl/curl.h> -#endif - #include "tgbot/net/Url.h" #include "tgbot/net/HttpReqArg.h" -#include "tgbot/net/HttpParser.h" namespace TgBot { @@ -56,66 +50,7 @@ public: virtual std::string makeRequest(const Url& url, const std::vector<HttpReqArg>& args) const = 0; }; -/** - * @brief This class makes http requests via boost::asio. - * - * @ingroup net - */ -class BoostHttpClient : public HttpClient { - -public: - /** - * @brief Returns instance which lives during all application lifetime. - */ - static BoostHttpClient& getInstance(); - - /** - * @brief Sends a request to the url. - * - * If there's no args specified, a GET request will be sent, otherwise a POST request will be sent. - * If at least 1 arg is marked as file, the content type of a request will be multipart/form-data, otherwise it will be application/x-www-form-urlencoded. - */ - std::string makeRequest(const Url& url, const std::vector<HttpReqArg>& args) const override; - -private: - mutable boost::asio::io_service _ioService; -}; - -#ifdef HAVE_CURL - -/** - * @brief This class makes http requests via libcurl. - * - * @ingroup net - */ -class CurlHttpClient : public HttpClient { - -public: - - /** - * @brief Raw curl settings storage for fine tuning. - */ - CURL* curlSettings; - - CurlHttpClient(); - ~CurlHttpClient(); - - /** - * @brief Returns instance which lives during all application lifetime. - */ - static CurlHttpClient& getInstance(); - - /** - * @brief Sends a request to the url. - * - * If there's no args specified, a GET request will be sent, otherwise a POST request will be sent. - * If at least 1 arg is marked as file, the content type of a request will be multipart/form-data, otherwise it will be application/x-www-form-urlencoded. - */ - std::string makeRequest(const Url& url, const std::vector<HttpReqArg>& args) const override; -}; - -#endif - } + #endif //TGBOT_HTTPCLIENT_H diff --git a/include/tgbot/net/HttpParser.h b/include/tgbot/net/HttpParser.h index d40619a..d4900a1 100644 --- a/include/tgbot/net/HttpParser.h +++ b/include/tgbot/net/HttpParser.h @@ -35,33 +35,13 @@ namespace TgBot { class HttpParser { public: - static HttpParser& getInstance(); - - std::string generateRequest(const Url& url, const std::vector<HttpReqArg>& args, bool isKeepAlive = false); - std::string generateMultipartFormData(const std::vector<HttpReqArg>& args, const std::string& bondary); - std::string generateMultipartBoundary(const std::vector<HttpReqArg>& args); - std::string generateWwwFormUrlencoded(const std::vector<HttpReqArg>& args); - std::string generateResponse(const std::string& data, const std::string& mimeType = "text/plain", short unsigned statusCode = 200, const std::string& statusStr = "OK", bool isKeepAlive = false); - - inline std::string parseRequest(const std::string& data, std::unordered_map<std::string, std::string>& headers) { - return parseHttp(true, data, headers); - } - - inline std::string parseRequest(const std::string& data) { - return parseHttp(true, data); - } - - inline std::string parseResponse(const std::string& data, std::unordered_map<std::string, std::string>& headers) { - return parseHttp(false, data, headers); - } - - inline std::string parseResponse(const std::string& data) { - return parseHttp(false, data); - } - -private: - std::string parseHttp(bool isRequest, const std::string& data, std::unordered_map<std::string, std::string>& headers); - std::string parseHttp(bool isRequest, const std::string& data); + std::string generateRequest(const Url& url, const std::vector<HttpReqArg>& args, bool isKeepAlive = false) const; + std::string generateMultipartFormData(const std::vector<HttpReqArg>& args, const std::string& bondary) const; + std::string generateMultipartBoundary(const std::vector<HttpReqArg>& args) const; + std::string generateWwwFormUrlencoded(const std::vector<HttpReqArg>& args) const; + std::string generateResponse(const std::string& data, const std::string& mimeType, unsigned short statusCode, const std::string& statusStr, bool isKeepAlive) const; + std::unordered_map<std::string, std::string> parseHeader(const std::string& data, bool isRequest) const; + std::string extractBody(const std::string& data) const; }; } diff --git a/include/tgbot/net/HttpReqArg.h b/include/tgbot/net/HttpReqArg.h index 7476366..a263224 100644 --- a/include/tgbot/net/HttpReqArg.h +++ b/include/tgbot/net/HttpReqArg.h @@ -24,6 +24,7 @@ #define TGBOT_HTTPPARAMETER_H #include <string> +#include <utility> #include <vector> #include <functional> @@ -39,36 +40,36 @@ namespace TgBot { class HttpReqArg { public: - template<typename T> - HttpReqArg(const std::string& name, const T& value, bool isFile = false, const std::string& mimeType = "text/plain", const std::string& fileName = "") : - name(name), value(boost::lexical_cast<std::string>(value)), isFile(isFile), mimeType(mimeType), fileName(fileName) - { - } + template<typename T> + HttpReqArg(std::string name, const T& value, bool isFile = false, std::string mimeType = "text/plain", std::string fileName = "") : + name(std::move(name)), value(boost::lexical_cast<std::string>(value)), isFile(isFile), mimeType(std::move(mimeType)), fileName(std::move(fileName)) + { + } - /** - * @brief Name of an argument. - */ - std::string name; + /** + * @brief Name of an argument. + */ + std::string name; - /** - * @brief Value of an argument. - */ - std::string value; + /** + * @brief Value of an argument. + */ + std::string value; - /** - * @brief Should be true if an argument value hold some file contents - */ - bool isFile = false; + /** + * @brief Should be true if an argument value hold some file contents + */ + bool isFile = false; - /** - * @brief Mime type of an argument value. This field makes sense only if isFile is true. - */ - std::string mimeType = "text/plain"; + /** + * @brief Mime type of an argument value. This field makes sense only if isFile is true. + */ + std::string mimeType = "text/plain"; - /** - * @brief Should be set if an argument value hold some file contents - */ - std::string fileName; + /** + * @brief Should be set if an argument value hold some file contents + */ + std::string fileName; }; } diff --git a/include/tgbot/net/HttpServer.h b/include/tgbot/net/HttpServer.h index 34cd9c7..a1c5a49 100644 --- a/include/tgbot/net/HttpServer.h +++ b/include/tgbot/net/HttpServer.h @@ -23,7 +23,9 @@ #ifndef TGBOT_HTTPSERVER_H #define TGBOT_HTTPSERVER_H +#include <iostream> #include <string> +#include <utility> #include <boost/asio.hpp> @@ -40,62 +42,146 @@ template<typename Protocol> class HttpServer { protected: - class Connection; + class Connection; public: - typedef std::function<std::string (const std::string&, const std::unordered_map<std::string, std::string>)> ServerHandler; - - HttpServer(std::shared_ptr<boost::asio::basic_socket_acceptor<Protocol>> acceptor, const ServerHandler& handler) : _acceptor(acceptor), _handler(handler) { - } - - /** - * @brief Starts receiving new connections. - */ - void start() { - auto socket(std::make_shared<boost::asio::basic_stream_socket<Protocol>>(_acceptor->get_io_service())); - auto connection(std::make_shared<Connection>(socket, _handler)); - _acceptor->async_accept(*connection->socket, [this, connection]() { - connection->start(); - start(); - }); - _ioService.run(); - } - - /** - * @brief Stops receiving new connections. - */ - void stop() { - _ioService.stop(); - } + typedef std::function<std::string (const std::string&, const std::unordered_map<std::string, std::string>&)> ServerHandler; + + HttpServer(const typename boost::asio::basic_socket_acceptor<Protocol>::endpoint_type& endpoint, ServerHandler handler) + : _ioService(), _acceptor(_ioService, endpoint), _socket(_ioService), _handler(std::move(handler)), _httpParser() + { + } + + /** + * @brief Starts receiving new connections. + */ + void start() { + _startAccept(); + _ioService.run(); + } + + /** + * @brief Stops receiving new connections. + */ + void stop() { + _ioService.stop(); + } protected: - class Connection { - - public: - Connection(std::shared_ptr<boost::asio::basic_stream_socket<Protocol>>& socket, const ServerHandler& handler) : socket(socket), _handler(handler) { - boost::asio::socket_base::keep_alive option(true); - socket.set_option(option); - } - - void start() { - data.reserve(10240); - socket->async_receive(data, [this]() { - std::unordered_map<std::string, std::string> headers; - std::string body = HttpParser::getInstance().parseResponse(data, headers); - socket->async_send(_handler(body, headers)); - }); - } - - std::shared_ptr<boost::asio::basic_stream_socket<Protocol>> socket; - std::string data; - - protected: - const ServerHandler _handler; - }; - - boost::asio::io_service _ioService; - std::shared_ptr<boost::asio::basic_socket_acceptor<Protocol>> _acceptor; - const ServerHandler _handler; + class Connection : public std::enable_shared_from_this<Connection> { + + public: + Connection(boost::asio::basic_stream_socket<Protocol> socket, ServerHandler handler, const HttpParser& httpParser) + : _socket(std::move(socket)), _handler(std::move(handler)), _httpParser(httpParser) + { + } + + void start() { + _readHeader(); + } + + protected: + boost::asio::basic_stream_socket<Protocol> _socket; + const ServerHandler _handler; + const HttpParser& _httpParser; + + void _readHeader() { + auto self(this->shared_from_this()); + + auto data(std::make_shared<boost::asio::streambuf>()); + data->prepare(1024); + + boost::asio::async_read_until( + _socket, + *data, + "\r\n\r\n", + [self, data](const boost::system::error_code& e, size_t n) { + if (e) { + std::cout << "error in HttpServer::Connection#_readHeader: " << e << std::endl; + return; + } + + boost::asio::streambuf::const_buffers_type bufs = data->data(); + std::string dataAsString(boost::asio::buffers_begin(bufs), boost::asio::buffers_begin(bufs) + n); + + auto headers(std::make_shared<std::unordered_map<std::string, std::string>>(self->_httpParser.parseHeader(dataAsString, true))); + + unsigned long long size; + auto contentLengthIter = headers->find("Content-Length"); + if (contentLengthIter != headers->end()) { + size = std::stoull(contentLengthIter->second); + } else { + size = 0; + } + + if (size == 0) { + std::string answer = self->_httpParser.generateResponse("Bad request", "text/plain", 400, "Bad request", false); + boost::asio::async_write( + self->_socket, + boost::asio::buffer(answer), + [](const boost::system::error_code& e, size_t n) { }); + return; + } + + data->consume(n); + self->_readBody(data, size, headers); + }); + } + + void _readBody(std::shared_ptr<boost::asio::streambuf> data, unsigned long long size, std::shared_ptr<std::unordered_map<std::string, std::string>> headers) { + auto self(this->shared_from_this()); + + data->prepare(size); + + boost::asio::async_read(_socket, + *data, + boost::asio::transfer_exactly(size - data->size()), + [self, data, size, headers](const boost::system::error_code& e, size_t n) { + if (e) { + std::cout << "error in HttpServer::Connection#_readBody: " << e << std::endl; + return; + } + + boost::asio::streambuf::const_buffers_type bufs = data->data(); + std::string dataAsString(boost::asio::buffers_begin(bufs), boost::asio::buffers_begin(bufs) + size); + + std::string answer; + try { + answer = self->_handler(dataAsString, *headers); + } catch (std::exception& e) { + std::cout << "error in HttpServer::Connection#_readBody answer: " << e.what() << std::endl; + answer = self->_httpParser.generateResponse("Internal server error", "text/plain", 500, "Internal server error", false); + } + boost::asio::async_write( + self->_socket, + boost::asio::buffer(answer), + [](const boost::system::error_code& e, size_t n) { }); + + self->_socket.close(); + }); + } + }; + + void _startAccept() { + _acceptor.async_accept(_socket, [this](const boost::system::error_code& e) { + if (e) { + std::cout << "error in HttpServer: " << e << std::endl; + _startAccept(); + return; + } + + auto connection(std::make_shared<Connection>(std::move(_socket), _handler, _httpParser)); + connection->start(); + + _startAccept(); + }); + } + + boost::asio::io_service _ioService; + boost::asio::basic_socket_acceptor<Protocol> _acceptor; + boost::asio::basic_stream_socket<Protocol> _socket; + const ServerHandler _handler; + const HttpParser _httpParser; }; } diff --git a/include/tgbot/net/TgLongPoll.h b/include/tgbot/net/TgLongPoll.h index a0281f1..643031e 100644 --- a/include/tgbot/net/TgLongPoll.h +++ b/include/tgbot/net/TgLongPoll.h @@ -37,21 +37,21 @@ namespace TgBot { class TgLongPoll { public: - TgLongPoll(const Api* api, const EventHandler* eventHandler, int32_t, int32_t, const std::shared_ptr<std::vector<std::string>>&); - TgLongPoll(const Bot& bot, int32_t = 100, int32_t = 60, const std::shared_ptr<std::vector<std::string>>& = nullptr); + TgLongPoll(const Api* api, const EventHandler* eventHandler, int32_t, int32_t, const std::shared_ptr<std::vector<std::string>>&); + TgLongPoll(const Bot& bot, int32_t = 100, int32_t = 60, const std::shared_ptr<std::vector<std::string>>& = nullptr); - /** - * @brief Starts long poll. After new update will come, this method will parse it and send to EventHandler which invokes your listeners. Designed to be executed in a loop. - */ - void start(); + /** + * @brief Starts long poll. After new update will come, this method will parse it and send to EventHandler which invokes your listeners. Designed to be executed in a loop. + */ + void start(); private: - const Api* _api; - const EventHandler* _eventHandler; - int32_t _lastUpdateId = 0; - int32_t _limit; - int32_t _timeout; - std::shared_ptr<std::vector<std::string>> _allowupdates; + const Api* _api; + const EventHandler* _eventHandler; + int32_t _lastUpdateId = 0; + int32_t _limit; + int32_t _timeout; + std::shared_ptr<std::vector<std::string>> _allowupdates; }; } diff --git a/include/tgbot/net/TgWebhookLocalServer.h b/include/tgbot/net/TgWebhookLocalServer.h index 685979d..d7cb06e 100644 --- a/include/tgbot/net/TgWebhookLocalServer.h +++ b/include/tgbot/net/TgWebhookLocalServer.h @@ -20,8 +20,8 @@ * SOFTWARE. */ -#ifndef TGBOT_TGWEBHOOKTCPSERVER_H -#define TGBOT_TGWEBHOOKTCPSERVER_H +#ifndef TGBOT_TGWEBHOOKLOCALSERVER_H +#define TGBOT_TGWEBHOOKLOCALSERVER_H #ifdef BOOST_ASIO_HAS_LOCAL_SOCKETS @@ -37,19 +37,21 @@ namespace TgBot { class TgWebhookLocalServer : public TgWebhookServer<boost::asio::local::stream_protocol> { public: - TgWebhookLocalServer(std::shared_ptr<boost::asio::basic_socket_acceptor<boost::asio::local::stream_protocol>>& acceptor, const std::string& path, EventHandler* eventHandler) = delete; - - TgWebhookLocalServer(const std::string& path, const EventHandler* eventHandler) : - TgWebhookServer<boost::asio::local::stream_protocol>(std::make_shared<boost::asio::basic_socket_acceptor<boost::asio::local::stream_protocol>>(_ioService, boost::asio::local::stream_protocol::endpoint(path)), path, eventHandler) - { - } - - TgWebhookLocalServer(const std::string& path, const Bot& bot) : TgWebhookLocalServer(path, &bot.getEventHandler()) { - } + TgWebhookLocalServer(const std::string& unixSocketPath, const std::string& path, const EventHandler& eventHandler) + : TgWebhookServer<boost::asio::local::stream_protocol>(boost::asio::local::stream_protocol::endpoint(unixSocketPath), + path, eventHandler) + { + } + + TgWebhookLocalServer(const std::string& unixSocketPath, const Bot& bot) + : TgWebhookServer<boost::asio::local::stream_protocol>(boost::asio::local::stream_protocol::endpoint(unixSocketPath), + bot) + { + } }; } #endif //BOOST_ASIO_HAS_LOCAL_SOCKETS -#endif //TGBOT_TGWEBHOOKTCPSERVER_H +#endif //TGBOT_TGWEBHOOKLOCALSERVER_H diff --git a/include/tgbot/net/TgWebhookServer.h b/include/tgbot/net/TgWebhookServer.h index 696d126..953c1a9 100644 --- a/include/tgbot/net/TgWebhookServer.h +++ b/include/tgbot/net/TgWebhookServer.h @@ -23,6 +23,8 @@ #ifndef TGBOT_TGHTTPSERVER_H #define TGBOT_TGHTTPSERVER_H +#include <utility> + #include "tgbot/Bot.h" #include "tgbot/EventHandler.h" #include "tgbot/TgTypeParser.h" @@ -34,22 +36,31 @@ template<typename Protocol> class TgWebhookServer : public HttpServer<Protocol> { public: - TgWebhookServer(std::shared_ptr<boost::asio::basic_socket_acceptor<Protocol>> acceptor, const typename HttpServer<Protocol>::ServerHandler& handler) = delete; - - TgWebhookServer(std::shared_ptr<boost::asio::basic_socket_acceptor<Protocol>> acceptor, const std::string& path, const EventHandler* eventHandler) : - HttpServer<Protocol>(acceptor, [eventHandler, &path](const std::string& data, const std::unordered_map<std::string, std::string>& headers) -> std::string { - if (headers.at("method") == "POST" && headers.at("path") == path) { - eventHandler->handleUpdate(TgTypeParser::getInstance().parseJsonAndGetUpdate(TgTypeParser::getInstance().parseJson(data))); - } - return HttpParser::getInstance().generateResponse(""); - }) - { - } - - TgWebhookServer(std::shared_ptr<boost::asio::basic_socket_acceptor<Protocol>> acceptor, const std::string& path, const Bot& bot) : - TgWebhookServer(acceptor, path, &bot.getEventHandler()) - { - } + TgWebhookServer(const typename boost::asio::basic_socket_acceptor<Protocol>::endpoint_type& endpoint, const typename HttpServer<Protocol>::ServerHandler& handler) = delete; + + TgWebhookServer(const typename boost::asio::basic_socket_acceptor<Protocol>::endpoint_type& endpoint, std::string path, const EventHandler& eventHandler) + : HttpServer<Protocol>(endpoint, + [this](const std::string& _1, const std::unordered_map<std::string, std::string>& _2) { return _handle(_1, _2); }), + _path(std::move(path)), _eventHandler(eventHandler), _tgTypeParser() + { + } + + TgWebhookServer(const typename boost::asio::basic_socket_acceptor<Protocol>::endpoint_type& endpoint, const Bot& bot) + : TgWebhookServer(endpoint, "/" + bot.getToken(), bot.getEventHandler()) + { + } + +private: + std::string _handle(const std::string& data, const std::unordered_map<std::string, std::string>& headers) { + if (headers.at("_method") == "POST" && headers.at("_path") == _path) { + _eventHandler.handleUpdate(_tgTypeParser.parseJsonAndGetUpdate(_tgTypeParser.parseJson(data))); + } + return HttpServer<Protocol>::_httpParser.generateResponse("", "text/plain", 200, "OK", false); + } + + const EventHandler& _eventHandler; + const std::string _path; + const TgTypeParser _tgTypeParser; }; } diff --git a/include/tgbot/net/TgWebhookTcpServer.h b/include/tgbot/net/TgWebhookTcpServer.h index de1f3e7..ad5a5b8 100644 --- a/include/tgbot/net/TgWebhookTcpServer.h +++ b/include/tgbot/net/TgWebhookTcpServer.h @@ -34,15 +34,17 @@ namespace TgBot { class TgWebhookTcpServer : public TgWebhookServer<boost::asio::ip::tcp> { public: - TgWebhookTcpServer(std::shared_ptr<boost::asio::basic_socket_acceptor<boost::asio::ip::tcp>> acceptor, const std::string& path, EventHandler* eventHandler) = delete; - - TgWebhookTcpServer(unsigned short port, const std::string& path, const EventHandler* eventHandler) : - TgWebhookServer(std::shared_ptr<boost::asio::basic_socket_acceptor<boost::asio::ip::tcp>>(new boost::asio::ip::tcp::acceptor(_ioService, boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), port))), path, eventHandler) - { - } - - TgWebhookTcpServer(const std::string& path, const Bot& bot) : TgWebhookTcpServer(path, &bot.getEventHandler()) { - } + TgWebhookTcpServer(unsigned short port, const std::string& path, const EventHandler& eventHandler) + : TgWebhookServer<boost::asio::ip::tcp>(boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), port), + path, eventHandler) + { + } + + TgWebhookTcpServer(unsigned short port, const Bot& bot) + : TgWebhookServer<boost::asio::ip::tcp>(boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), port), + bot) + { + } }; } diff --git a/include/tgbot/net/Url.h b/include/tgbot/net/Url.h index c039355..f9226e5 100644 --- a/include/tgbot/net/Url.h +++ b/include/tgbot/net/Url.h @@ -35,32 +35,32 @@ namespace TgBot { class Url { public: - Url(const std::string& url); + Url(const std::string& url); - /** - * @brief Protocol part of an url. Example: https:// - */ - std::string protocol; + /** + * @brief Protocol part of an url. Example: https:// + */ + std::string protocol; - /** - * @brief Host part of an url. Example: www.example.com - */ - std::string host; + /** + * @brief Host part of an url. Example: www.example.com + */ + std::string host; - /** - * @brief Path part of an url including preceding '/' char. Example: /index.html - */ - std::string path; + /** + * @brief Path part of an url including preceding '/' char. Example: /index.html + */ + std::string path; - /** - * @brief Query part of an url without '?' char. Example: a=1&b=2&c=3 - */ - std::string query; + /** + * @brief Query part of an url without '?' char. Example: a=1&b=2&c=3 + */ + std::string query; - /** - * @brief Fragment part of an url without '#' char. Example: section1 - */ - std::string fragment; + /** + * @brief Fragment part of an url without '#' char. Example: section1 + */ + std::string fragment; }; } |