diff options
Diffstat (limited to '')
-rw-r--r-- | src/HTTP/EnvelopeParser.cpp | 13 | ||||
-rw-r--r-- | src/HTTP/EnvelopeParser.h | 17 | ||||
-rw-r--r-- | src/HTTP/HTTPFormParser.cpp | 23 | ||||
-rw-r--r-- | src/HTTP/HTTPFormParser.h | 38 | ||||
-rw-r--r-- | src/HTTP/HTTPMessage.cpp | 23 | ||||
-rw-r--r-- | src/HTTP/HTTPMessage.h | 38 | ||||
-rw-r--r-- | src/HTTP/HTTPMessageParser.cpp | 17 | ||||
-rw-r--r-- | src/HTTP/HTTPMessageParser.h | 16 | ||||
-rw-r--r-- | src/HTTP/HTTPServer.cpp | 40 | ||||
-rw-r--r-- | src/HTTP/HTTPServer.h | 37 | ||||
-rw-r--r-- | src/HTTP/HTTPServerConnection.cpp | 8 | ||||
-rw-r--r-- | src/HTTP/HTTPServerConnection.h | 21 | ||||
-rw-r--r-- | src/HTTP/MultipartParser.cpp | 22 | ||||
-rw-r--r-- | src/HTTP/MultipartParser.h | 23 | ||||
-rw-r--r-- | src/HTTP/NameValueParser.cpp | 10 | ||||
-rw-r--r-- | src/HTTP/NameValueParser.h | 33 | ||||
-rw-r--r-- | src/HTTP/SslHTTPServerConnection.cpp | 12 | ||||
-rw-r--r-- | src/HTTP/SslHTTPServerConnection.h | 14 | ||||
-rw-r--r-- | src/HTTP/TransferEncodingParser.cpp | 86 | ||||
-rw-r--r-- | src/HTTP/TransferEncodingParser.h | 16 | ||||
-rw-r--r-- | src/HTTP/UrlClient.cpp | 179 | ||||
-rw-r--r-- | src/HTTP/UrlClient.h | 34 | ||||
-rw-r--r-- | src/HTTP/UrlParser.cpp | 11 | ||||
-rw-r--r-- | src/HTTP/UrlParser.h | 6 |
24 files changed, 313 insertions, 424 deletions
diff --git a/src/HTTP/EnvelopeParser.cpp b/src/HTTP/EnvelopeParser.cpp index 15ab95380..2d58ee99b 100644 --- a/src/HTTP/EnvelopeParser.cpp +++ b/src/HTTP/EnvelopeParser.cpp @@ -1,7 +1,8 @@ // EnvelopeParser.cpp -// Implements the cEnvelopeParser class representing a parser for RFC-822 envelope headers, used both in HTTP and in MIME +// Implements the cEnvelopeParser class representing a parser for RFC-822 envelope headers, used both in HTTP and in +// MIME #include "Globals.h" #include "EnvelopeParser.h" @@ -11,8 +12,7 @@ cEnvelopeParser::cEnvelopeParser(cCallbacks & a_Callbacks) : - m_Callbacks(a_Callbacks), - m_IsInHeaders(true) + m_Callbacks(a_Callbacks), m_IsInHeaders(true) { } @@ -59,7 +59,8 @@ size_t cEnvelopeParser::Parse(const char * a_Data, size_t a_Size) } Last = idxCRLF + 2; idxCRLF = m_IncomingData.find("\r\n", idxCRLF + 2); - } while (idxCRLF != AString::npos); + } + while (idxCRLF != AString::npos); m_IncomingData.erase(0, Last); // Parsed all lines and still expecting more @@ -133,7 +134,3 @@ bool cEnvelopeParser::ParseLine(const char * a_Data, size_t a_Size) // No colon was found, key-less header?? return false; } - - - - diff --git a/src/HTTP/EnvelopeParser.h b/src/HTTP/EnvelopeParser.h index 2fa930539..a1f0905a0 100644 --- a/src/HTTP/EnvelopeParser.h +++ b/src/HTTP/EnvelopeParser.h @@ -15,16 +15,16 @@ class cEnvelopeParser { -public: + public: class cCallbacks { - public: + public: // Force a virtual destructor in descendants: virtual ~cCallbacks() {} /** Called when a full header line is parsed */ virtual void OnHeaderLine(const AString & a_Key, const AString & a_Value) = 0; - } ; + }; cEnvelopeParser(cCallbacks & a_Callbacks); @@ -44,11 +44,12 @@ public: /** Sets the IsInHeaders flag; used by cMultipartParser to simplify the parser initial conditions */ void SetIsInHeaders(bool a_IsInHeaders) { m_IsInHeaders = a_IsInHeaders; } -public: + public: /** Callbacks to call for the various events */ cCallbacks & m_Callbacks; - /** Set to true while the parser is still parsing the envelope headers. Once set to true, the parser will not consume any more data. */ + /** Set to true while the parser is still parsing the envelope headers. Once set to true, the parser will not + * consume any more data. */ bool m_IsInHeaders; /** Buffer for the incoming data until it is parsed */ @@ -66,8 +67,4 @@ public: /** Parses one line of header data. Returns true if successful */ bool ParseLine(const char * a_Data, size_t a_Size); -} ; - - - - +}; diff --git a/src/HTTP/HTTPFormParser.cpp b/src/HTTP/HTTPFormParser.cpp index d5b58d2f4..7e0ca86f0 100644 --- a/src/HTTP/HTTPFormParser.cpp +++ b/src/HTTP/HTTPFormParser.cpp @@ -13,10 +13,7 @@ cHTTPFormParser::cHTTPFormParser(const cHTTPIncomingRequest & a_Request, cCallbacks & a_Callbacks) : - m_Callbacks(a_Callbacks), - m_IsValid(true), - m_IsCurrentPartFile(false), - m_FileHasBeenAnnounced(false) + m_Callbacks(a_Callbacks), m_IsValid(true), m_IsCurrentPartFile(false), m_FileHasBeenAnnounced(false) { if (a_Request.GetMethod() == "GET") { @@ -54,11 +51,7 @@ cHTTPFormParser::cHTTPFormParser(const cHTTPIncomingRequest & a_Request, cCallba cHTTPFormParser::cHTTPFormParser(eKind a_Kind, const char * a_Data, size_t a_Size, cCallbacks & a_Callbacks) : - m_Callbacks(a_Callbacks), - m_Kind(a_Kind), - m_IsValid(true), - m_IsCurrentPartFile(false), - m_FileHasBeenAnnounced(false) + m_Callbacks(a_Callbacks), m_Kind(a_Kind), m_IsValid(true), m_IsCurrentPartFile(false), m_FileHasBeenAnnounced(false) { Parse(a_Data, a_Size); } @@ -126,10 +119,7 @@ bool cHTTPFormParser::HasFormData(const cHTTPIncomingRequest & a_Request) return ( (ContentType == "application/x-www-form-urlencoded") || (strncmp(ContentType.c_str(), "multipart/form-data", 19) == 0) || - ( - (a_Request.GetMethod() == "GET") && - (a_Request.GetURL().find('?') != AString::npos) - ) + ((a_Request.GetMethod() == "GET") && (a_Request.GetURL().find('?') != AString::npos)) ); } @@ -150,7 +140,8 @@ void cHTTPFormParser::BeginMultipart(const cHTTPIncomingRequest & a_Request) void cHTTPFormParser::ParseFormUrlEncoded(void) { // Parse m_IncomingData for all the variables; no more data is incoming, since this is called from Finish() - // This may not be the most performant version, but we don't care, the form data is small enough and we're not a full-fledged web server anyway + // This may not be the most performant version, but we don't care, the form data is small enough and we're not a + // full-fledged web server anyway AStringVector Lines = StringSplit(m_IncomingData, "&"); for (AStringVector::iterator itr = Lines.begin(), end = Lines.end(); itr != end; ++itr) { @@ -295,7 +286,3 @@ void cHTTPFormParser::OnPartEnd(void) m_CurrentPartName.clear(); m_CurrentPartFileName.clear(); } - - - - diff --git a/src/HTTP/HTTPFormParser.h b/src/HTTP/HTTPFormParser.h index 6bf3e7d78..e4c441bd0 100644 --- a/src/HTTP/HTTPFormParser.h +++ b/src/HTTP/HTTPFormParser.h @@ -21,21 +21,21 @@ class cHTTPIncomingRequest; -class cHTTPFormParser : - public std::map<AString, AString>, - public cMultipartParser::cCallbacks +class cHTTPFormParser : public std::map<AString, AString>, + public cMultipartParser::cCallbacks { -public: + public: enum eKind { - fpkURL, ///< The form has been transmitted as parameters to a GET request - fpkFormUrlEncoded, ///< The form has been POSTed or PUT, with Content-Type of "application/x-www-form-urlencoded" - fpkMultipart, ///< The form has been POSTed or PUT, with Content-Type of "multipart/form-data" - } ; + fpkURL, ///< The form has been transmitted as parameters to a GET request + fpkFormUrlEncoded, ///< The form has been POSTed or PUT, with Content-Type of + ///< "application/x-www-form-urlencoded" + fpkMultipart, ///< The form has been POSTed or PUT, with Content-Type of "multipart/form-data" + }; class cCallbacks { - public: + public: // Force a virtual destructor in descendants: virtual ~cCallbacks() {} @@ -47,7 +47,7 @@ public: /** Called when the current file part has ended in the form data */ virtual void OnFileEnd(cHTTPFormParser & a_Parser) = 0; - } ; + }; /** Creates a parser that is tied to a request and notifies of various events using a callback mechanism */ @@ -66,8 +66,7 @@ public: /** Returns true if the headers suggest the request has form data parseable by this class */ static bool HasFormData(const cHTTPIncomingRequest & a_Request); -protected: - + protected: /** The callbacks to call for incoming file data */ cCallbacks & m_Callbacks; @@ -77,7 +76,8 @@ protected: /** Buffer for the incoming data until it's parsed */ AString m_IncomingData; - /** True if the information received so far is a valid form; set to false on first problem. Further parsing is skipped when false. */ + /** True if the information received so far is a valid form; set to false on first problem. Further parsing is + * skipped when false. */ bool m_IsValid; /** The parser for the multipart data, if used */ @@ -103,12 +103,8 @@ protected: void ParseFormUrlEncoded(void); // cMultipartParser::cCallbacks overrides: - virtual void OnPartStart (void) override; + virtual void OnPartStart(void) override; virtual void OnPartHeader(const AString & a_Key, const AString & a_Value) override; - virtual void OnPartData (const char * a_Data, size_t a_Size) override; - virtual void OnPartEnd (void) override; -} ; - - - - + virtual void OnPartData(const char * a_Data, size_t a_Size) override; + virtual void OnPartEnd(void) override; +}; diff --git a/src/HTTP/HTTPMessage.cpp b/src/HTTP/HTTPMessage.cpp index 827842ef9..56ed82571 100644 --- a/src/HTTP/HTTPMessage.cpp +++ b/src/HTTP/HTTPMessage.cpp @@ -12,8 +12,8 @@ // Disable MSVC warnings: #if defined(_MSC_VER) - #pragma warning(push) - #pragma warning(disable:4355) // 'this' : used in base member initializer list +#pragma warning(push) +#pragma warning(disable : 4355) // 'this' : used in base member initializer list #endif @@ -24,8 +24,7 @@ // cHTTPMessage: cHTTPMessage::cHTTPMessage(eKind a_Kind) : - m_Kind(a_Kind), - m_ContentLength(AString::npos) + m_Kind(a_Kind), m_ContentLength(AString::npos) { } @@ -104,11 +103,8 @@ void cHTTPOutgoingResponse::AppendToData(AString & a_DataStream) const //////////////////////////////////////////////////////////////////////////////// // cHTTPIncomingRequest: -cHTTPIncomingRequest::cHTTPIncomingRequest(const AString & a_Method, const AString & a_URL): - Super(mkRequest), - m_Method(a_Method), - m_URL(a_URL), - m_HasAuth(false) +cHTTPIncomingRequest::cHTTPIncomingRequest(const AString & a_Method, const AString & a_URL) : + Super(mkRequest), m_Method(a_Method), m_URL(a_URL), m_HasAuth(false) { } @@ -135,10 +131,7 @@ AString cHTTPIncomingRequest::GetURLPath(void) const void cHTTPIncomingRequest::AddHeader(const AString & a_Key, const AString & a_Value) { - if ( - (NoCaseCompare(a_Key, "Authorization") == 0) && - (strncmp(a_Value.c_str(), "Basic ", 6) == 0) - ) + if ((NoCaseCompare(a_Key, "Authorization") == 0) && (strncmp(a_Value.c_str(), "Basic ", 6) == 0)) { AString UserPass = Base64Decode(a_Value.substr(6)); size_t idxCol = UserPass.find(':'); @@ -155,7 +148,3 @@ void cHTTPIncomingRequest::AddHeader(const AString & a_Key, const AString & a_Va } Super::AddHeader(a_Key, a_Value); } - - - - diff --git a/src/HTTP/HTTPMessage.h b/src/HTTP/HTTPMessage.h index f73957748..d6df46d9f 100644 --- a/src/HTTP/HTTPMessage.h +++ b/src/HTTP/HTTPMessage.h @@ -15,18 +15,18 @@ class cHTTPMessage { -public: + public: enum eStatus { HTTP_OK = 200, HTTP_BAD_REQUEST = 400, - } ; + }; enum eKind { mkRequest, mkResponse, - } ; + }; cHTTPMessage(eKind a_Kind); @@ -36,14 +36,13 @@ public: /** Adds a header into the internal map of headers. Recognizes special headers: Content-Type and Content-Length */ virtual void AddHeader(const AString & a_Key, const AString & a_Value); - void SetContentType (const AString & a_ContentType) { m_ContentType = a_ContentType; } - void SetContentLength(size_t a_ContentLength) { m_ContentLength = a_ContentLength; } + void SetContentType(const AString & a_ContentType) { m_ContentType = a_ContentType; } + void SetContentLength(size_t a_ContentLength) { m_ContentLength = a_ContentLength; } - const AString & GetContentType (void) const { return m_ContentType; } - size_t GetContentLength(void) const { return m_ContentLength; } - -protected: + const AString & GetContentType(void) const { return m_ContentType; } + size_t GetContentLength(void) const { return m_ContentLength; } + protected: using cNameValueMap = std::map<AString, AString>; @@ -59,43 +58,39 @@ protected: AString::npos when the object is created. Parsed by AddHeader() or set directly by SetContentLength() */ size_t m_ContentLength; -} ; +}; /** Stores outgoing response headers and serializes them to an HTTP data stream. */ -class cHTTPOutgoingResponse: - public cHTTPMessage +class cHTTPOutgoingResponse : public cHTTPMessage { using Super = cHTTPMessage; -public: - + public: cHTTPOutgoingResponse(void); /** Appends the response to the specified datastream - response line and headers. The body will be sent later directly through cConnection::Send() */ void AppendToData(AString & a_DataStream) const; -} ; +}; /** Provides storage for an incoming HTTP request. */ -class cHTTPIncomingRequest: - public cHTTPMessage +class cHTTPIncomingRequest : public cHTTPMessage { using Super = cHTTPMessage; -public: - + public: /** Base class for anything that can be used as the UserData for the request. */ class cUserData { - public: + public: // Force a virtual destructor in descendants: virtual ~cUserData() {} }; @@ -135,8 +130,7 @@ public: Overrides the parent to add recognizing additional headers: auth and keepalive. */ virtual void AddHeader(const AString & a_Key, const AString & a_Value) override; -protected: - + protected: /** Method of the request (GET / PUT / POST / ...) */ AString m_Method; diff --git a/src/HTTP/HTTPMessageParser.cpp b/src/HTTP/HTTPMessageParser.cpp index de3cf6518..759639f96 100644 --- a/src/HTTP/HTTPMessageParser.cpp +++ b/src/HTTP/HTTPMessageParser.cpp @@ -11,9 +11,8 @@ -cHTTPMessageParser::cHTTPMessageParser(cHTTPMessageParser::cCallbacks & a_Callbacks): - m_Callbacks(a_Callbacks), - m_EnvelopeParser(*this) +cHTTPMessageParser::cHTTPMessageParser(cHTTPMessageParser::cCallbacks & a_Callbacks) : + m_Callbacks(a_Callbacks), m_EnvelopeParser(*this) { Reset(); } @@ -36,7 +35,9 @@ size_t cHTTPMessageParser::Parse(const char * a_Data, size_t a_Size) { m_Buffer.append(a_Data, a_Size); auto bytesConsumedFirstLine = ParseFirstLine(); - ASSERT(bytesConsumedFirstLine <= inBufferSoFar + a_Size); // Haven't consumed more data than there is in the buffer + ASSERT( + bytesConsumedFirstLine <= inBufferSoFar + a_Size + ); // Haven't consumed more data than there is in the buffer ASSERT(bytesConsumedFirstLine > inBufferSoFar); // Have consumed at least the previous buffer contents if (m_FirstLine.empty()) { @@ -55,7 +56,9 @@ size_t cHTTPMessageParser::Parse(const char * a_Data, size_t a_Size) m_Callbacks.OnError("Failed to parse the envelope"); return AString::npos; } - ASSERT(bytesConsumedEnvelope <= bytesConsumedFirstLine + a_Size); // Haven't consumed more data than there was in the buffer + ASSERT( + bytesConsumedEnvelope <= bytesConsumedFirstLine + a_Size + ); // Haven't consumed more data than there was in the buffer m_Buffer.erase(0, bytesConsumedEnvelope); if (!m_EnvelopeParser.IsInHeaders()) { @@ -218,7 +221,3 @@ void cHTTPMessageParser::OnBodyFinished(void) m_IsFinished = true; m_Callbacks.OnBodyFinished(); } - - - - diff --git a/src/HTTP/HTTPMessageParser.h b/src/HTTP/HTTPMessageParser.h index 307714243..7512afcb0 100644 --- a/src/HTTP/HTTPMessageParser.h +++ b/src/HTTP/HTTPMessageParser.h @@ -17,14 +17,13 @@ -class cHTTPMessageParser: - protected cEnvelopeParser::cCallbacks, - protected cTransferEncodingParser::cCallbacks +class cHTTPMessageParser : protected cEnvelopeParser::cCallbacks, + protected cTransferEncodingParser::cCallbacks { -public: + public: class cCallbacks { - public: + public: // Force a virtual destructor in descendants: virtual ~cCallbacks() {} @@ -66,8 +65,7 @@ public: void Reset(void); -protected: - + protected: /** The callbacks used for reporting. */ cCallbacks & m_Callbacks; @@ -120,7 +118,3 @@ protected: virtual void OnBodyData(const void * a_Data, size_t a_Size) override; virtual void OnBodyFinished(void) override; }; - - - - diff --git a/src/HTTP/HTTPServer.cpp b/src/HTTP/HTTPServer.cpp index 42e1159ac..e8336cd98 100644 --- a/src/HTTP/HTTPServer.cpp +++ b/src/HTTP/HTTPServer.cpp @@ -1,7 +1,8 @@ // HTTPServer.cpp -// Implements the cHTTPServer class representing a HTTP webserver that uses cListenThread and cSocketThreads for processing +// Implements the cHTTPServer class representing a HTTP webserver that uses cListenThread and cSocketThreads for +// processing #include "Globals.h" #include "HTTPServer.h" @@ -17,8 +18,8 @@ // Disable MSVC warnings: #if defined(_MSC_VER) - #pragma warning(push) - #pragma warning(disable:4355) // 'this' : used in base member initializer list +#pragma warning(push) +#pragma warning(disable : 4355) // 'this' : used in base member initializer list #endif @@ -28,17 +29,15 @@ //////////////////////////////////////////////////////////////////////////////// // cHTTPServerListenCallbacks: -class cHTTPServerListenCallbacks: - public cNetwork::cListenCallbacks +class cHTTPServerListenCallbacks : public cNetwork::cListenCallbacks { -public: - cHTTPServerListenCallbacks(cHTTPServer & a_HTTPServer, UInt16 a_Port): - m_HTTPServer(a_HTTPServer), - m_Port(a_Port) + public: + cHTTPServerListenCallbacks(cHTTPServer & a_HTTPServer, UInt16 a_Port) : + m_HTTPServer(a_HTTPServer), m_Port(a_Port) { } -protected: + protected: /** The HTTP server instance that we're attached to. */ cHTTPServer & m_HTTPServer; @@ -46,7 +45,8 @@ protected: UInt16 m_Port; // cNetwork::cListenCallbacks overrides: - virtual cTCPLink::cCallbacksPtr OnIncomingConnection(const AString & a_RemoteIPAddress, UInt16 a_RemotePort) override + virtual cTCPLink::cCallbacksPtr OnIncomingConnection(const AString & a_RemoteIPAddress, UInt16 a_RemotePort) + override { return m_HTTPServer.OnIncomingConnection(a_RemoteIPAddress, a_RemotePort); } @@ -86,7 +86,7 @@ bool cHTTPServer::Initialize(void) { // Read the HTTPS cert + key: AString CertFile = cFile::ReadWholeFile("webadmin/httpscert.crt"); - AString KeyFile = cFile::ReadWholeFile("webadmin/httpskey.pem"); + AString KeyFile = cFile::ReadWholeFile("webadmin/httpskey.pem"); if (!CertFile.empty() && !KeyFile.empty()) { auto Cert = std::make_shared<cX509Cert>(); @@ -118,7 +118,8 @@ bool cHTTPServer::Initialize(void) if (m_SslConfig == nullptr) { LOGWARNING("WebServer: The server will run in unsecured HTTP mode."); - LOGINFO("Put a valid HTTPS certificate in file 'webadmin/httpscert.crt' and its corresponding private key to 'webadmin/httpskey.pem' (without any password) to enable HTTPS support"); + LOGINFO("Put a valid HTTPS certificate in file 'webadmin/httpscert.crt' and its corresponding private key to " + "'webadmin/httpskey.pem' (without any password) to enable HTTPS support"); } else { @@ -155,7 +156,7 @@ bool cHTTPServer::Start(cCallbacks & a_Callbacks, const AStringVector & a_Ports) // Inform the admin about the ports opened: AString reportPorts; - for (const auto & port: ports) + for (const auto & port : ports) { if (!reportPorts.empty()) { @@ -214,7 +215,12 @@ void cHTTPServer::NewRequest(cHTTPServerConnection & a_Connection, cHTTPIncoming -void cHTTPServer::RequestBody(cHTTPServerConnection & a_Connection, cHTTPIncomingRequest & a_Request, const void * a_Data, size_t a_Size) +void cHTTPServer::RequestBody( + cHTTPServerConnection & a_Connection, + cHTTPIncomingRequest & a_Request, + const void * a_Data, + size_t a_Size +) { m_Callbacks->OnRequestBody(a_Connection, a_Request, static_cast<const char *>(a_Data), a_Size); } @@ -227,7 +233,3 @@ void cHTTPServer::RequestFinished(cHTTPServerConnection & a_Connection, cHTTPInc { m_Callbacks->OnRequestFinished(a_Connection, a_Request); } - - - - diff --git a/src/HTTP/HTTPServer.h b/src/HTTP/HTTPServer.h index 33f316b51..1e09e9cc9 100644 --- a/src/HTTP/HTTPServer.h +++ b/src/HTTP/HTTPServer.h @@ -1,7 +1,8 @@ // HTTPServer.h -// Declares the cHTTPServer class representing a HTTP webserver that uses cListenThread and cSocketThreads for processing +// Declares the cHTTPServer class representing a HTTP webserver that uses cListenThread and cSocketThreads for +// processing @@ -29,10 +30,10 @@ class cSslConfig; class cHTTPServer { -public: + public: class cCallbacks { - public: + public: virtual ~cCallbacks() {} /** Called when a new request arrives over a connection and all its headers have been parsed. @@ -41,11 +42,16 @@ public: /** Called when another part of request body has arrived. May be called multiple times for a single request. */ - virtual void OnRequestBody(cHTTPServerConnection & a_Connection, cHTTPIncomingRequest & a_Request, const char * a_Data, size_t a_Size) = 0; + virtual void OnRequestBody( + cHTTPServerConnection & a_Connection, + cHTTPIncomingRequest & a_Request, + const char * a_Data, + size_t a_Size + ) = 0; /** Called when the request body has been fully received in previous calls to OnRequestBody() */ virtual void OnRequestFinished(cHTTPServerConnection & a_Connection, cHTTPIncomingRequest & a_Request) = 0; - } ; + }; cHTTPServer(void); virtual ~cHTTPServer(); @@ -59,7 +65,7 @@ public: /** Stops the server, drops all current connections */ void Stop(void); -protected: + protected: friend class cHTTPServerConnection; friend class cSslHTTPServerConnection; friend class cHTTPServerListenCallbacks; @@ -83,13 +89,14 @@ protected: /** Called by cHTTPConenction when it receives more data for the request body. May be called multiple times for a single request. */ - void RequestBody(cHTTPServerConnection & a_Connection, cHTTPIncomingRequest & a_Request, const void * a_Data, size_t a_Size); - - /** Called by cHTTPServerConnection when it detects that the request has finished (all of its body has been received) */ + void RequestBody( + cHTTPServerConnection & a_Connection, + cHTTPIncomingRequest & a_Request, + const void * a_Data, + size_t a_Size + ); + + /** Called by cHTTPServerConnection when it detects that the request has finished (all of its body has been + * received) */ void RequestFinished(cHTTPServerConnection & a_Connection, cHTTPIncomingRequest & a_Request); -} ; - - - - - +}; diff --git a/src/HTTP/HTTPServerConnection.cpp b/src/HTTP/HTTPServerConnection.cpp index f79f08517..fa2b78eb5 100644 --- a/src/HTTP/HTTPServerConnection.cpp +++ b/src/HTTP/HTTPServerConnection.cpp @@ -13,8 +13,7 @@ cHTTPServerConnection::cHTTPServerConnection(cHTTPServer & a_HTTPServer) : - m_HTTPServer(a_HTTPServer), - m_Parser(*this) + m_HTTPServer(a_HTTPServer), m_Parser(*this) { } @@ -43,7 +42,10 @@ void cHTTPServerConnection::SendStatusAndReason(int a_StatusCode, const AString void cHTTPServerConnection::SendNeedAuth(const AString & a_Realm) { - SendData(fmt::format(FMT_STRING("HTTP/1.1 401 Unauthorized\r\nWWW-Authenticate: Basic realm=\"{}\"\r\nContent-Length: 0\r\n\r\n"), a_Realm)); + SendData(fmt::format( + FMT_STRING("HTTP/1.1 401 Unauthorized\r\nWWW-Authenticate: Basic realm=\"{}\"\r\nContent-Length: 0\r\n\r\n"), + a_Realm + )); m_CurrentRequest.reset(); m_Parser.Reset(); } diff --git a/src/HTTP/HTTPServerConnection.h b/src/HTTP/HTTPServerConnection.h index 22e243d93..2459a63ed 100644 --- a/src/HTTP/HTTPServerConnection.h +++ b/src/HTTP/HTTPServerConnection.h @@ -24,11 +24,10 @@ class cHTTPIncomingRequest; -class cHTTPServerConnection : - public cTCPLink::cCallbacks, - public cHTTPMessageParser::cCallbacks +class cHTTPServerConnection : public cTCPLink::cCallbacks, + public cHTTPMessageParser::cCallbacks { -public: + public: /** Creates a new instance, connected to the specified HTTP server instance */ cHTTPServerConnection(cHTTPServer & a_HTTPServer); @@ -60,7 +59,7 @@ public: /** Terminates the connection; finishes any request being currently processed */ void Terminate(void); -protected: + protected: typedef std::map<AString, AString> cNameValueMap; /** The parent webserver that is to be notified of events on this connection */ @@ -104,15 +103,7 @@ protected: /** Sends the raw data over the link. Descendants may provide data transformations (SSL etc.) via the overridable SendData() function. */ - void SendData(const AString & a_Data) - { - SendData(a_Data.data(), a_Data.size()); - } -} ; + void SendData(const AString & a_Data) { SendData(a_Data.data(), a_Data.size()); } +}; typedef std::vector<cHTTPServerConnection *> cHTTPServerConnections; - - - - - diff --git a/src/HTTP/MultipartParser.cpp b/src/HTTP/MultipartParser.cpp index 09f4fd02a..6dfcd1620 100644 --- a/src/HTTP/MultipartParser.cpp +++ b/src/HTTP/MultipartParser.cpp @@ -13,8 +13,8 @@ // Disable MSVC warnings: #if defined(_MSC_VER) - #pragma warning(push) - #pragma warning(disable:4355) // 'this' : used in base member initializer list +#pragma warning(push) +#pragma warning(disable : 4355) // 'this' : used in base member initializer list #endif @@ -92,10 +92,7 @@ ThisIsIgnoredEpilogue"; cMultipartParser::cMultipartParser(const AString & a_ContentType, cCallbacks & a_Callbacks) : - m_Callbacks(a_Callbacks), - m_IsValid(true), - m_EnvelopeParser(*this), - m_HasHadData(false) + m_Callbacks(a_Callbacks), m_IsValid(true), m_EnvelopeParser(*this), m_HasHadData(false) { // Check that the content type is multipart: AString ContentType(a_ContentType); @@ -127,7 +124,8 @@ cMultipartParser::cMultipartParser(const AString & a_ContentType, cCallbacks & a return; } - // Set the envelope parser for parsing the body, so that our Parse() function parses the ignored prefix data as a body + // Set the envelope parser for parsing the body, so that our Parse() function parses the ignored prefix data as a + // body m_EnvelopeParser.SetIsInHeaders(false); // Append an initial CRLF to the incoming data, so that a body starting with the boundary line will get caught @@ -203,8 +201,7 @@ void cMultipartParser::Parse(const char * a_Data, size_t a_Size) } return; } - if ( - (LineEnd - idxBoundary != m_Boundary.size()) && // Line length not equal to boundary + if ((LineEnd - idxBoundary != m_Boundary.size()) && // Line length not equal to boundary (LineEnd - idxBoundary != m_Boundary.size() + 2) // Line length not equal to boundary end ) { @@ -234,7 +231,8 @@ void cMultipartParser::Parse(const char * a_Data, size_t a_Size) continue; } - // It's a line, but not a boundary. It can be fully sent to the data receiver, since a boundary cannot cross lines + // It's a line, but not a boundary. It can be fully sent to the data receiver, since a boundary cannot cross + // lines m_Callbacks.OnPartData(m_IncomingData.c_str(), LineEnd); m_IncomingData.erase(0, LineEnd); } // while (true) @@ -248,7 +246,3 @@ void cMultipartParser::OnHeaderLine(const AString & a_Key, const AString & a_Val { m_Callbacks.OnPartHeader(a_Key, a_Value); } - - - - diff --git a/src/HTTP/MultipartParser.h b/src/HTTP/MultipartParser.h index 4f20b2bed..df836366a 100644 --- a/src/HTTP/MultipartParser.h +++ b/src/HTTP/MultipartParser.h @@ -15,13 +15,12 @@ -class cMultipartParser : - protected cEnvelopeParser::cCallbacks +class cMultipartParser : protected cEnvelopeParser::cCallbacks { -public: + public: class cCallbacks { - public: + public: // Force a virtual destructor in descendants: virtual ~cCallbacks() {} @@ -36,7 +35,7 @@ public: /** Called when the current part ends */ virtual void OnPartEnd(void) = 0; - } ; + }; /** Creates the parser, expects to find the boundary in a_ContentType */ cMultipartParser(const AString & a_ContentType, cCallbacks & a_Callbacks); @@ -44,7 +43,7 @@ public: /** Parses more incoming data */ void Parse(const char * a_Data, size_t a_Size); -protected: + protected: /** The callbacks to call for various parsing events */ cCallbacks & m_Callbacks; @@ -60,20 +59,18 @@ protected: /** The boundary, excluding both the initial "--" and the terminating CRLF */ AString m_Boundary; - /** Set to true if some data for the current part has already been signalized to m_Callbacks. Used for proper CRLF inserting. */ + /** Set to true if some data for the current part has already been signalized to m_Callbacks. Used for proper CRLF + * inserting. */ bool m_HasHadData; /** Parse one line of incoming data. The CRLF has already been stripped from a_Data / a_Size */ void ParseLine(const char * a_Data, size_t a_Size); - /** Parse one line of incoming data in the headers section of a part. The CRLF has already been stripped from a_Data / a_Size */ + /** Parse one line of incoming data in the headers section of a part. The CRLF has already been stripped from a_Data + * / a_Size */ void ParseHeaderLine(const char * a_Data, size_t a_Size); // cEnvelopeParser overrides: virtual void OnHeaderLine(const AString & a_Key, const AString & a_Value) override; -} ; - - - - +}; diff --git a/src/HTTP/NameValueParser.cpp b/src/HTTP/NameValueParser.cpp index d62d05929..4273eec40 100644 --- a/src/HTTP/NameValueParser.cpp +++ b/src/HTTP/NameValueParser.cpp @@ -72,8 +72,7 @@ public: // cNameValueParser: cNameValueParser::cNameValueParser(bool a_AllowsKeyOnly) : - m_State(psKeySpace), - m_AllowsKeyOnly(a_AllowsKeyOnly) + m_State(psKeySpace), m_AllowsKeyOnly(a_AllowsKeyOnly) { } @@ -82,8 +81,7 @@ cNameValueParser::cNameValueParser(bool a_AllowsKeyOnly) : cNameValueParser::cNameValueParser(const char * a_Data, size_t a_Size, bool a_AllowsKeyOnly) : - m_State(psKeySpace), - m_AllowsKeyOnly(a_AllowsKeyOnly) + m_State(psKeySpace), m_AllowsKeyOnly(a_AllowsKeyOnly) { Parse(a_Data, a_Size); } @@ -405,7 +403,3 @@ bool cNameValueParser::Finish(void) } UNREACHABLE("Unsupported name value parser state"); } - - - - diff --git a/src/HTTP/NameValueParser.h b/src/HTTP/NameValueParser.h index e205079db..203f7f032 100644 --- a/src/HTTP/NameValueParser.h +++ b/src/HTTP/NameValueParser.h @@ -13,10 +13,9 @@ -class cNameValueParser : - public std::map<AString, AString> +class cNameValueParser : public std::map<AString, AString> { -public: + public: /** Creates an empty parser */ cNameValueParser(bool a_AllowsKeyOnly = true); @@ -35,20 +34,20 @@ public: /** Returns true if the parser expects no more data */ bool IsFinished(void) const { return ((m_State == psInvalid) || (m_State == psFinished)); } -protected: + protected: enum eState { - psKeySpace, ///< Parsing the space in front of the next key - psKey, ///< Currently adding more chars to the key in m_CurrentKey - psEqualSpace, ///< Space after m_CurrentKey - psEqual, ///< Just parsed the = sign after a name + psKeySpace, ///< Parsing the space in front of the next key + psKey, ///< Currently adding more chars to the key in m_CurrentKey + psEqualSpace, ///< Space after m_CurrentKey + psEqual, ///< Just parsed the = sign after a name psValueInSQuotes, ///< Just parsed a Single-quote sign after the Equal sign psValueInDQuotes, ///< Just parsed a Double-quote sign after the Equal sign - psValueRaw, ///< Just parsed a raw value without a quote - psAfterValue, ///< Just finished parsing the value, waiting for semicolon or data end - psInvalid, ///< The parser has encountered an invalid input; further parsing is skipped - psFinished, ///< The parser has already been instructed to finish and doesn't expect any more data - } ; + psValueRaw, ///< Just parsed a raw value without a quote + psAfterValue, ///< Just finished parsing the value, waiting for semicolon or data end + psInvalid, ///< The parser has encountered an invalid input; further parsing is skipped + psFinished, ///< The parser has already been instructed to finish and doesn't expect any more data + }; /** The current state of the parser */ eState m_State; @@ -61,10 +60,4 @@ protected: /** Buffer for the current Value; */ AString m_CurrentValue; - - -} ; - - - - +}; diff --git a/src/HTTP/SslHTTPServerConnection.cpp b/src/HTTP/SslHTTPServerConnection.cpp index b6f9f246a..b32a24a88 100644 --- a/src/HTTP/SslHTTPServerConnection.cpp +++ b/src/HTTP/SslHTTPServerConnection.cpp @@ -12,10 +12,10 @@ cSslHTTPServerConnection::cSslHTTPServerConnection( - cHTTPServer & a_HTTPServer, const std::shared_ptr<const cSslConfig> & a_Config -): - Super(a_HTTPServer), - m_Ssl(64000) + cHTTPServer & a_HTTPServer, + const std::shared_ptr<const cSslConfig> & a_Config +) : + Super(a_HTTPServer), m_Ssl(64000) { if (a_Config != nullptr) { @@ -115,7 +115,3 @@ void cSslHTTPServerConnection::SendData(const void * a_Data, size_t a_Size) } } } - - - - diff --git a/src/HTTP/SslHTTPServerConnection.h b/src/HTTP/SslHTTPServerConnection.h index 157aa9326..2d293c605 100644 --- a/src/HTTP/SslHTTPServerConnection.h +++ b/src/HTTP/SslHTTPServerConnection.h @@ -16,27 +16,21 @@ -class cSslHTTPServerConnection: - public cHTTPServerConnection +class cSslHTTPServerConnection : public cHTTPServerConnection { using Super = cHTTPServerConnection; -public: - + public: /** Creates a new connection on the specified server. Sends the specified cert as the server certificate, uses the private key for decryption. */ cSslHTTPServerConnection(cHTTPServer & a_HTTPServer, const std::shared_ptr<const cSslConfig> & a_Config); virtual ~cSslHTTPServerConnection() override; -protected: + protected: cBufferedSslContext m_Ssl; // cHTTPConnection overrides: virtual void OnReceivedData(const char * a_Data, size_t a_Size) override; // Data is received from the client virtual void SendData(const void * a_Data, size_t a_Size) override; // Data is to be sent to client -} ; - - - - +}; diff --git a/src/HTTP/TransferEncodingParser.cpp b/src/HTTP/TransferEncodingParser.cpp index 925c919d3..4d5442b12 100644 --- a/src/HTTP/TransferEncodingParser.cpp +++ b/src/HTTP/TransferEncodingParser.cpp @@ -1,7 +1,8 @@ // TransferEncodingParser.cpp -// Implements the cTransferEncodingParser class and its descendants representing the parsers for the various transfer encodings (chunked etc.) +// Implements the cTransferEncodingParser class and its descendants representing the parsers for the various transfer +// encodings (chunked etc.) #include "Globals.h" #include "TransferEncodingParser.h" @@ -14,34 +15,29 @@ //////////////////////////////////////////////////////////////////////////////// // cChunkedTEParser: -class cChunkedTEParser: - public cTransferEncodingParser, - public cEnvelopeParser::cCallbacks +class cChunkedTEParser : public cTransferEncodingParser, + public cEnvelopeParser::cCallbacks { using Super = cTransferEncodingParser; -public: - - cChunkedTEParser(Super::cCallbacks & a_Callbacks): - Super(a_Callbacks), - m_State(psChunkLength), - m_ChunkDataLengthLeft(0), - m_TrailerParser(*this) + public: + cChunkedTEParser(Super::cCallbacks & a_Callbacks) : + Super(a_Callbacks), m_State(psChunkLength), m_ChunkDataLengthLeft(0), m_TrailerParser(*this) { } -protected: + protected: enum eState { - psChunkLength, ///< Parsing the chunk length hex number + psChunkLength, ///< Parsing the chunk length hex number psChunkLengthTrailer, ///< Any trailer (chunk extension) specified after the chunk length - psChunkLengthLF, ///< The LF character after the CR character terminating the chunk length - psChunkData, ///< Relaying chunk data - psChunkDataCR, ///< Skipping the extra CR character after chunk data - psChunkDataLF, ///< Skipping the extra LF character after chunk data - psTrailer, ///< Received an empty chunk, parsing the trailer (through the envelope parser) - psFinished, ///< The parser has finished parsing, either successfully or with an error + psChunkLengthLF, ///< The LF character after the CR character terminating the chunk length + psChunkData, ///< Relaying chunk data + psChunkDataCR, ///< Skipping the extra CR character after chunk data + psChunkDataLF, ///< Skipping the extra LF character after chunk data + psTrailer, ///< Received an empty chunk, parsing the trailer (through the envelope parser) + psFinished, ///< The parser has finished parsing, either successfully or with an error }; /** The current state of the parser (parsing chunk length / chunk data). */ @@ -69,7 +65,8 @@ protected: size_t ParseChunkLength(const char * a_Data, size_t a_Size) { // Expected input: <hexnumber>[;<trailer>]<CR><LF> - // Only the hexnumber is parsed into m_ChunkDataLengthLeft, the rest is postponed into psChunkLengthTrailer or psChunkLengthLF + // Only the hexnumber is parsed into m_ChunkDataLengthLeft, the rest is postponed into psChunkLengthTrailer or + // psChunkLengthLF for (size_t i = 0; i < a_Size; i++) { switch (a_Data[i]) @@ -85,7 +82,8 @@ protected: case '8': case '9': { - m_ChunkDataLengthLeft = m_ChunkDataLengthLeft * 16 + static_cast<decltype(m_ChunkDataLengthLeft)>(a_Data[i] - '0'); + m_ChunkDataLengthLeft = + m_ChunkDataLengthLeft * 16 + static_cast<decltype(m_ChunkDataLengthLeft)>(a_Data[i] - '0'); break; } case 'a': @@ -95,7 +93,8 @@ protected: case 'e': case 'f': { - m_ChunkDataLengthLeft = m_ChunkDataLengthLeft * 16 + static_cast<decltype(m_ChunkDataLengthLeft)>(a_Data[i] - 'a' + 10); + m_ChunkDataLengthLeft = + m_ChunkDataLengthLeft * 16 + static_cast<decltype(m_ChunkDataLengthLeft)>(a_Data[i] - 'a' + 10); break; } case 'A': @@ -105,7 +104,8 @@ protected: case 'E': case 'F': { - m_ChunkDataLengthLeft = m_ChunkDataLengthLeft * 16 + static_cast<decltype(m_ChunkDataLengthLeft)>(a_Data[i] - 'A' + 10); + m_ChunkDataLengthLeft = + m_ChunkDataLengthLeft * 16 + static_cast<decltype(m_ChunkDataLengthLeft)>(a_Data[i] - 'A' + 10); break; } case '\r': @@ -247,8 +247,8 @@ protected: /** Parses the incoming data, the current state is psChunkDataCR. - The trailer is normally a set of "Header: Value" lines, terminated by an empty line. Use the m_TrailerParser for that. - Returns the number of bytes consumed from the input, or AString::npos on error (calls the Error handler). */ + The trailer is normally a set of "Header: Value" lines, terminated by an empty line. Use the m_TrailerParser for + that. Returns the number of bytes consumed from the input, or AString::npos on error (calls the Error handler). */ size_t ParseTrailer(const char * a_Data, size_t a_Size) { auto res = m_TrailerParser.Parse(a_Data, a_Size); @@ -273,14 +273,14 @@ protected: size_t consumed = 0; switch (m_State) { - case psChunkLength: consumed = ParseChunkLength (a_Data, a_Size); break; + case psChunkLength: consumed = ParseChunkLength(a_Data, a_Size); break; case psChunkLengthTrailer: consumed = ParseChunkLengthTrailer(a_Data, a_Size); break; - case psChunkLengthLF: consumed = ParseChunkLengthLF (a_Data, a_Size); break; - case psChunkData: consumed = ParseChunkData (a_Data, a_Size); break; - case psChunkDataCR: consumed = ParseChunkDataCR (a_Data, a_Size); break; - case psChunkDataLF: consumed = ParseChunkDataLF (a_Data, a_Size); break; - case psTrailer: consumed = ParseTrailer (a_Data, a_Size); break; - case psFinished: consumed = 0; break; // Not supposed to happen, but Clang complains without it + case psChunkLengthLF: consumed = ParseChunkLengthLF(a_Data, a_Size); break; + case psChunkData: consumed = ParseChunkData(a_Data, a_Size); break; + case psChunkDataCR: consumed = ParseChunkDataCR(a_Data, a_Size); break; + case psChunkDataLF: consumed = ParseChunkDataLF(a_Data, a_Size); break; + case psTrailer: consumed = ParseTrailer(a_Data, a_Size); break; + case psFinished: consumed = 0; break; // Not supposed to happen, but Clang complains without it } if (consumed == AString::npos) { @@ -296,7 +296,10 @@ protected: { if (m_State != psFinished) { - Error(fmt::format(FMT_STRING("ChunkedTransferEncoding: Finish signal received before the data stream ended (state: {})"), m_State)); + Error(fmt::format( + FMT_STRING("ChunkedTransferEncoding: Finish signal received before the data stream ended (state: {})"), + m_State + )); } m_State = psFinished; } @@ -316,21 +319,18 @@ protected: //////////////////////////////////////////////////////////////////////////////// // cIdentityTEParser: -class cIdentityTEParser: - public cTransferEncodingParser +class cIdentityTEParser : public cTransferEncodingParser { using Super = cTransferEncodingParser; -public: - - cIdentityTEParser(cCallbacks & a_Callbacks, size_t a_ContentLength): - Super(a_Callbacks), - m_BytesLeft(a_ContentLength) + public: + cIdentityTEParser(cCallbacks & a_Callbacks, size_t a_ContentLength) : + Super(a_Callbacks), m_BytesLeft(a_ContentLength) { } -protected: + protected: /** How many bytes of content are left before the message ends. */ size_t m_BytesLeft; @@ -390,7 +390,3 @@ cTransferEncodingParserPtr cTransferEncodingParser::Create( } return nullptr; } - - - - diff --git a/src/HTTP/TransferEncodingParser.h b/src/HTTP/TransferEncodingParser.h index 328186029..0e6ef3f50 100644 --- a/src/HTTP/TransferEncodingParser.h +++ b/src/HTTP/TransferEncodingParser.h @@ -20,10 +20,10 @@ typedef std::shared_ptr<cTransferEncodingParser> cTransferEncodingParserPtr; /** Used as both the interface that all the parsers share and the (static) factory creating such parsers. */ class cTransferEncodingParser { -public: + public: class cCallbacks { - public: + public: // Force a virtual destructor in descendants virtual ~cCallbacks() {} @@ -42,8 +42,8 @@ public: virtual ~cTransferEncodingParser() {} /** Parses the incoming data and calls the appropriate callbacks. - Returns the number of bytes from the end of a_Data that is already not part of this message (if the parser can detect it). - Returns AString::npos on an error. */ + Returns the number of bytes from the end of a_Data that is already not part of this message (if the parser can + detect it). Returns AString::npos on an error. */ virtual size_t Parse(const char * a_Data, size_t a_Size) = 0; /** To be called when the stream is terminated from the source (connection closed). @@ -60,17 +60,13 @@ public: size_t a_ContentLength ); -protected: + protected: /** The callbacks used to report progress. */ cCallbacks & m_Callbacks; - cTransferEncodingParser(cCallbacks & a_Callbacks): + cTransferEncodingParser(cCallbacks & a_Callbacks) : m_Callbacks(a_Callbacks) { } }; - - - - diff --git a/src/HTTP/UrlClient.cpp b/src/HTTP/UrlClient.cpp index 24eeef0f1..433d2b928 100644 --- a/src/HTTP/UrlClient.cpp +++ b/src/HTTP/UrlClient.cpp @@ -25,56 +25,49 @@ using cSchemeHandlerPtr = std::shared_ptr<cSchemeHandler>; namespace { - /** Callbacks implementing the blocking UrlClient behavior. */ - class cBlockingHTTPCallbacks : - public cUrlClient::cCallbacks +/** Callbacks implementing the blocking UrlClient behavior. */ +class cBlockingHTTPCallbacks : public cUrlClient::cCallbacks +{ + public: + explicit cBlockingHTTPCallbacks(std::shared_ptr<cEvent> a_Event, AString & a_ResponseBody) : + m_Event(std::move(a_Event)), m_ResponseBody(a_ResponseBody), m_IsError(false) { - public: - - explicit cBlockingHTTPCallbacks(std::shared_ptr<cEvent> a_Event, AString & a_ResponseBody) : - m_Event(std::move(a_Event)), m_ResponseBody(a_ResponseBody), - m_IsError(false) - { - } + } - void OnBodyFinished() override - { - m_Event->Set(); - } + void OnBodyFinished() override { m_Event->Set(); } - void OnError(const AString & a_ErrorMsg) override - { - LOGERROR("%s %d: HTTP Error: %s", __FILE__, __LINE__, a_ErrorMsg.c_str()); - m_IsError = true; - m_Event->Set(); - } + void OnError(const AString & a_ErrorMsg) override + { + LOGERROR("%s %d: HTTP Error: %s", __FILE__, __LINE__, a_ErrorMsg.c_str()); + m_IsError = true; + m_Event->Set(); + } - void OnBodyData(const void * a_Data, size_t a_Size) override - { - m_ResponseBody.append(static_cast<const char *>(a_Data), a_Size); - } + void OnBodyData(const void * a_Data, size_t a_Size) override + { + m_ResponseBody.append(static_cast<const char *>(a_Data), a_Size); + } - std::shared_ptr<cEvent> m_Event; + std::shared_ptr<cEvent> m_Event; - /** The accumulator for the partial body data, so that OnBodyFinished() can send the entire thing at once. */ - AString & m_ResponseBody; + /** The accumulator for the partial body data, so that OnBodyFinished() can send the entire thing at once. */ + AString & m_ResponseBody; - /** Indicates whether an error was encountered while processing the request. */ - bool m_IsError; - }; -} + /** Indicates whether an error was encountered while processing the request. */ + bool m_IsError; +}; +} // namespace -class cUrlClientRequest: - public cNetwork::cConnectCallbacks, - public cTCPLink::cCallbacks +class cUrlClientRequest : public cNetwork::cConnectCallbacks, + public cTCPLink::cCallbacks { friend class cHttpSchemeHandler; -public: + public: static std::pair<bool, AString> Request( const AString & a_Method, const AString & a_URL, @@ -86,9 +79,9 @@ public: { // Create a new instance of cUrlClientRequest, wrapped in a SharedPtr, so that it has a controlled lifetime. // Cannot use std::make_shared, because the constructor is not public - std::shared_ptr<cUrlClientRequest> ptr (new cUrlClientRequest( - a_Method, a_URL, std::move(a_Callbacks), std::move(a_Headers), a_Body, a_Options - )); + std::shared_ptr<cUrlClientRequest> ptr( + new cUrlClientRequest(a_Method, a_URL, std::move(a_Callbacks), std::move(a_Headers), a_Body, a_Options) + ); return ptr->DoRequest(ptr); } @@ -164,8 +157,7 @@ public: return Cert; } -protected: - + protected: /** Method to be used for the request */ AString m_Method; @@ -211,7 +203,7 @@ protected: AStringMap && a_Headers, const AString & a_Body, const AStringMap & a_Options - ): + ) : m_Method(a_Method), m_Url(a_Url), m_Callbacks(std::move(a_Callbacks)), @@ -237,10 +229,7 @@ protected: // cTCPLink::cCallbacks override: TCP link created - virtual void OnLinkCreated(cTCPLinkPtr a_Link) override - { - m_Link = a_Link; - } + virtual void OnLinkCreated(cTCPLinkPtr a_Link) override { m_Link = a_Link; } // cTCPLink::cCallbacks override: TLS handshake completed on the link: @@ -267,8 +256,8 @@ from right after connecting to the TCP link till the link is closed. For an example of a specific handler, see the cHttpSchemeHandler class. */ class cSchemeHandler abstract { -public: - cSchemeHandler(cUrlClientRequest & a_ParentRequest): + public: + cSchemeHandler(cUrlClientRequest & a_ParentRequest) : m_ParentRequest(a_ParentRequest) { } @@ -294,7 +283,7 @@ public: Sending data on the link is not an error, but the data won't be delivered. */ virtual void OnRemoteClosed(void) = 0; -protected: + protected: cUrlClientRequest & m_ParentRequest; }; @@ -303,19 +292,14 @@ protected: /** cSchemeHandler descendant that handles HTTP (and HTTPS) requests. */ -class cHttpSchemeHandler: - public cSchemeHandler, - protected cHTTPMessageParser::cCallbacks +class cHttpSchemeHandler : public cSchemeHandler, + protected cHTTPMessageParser::cCallbacks { using Super = cSchemeHandler; -public: - - cHttpSchemeHandler(cUrlClientRequest & a_ParentRequest, bool a_IsTls): - Super(a_ParentRequest), - m_Parser(*this), - m_IsTls(a_IsTls), - m_IsRedirect(false) + public: + cHttpSchemeHandler(cUrlClientRequest & a_ParentRequest, bool a_IsTls) : + Super(a_ParentRequest), m_Parser(*this), m_IsTls(a_IsTls), m_IsRedirect(false) { } @@ -325,7 +309,11 @@ public: m_Link = &a_Link; if (m_IsTls) { - m_Link->StartTLSClient(m_ParentRequest.GetOwnCert(), m_ParentRequest.GetOwnPrivKey(), m_ParentRequest.GetTrustedRootCAs()); + m_Link->StartTLSClient( + m_ParentRequest.GetOwnCert(), + m_ParentRequest.GetOwnPrivKey(), + m_ParentRequest.GetTrustedRootCAs() + ); } else { @@ -354,7 +342,7 @@ public: // Send the headers: m_Link->Send(fmt::format(FMT_STRING("Host: {}\r\n"), m_ParentRequest.m_UrlHost)); m_Link->Send(fmt::format(FMT_STRING("Content-Length: {}\r\n"), m_ParentRequest.m_Body.size())); - for (const auto & hdr: m_ParentRequest.m_Headers) + for (const auto & hdr : m_ParentRequest.m_Headers) { m_Link->Send(fmt::format(FMT_STRING("{}: {}\r\n"), hdr.first, hdr.second)); } // for itr - m_Headers[] @@ -379,16 +367,10 @@ public: } - virtual void OnTlsHandshakeCompleted(void) override - { - SendRequest(); - } + virtual void OnTlsHandshakeCompleted(void) override { SendRequest(); } - virtual void OnRemoteClosed(void) override - { - m_Link = nullptr; - } + virtual void OnRemoteClosed(void) override { m_Link = nullptr; } // cHTTPResponseParser::cCallbacks overrides: @@ -405,20 +387,27 @@ public: auto idxFirstSpace = a_FirstLine.find(' '); if (idxFirstSpace == AString::npos) { - m_ParentRequest.CallErrorCallback(fmt::format(FMT_STRING("Failed to parse HTTP status line \"{}\", no space delimiter."), a_FirstLine)); + m_ParentRequest.CallErrorCallback( + fmt::format(FMT_STRING("Failed to parse HTTP status line \"{}\", no space delimiter."), a_FirstLine) + ); return; } auto idxSecondSpace = a_FirstLine.find(' ', idxFirstSpace + 1); if (idxSecondSpace == AString::npos) { - m_ParentRequest.CallErrorCallback(fmt::format(FMT_STRING("Failed to parse HTTP status line \"{}\", missing second space delimiter."), a_FirstLine)); + m_ParentRequest.CallErrorCallback(fmt::format( + FMT_STRING("Failed to parse HTTP status line \"{}\", missing second space delimiter."), + a_FirstLine + )); return; } int resultCode; auto resultCodeStr = a_FirstLine.substr(idxFirstSpace + 1, idxSecondSpace - idxFirstSpace - 1); if (!StringToInteger(resultCodeStr, resultCode)) { - m_ParentRequest.CallErrorCallback(fmt::format(FMT_STRING("Failed to parse HTTP result code from response \"{}\""), resultCodeStr)); + m_ParentRequest.CallErrorCallback( + fmt::format(FMT_STRING("Failed to parse HTTP result code from response \"{}\""), resultCodeStr) + ); return; } @@ -435,7 +424,8 @@ public: return; } } - m_ParentRequest.GetCallbacks().OnStatusLine(a_FirstLine.substr(0, idxFirstSpace), resultCode, a_FirstLine.substr(idxSecondSpace + 1)); + m_ParentRequest.GetCallbacks() + .OnStatusLine(a_FirstLine.substr(0, idxFirstSpace), resultCode, a_FirstLine.substr(idxSecondSpace + 1)); } @@ -497,8 +487,7 @@ public: } } -protected: - + protected: /** The network link. */ cTCPLink * m_Link; @@ -508,9 +497,9 @@ protected: /** If true, the TLS should be started on the link before sending the request (used for https). */ bool m_IsTls; - /** Set to true if the first line contains a redirecting HTTP status code and the options specify to follow redirects. - If true, and the parent request allows redirects, neither headers not the body contents are reported through the callbacks, - and after the entire request is parsed, the redirect is attempted. */ + /** Set to true if the first line contains a redirecting HTTP status code and the options specify to follow + redirects. If true, and the parent request allows redirects, neither headers not the body contents are reported + through the callbacks, and after the entire request is parsed, the redirect is attempted. */ bool m_IsRedirect; /** The Location where the request should be redirected. @@ -644,7 +633,17 @@ std::pair<bool, AString> cUrlClientRequest::DoRequest(const std::shared_ptr<cUrl m_Self = a_Self; // Parse the URL: - auto res = cUrlParser::Parse(m_Url, m_UrlScheme, m_UrlUsername, m_UrlPassword, m_UrlHost, m_UrlPort, m_UrlPath, m_UrlQuery, m_UrlFragment); + auto res = cUrlParser::Parse( + m_Url, + m_UrlScheme, + m_UrlUsername, + m_UrlPassword, + m_UrlHost, + m_UrlPort, + m_UrlPath, + m_UrlQuery, + m_UrlFragment + ); if (!res.first) { return res; @@ -681,9 +680,7 @@ std::pair<bool, AString> cUrlClient::Request( const AStringMap & a_Options ) { - return cUrlClientRequest::Request( - a_Method, a_URL, std::move(a_Callbacks), std::move(a_Headers), a_Body, a_Options - ); + return cUrlClientRequest::Request(a_Method, a_URL, std::move(a_Callbacks), std::move(a_Headers), a_Body, a_Options); } @@ -698,9 +695,7 @@ std::pair<bool, AString> cUrlClient::Get( const AStringMap & a_Options ) { - return cUrlClientRequest::Request( - "GET", a_URL, std::move(a_Callbacks), std::move(a_Headers), a_Body, a_Options - ); + return cUrlClientRequest::Request("GET", a_URL, std::move(a_Callbacks), std::move(a_Headers), a_Body, a_Options); } @@ -715,9 +710,7 @@ std::pair<bool, AString> cUrlClient::Post( const AStringMap & a_Options ) { - return cUrlClientRequest::Request( - "POST", a_URL, std::move(a_Callbacks), std::move(a_Headers), a_Body, a_Options - ); + return cUrlClientRequest::Request("POST", a_URL, std::move(a_Callbacks), std::move(a_Headers), a_Body, a_Options); } @@ -732,9 +725,7 @@ std::pair<bool, AString> cUrlClient::Put( const AStringMap & a_Options ) { - return cUrlClientRequest::Request( - "PUT", a_URL, std::move(a_Callbacks), std::move(a_Headers), a_Body, a_Options - ); + return cUrlClientRequest::Request("PUT", a_URL, std::move(a_Callbacks), std::move(a_Headers), a_Body, a_Options); } @@ -752,7 +743,8 @@ std::pair<bool, AString> cUrlClient::BlockingRequest( auto EvtFinished = std::make_shared<cEvent>(); AString Response; auto Callbacks = std::make_shared<cBlockingHTTPCallbacks>(EvtFinished, Response); - auto [Success, ErrorMessage] = cUrlClient::Request(a_Method, a_URL, Callbacks, std::move(a_Headers), a_Body, a_Options); + auto [Success, ErrorMessage] = + cUrlClient::Request(a_Method, a_URL, Callbacks, std::move(a_Headers), a_Body, a_Options); if (Success) { if (!EvtFinished->Wait(10000)) @@ -813,8 +805,3 @@ std::pair<bool, AString> cUrlClient::BlockingPut( { return BlockingRequest("PUT", a_URL, std::move(a_Headers), a_Body, a_Options); } - - - - - diff --git a/src/HTTP/UrlClient.h b/src/HTTP/UrlClient.h index 6de18672a..402a3f3b3 100644 --- a/src/HTTP/UrlClient.h +++ b/src/HTTP/UrlClient.h @@ -6,10 +6,11 @@ /* Options that can be set via the Options parameter to the cUrlClient calls: "MaxRedirects": The maximum number of allowed redirects before the client refuses a redirect with an error -"OwnCert": The client certificate to use, if requested by the server. Any string that can be parsed by cX509Cert. -"OwnPrivKey": The private key appropriate for OwnCert. Any string that can be parsed by cCryptoKey. +"OwnCert": The client certificate to use, if requested by the server. Any string that can be parsed by +cX509Cert. "OwnPrivKey": The private key appropriate for OwnCert. Any string that can be parsed by cCryptoKey. "OwnPrivKeyPassword": The password for OwnPrivKey. If not present or empty, no password is assumed. -"TrustedRootCAs": The trusted root CA certificates (\n-delimited concatenated PEM format) to be used for peer cert verification. If not present, peer cert is not verified. +"TrustedRootCAs": The trusted root CA certificates (\n-delimited concatenated PEM format) to be used for peer cert +verification. If not present, peer cert is not verified. Behavior: - If a redirect is received, and redirection is allowed, the redirection is reported via OnRedirecting() callback @@ -33,11 +34,11 @@ without reporting the redirect's headers nor body. class cUrlClient { -public: + public: /** Callbacks that are used for progress and result reporting. */ class cCallbacks { - public: + public: // Force a virtual destructor in descendants: virtual ~cCallbacks() {} @@ -51,8 +52,9 @@ public: virtual bool OnCertificateReceived() { return true; } /** Called for TLS connections, when the TLS handshake has been completed. - An empty default implementation is provided so that clients don't need to reimplement it unless they are interested in the event. */ - virtual void OnTlsHandshakeCompleted() { } + An empty default implementation is provided so that clients don't need to reimplement it unless they are + interested in the event. */ + virtual void OnTlsHandshakeCompleted() {} /** Called after the entire request has been sent to the remote peer. */ virtual void OnRequestSent() {} @@ -72,8 +74,8 @@ public: This can be called multiple times, as data arrives over the network. */ virtual void OnBodyData(const void * a_Data, size_t a_Size) {} - /** Called after the response body has been fully reported by OnBody() calls, unless the response is an allowed redirect. - There will be no more OnBody() calls. */ + /** Called after the response body has been fully reported by OnBody() calls, unless the response is an allowed + redirect. There will be no more OnBody() calls. */ virtual void OnBodyFinished() {} /** Called when an asynchronous error is encountered. */ @@ -93,11 +95,11 @@ public: /** Used for HTTP status codes. */ enum eHTTPStatus { - HTTP_STATUS_OK = 200, - HTTP_STATUS_MULTIPLE_CHOICES = 300, // MAY have a redirect using the "Location" header - HTTP_STATUS_MOVED_PERMANENTLY = 301, // redirect using the "Location" header - HTTP_STATUS_FOUND = 302, // redirect using the "Location" header - HTTP_STATUS_SEE_OTHER = 303, // redirect using the "Location" header + HTTP_STATUS_OK = 200, + HTTP_STATUS_MULTIPLE_CHOICES = 300, // MAY have a redirect using the "Location" header + HTTP_STATUS_MOVED_PERMANENTLY = 301, // redirect using the "Location" header + HTTP_STATUS_FOUND = 302, // redirect using the "Location" header + HTTP_STATUS_SEE_OTHER = 303, // redirect using the "Location" header HTTP_STATUS_TEMPORARY_REDIRECT = 307, // redirect using the "Location" header }; @@ -182,7 +184,3 @@ public: const AStringMap & a_Options = {} ); }; - - - - diff --git a/src/HTTP/UrlParser.cpp b/src/HTTP/UrlParser.cpp index f89aaad45..41cb0f428 100644 --- a/src/HTTP/UrlParser.cpp +++ b/src/HTTP/UrlParser.cpp @@ -155,11 +155,8 @@ std::pair<bool, AString> cUrlParser::Parse( } // Parse the Authority part into individual components: - auto res = ParseAuthorityPart( - a_Url.substr(authStart, idxFirstSlash - authStart), - a_Username, a_Password, - a_Host, a_Port - ); + auto res = + ParseAuthorityPart(a_Url.substr(authStart, idxFirstSlash - authStart), a_Username, a_Password, a_Host, a_Port); if (!res.first) { return res; @@ -205,7 +202,3 @@ std::pair<bool, AString> cUrlParser::Validate(const AString & a_Url) UInt16 Port; return Parse(a_Url, UrlScheme, UrlUsername, UrlPassword, UrlHost, Port, UrlPath, UrlQuery, UrlFragment); } - - - - diff --git a/src/HTTP/UrlParser.h b/src/HTTP/UrlParser.h index 76018460a..1027aba2e 100644 --- a/src/HTTP/UrlParser.h +++ b/src/HTTP/UrlParser.h @@ -15,7 +15,7 @@ class cUrlParser { -public: + public: /** Returns true if the specified scheme (http, ftp, mailto, ...) is recognized by the URL parser. Is case sensitive, known schemes are always lowercase. */ static bool IsKnownScheme(const AString & a_Scheme) { return (GetDefaultPort(a_Scheme) > 0); } @@ -55,7 +55,3 @@ public: /** Checks if the supplied URL is valid */ static std::pair<bool, AString> Validate(const AString & a_Url); }; - - - - |