diff --git a/src/com/HTTP/httplayer.cpp b/src/com/HTTP/httplayer.cpp index a37931e9e..c27cd2622 100644 --- a/src/com/HTTP/httplayer.cpp +++ b/src/com/HTTP/httplayer.cpp @@ -28,8 +28,7 @@ using namespace forte::com_infra; using namespace std::string_literals; CHttpComLayer::CHttpComLayer(CComLayer* paUpperLayer, CBaseCommFB* paComFB) : - CComLayer(paUpperLayer, paComFB), mInterruptResp(e_Nothing), mRequestType(e_NOTSET), mPort(80), mBufFillSize(0), mCorrectlyInitialized(false), - mHasParameterInSD(false) { + CComLayer(paUpperLayer, paComFB), mInterruptResp(e_Nothing), mRequestType(e_NOTSET), mPort(80), mBufFillSize(0), mCorrectlyInitialized(false) { memset(mRecvBuffer, 0, sizeof(mRecvBuffer)); } @@ -39,7 +38,6 @@ CHttpComLayer::~CHttpComLayer() { EComResponse CHttpComLayer::openConnection(char *paLayerParameter) { EComResponse eRetVal = e_InitInvalidId; - if(checkSDsAndRDsType()) { switch(mFb->getComServiceType()){ case e_Server: @@ -62,73 +60,26 @@ EComResponse CHttpComLayer::openConnection(char *paLayerParameter) { break; } } - mCorrectlyInitialized = (eRetVal == e_InitOk); return eRetVal; } EComResponse CHttpComLayer::openClientConnection(char* paLayerParameter) { EComResponse eRetVal = e_InitInvalidId; - TPortId numberOfSD = mFb->getNumSD(); - - if(2 == mFb->getNumRD()) { + if(2 == mFb->getNumRD() && 3 == mFb->getNumSD()) { CParameterParser parser(paLayerParameter, ';', 3); //IP:PORT;POST|PUT|GET;[content-type] - - if(handleContentAndRequestType(parser, parser.parseParameters()) && handleAddress(parser[0], numberOfSD)) { - - switch(mRequestType){ - case e_PUT: - case e_POST: - if(checkSDInPOSTAndPUT(numberOfSD)) { - CHttpParser::createPutPostRequest(mRequest, mHost, mPath, mReqData, mContentType, mRequestType); - eRetVal = e_InitOk; - DEVLOG_INFO("[HTTP Layer] FB with PUT/POST request initialized. Host: %s, Path: %s\n", mHost.c_str(), mPath.c_str()); - } - break; - case e_GET: - if(0 != numberOfSD) { - DEVLOG_WARNING("[HTTP Layer] FB with GET request has SD which are ignore. If you want to have parameters, put them in the path in the PARAMS\n"); - } - CHttpParser::createGetRequest(mRequest, mHost, mPath); - eRetVal = e_InitOk; - DEVLOG_INFO("[HTTP Layer] FB with GET request initialized. Host: %s, Path: %s\n", mHost.c_str(), mPath.c_str()); - break; - default: - break; - } - } + handleContentAndRequestType(parser, parser.parseParameters()); + handleAddress(parser[0]); + eRetVal = e_InitOk; } else { DEVLOG_ERROR( - "[HTTP Layer] A client should ALWAYS have exactly 2 RD, the first one for the response code, and the second for the response body, even for PUT and POST\n"); + "[HTTP Layer] A client should ALWAYS have exactly 2 RD, the first one for the response code, and the second for the response body, and ALWAYS exactly 3 SD one for authentication, one for parameters, and one for the body.\n"); } - mConnectionState = e_Disconnected; return eRetVal; } -bool CHttpComLayer::checkSDInPOSTAndPUT(size_t paNoOfSD) { - bool evetythingOK = true; - - if(0 == paNoOfSD) { - if(mReqData.empty()) { - DEVLOG_ERROR("[HTTP Layer] You are using a POST/PUT FB but no data is defined as SD nor as parameters in PARAMS\n"); - evetythingOK = false; - } - } else if(1 == paNoOfSD) { - if(!mReqData.empty()) { - DEVLOG_WARNING("[HTTP Layer] Parameters in PARAMS are ignored for PUT/POST request data and SDs are sent instead\n"); - } - mHasParameterInSD = true; - } else { - DEVLOG_ERROR("[HTTP Layer] You can use maximum 1 SD\n"); - evetythingOK = false; - } - - return evetythingOK; -} - bool CHttpComLayer::checkSDsAndRDsType() const { - for(size_t i = 2; i < mFb->getNumSD(); i++) { CIEC_ANY::EDataTypeID typeToCheck = mFb->getDI(static_cast(i))->getDataTypeID(); if(CIEC_ANY::e_ANY != typeToCheck && CIEC_ANY::e_STRING != typeToCheck && CIEC_ANY::e_WSTRING != typeToCheck) { @@ -136,7 +87,6 @@ bool CHttpComLayer::checkSDsAndRDsType() const { return false; } } - for(size_t i = 2; i < mFb->getNumRD(); i++) { CIEC_ANY::EDataTypeID typeToCheck = mFb->getDO(static_cast(i))->getDataTypeID(); if(CIEC_ANY::e_ANY != typeToCheck && CIEC_ANY::e_STRING != typeToCheck && CIEC_ANY::e_WSTRING != typeToCheck) { @@ -178,22 +128,11 @@ bool CHttpComLayer::handleContentAndRequestType(CParameterParser &paParser, size return everythingOK; } -bool CHttpComLayer::handleAddress(const char* paAddress, size_t paNoOfSDs) { +bool CHttpComLayer::handleAddress(const char* paAddress) { bool everythingOK = true; - //look for parameters - CParameterParser parser(paAddress, '?', 2); //IP:PORT/PATH?PARAMETERS std::string addressToParse(paAddress); - if(2 == parser.parseParameters() && (e_PUT == mRequestType || e_POST == mRequestType)) { - if(0 == paNoOfSDs) { //if SDs are present, the parameters in PARAMS are ignored - mReqData = std::string(parser[1]); - mContentType = "application/x-www-form-urlencoded"s; - } - addressToParse = std::string(parser[0]); - } - char *firstSlash = strchr(addressToParse.data(), '/'); - if(firstSlash) { mPath = std::string(firstSlash); *firstSlash = '\0'; @@ -212,15 +151,20 @@ bool CHttpComLayer::handleAddress(const char* paAddress, size_t paNoOfSDs) { return everythingOK; } +const CIEC_ANY& CHttpComLayer::getSDx(void *paData, int paSdNum){ + const CIEC_ANY **sds = static_cast(paData); + return sds[paSdNum]->unwrap(); +} + EComResponse CHttpComLayer::sendData(void *paData, unsigned int) { mInterruptResp = e_Nothing; if(mCorrectlyInitialized) { switch(mFb->getComServiceType()){ case e_Server: - sendDataAsServer(paData); + sendDataAsServer(getSDx(paData, 0), getSDx(paData, 1), getSDx(paData, 2)); break; case e_Client: - sendDataAsClient(paData); + sendDataAsClient(getSDx(paData, 0), getSDx(paData, 1), getSDx(paData, 2)); break; default: // e_Publisher and e_Subscriber @@ -233,47 +177,41 @@ EComResponse CHttpComLayer::sendData(void *paData, unsigned int) { return mInterruptResp; } -void CHttpComLayer::sendDataAsServer(const void *paData) { - bool error = false; - const CIEC_ANY* apoSDs = static_cast(paData); - if(!serializeData(apoSDs[0])) { - error = true; - } else { - CHttpParser::createResponse(mRequest, "HTTP/1.1 200 OK"s, "text/plain"s, mReqData); - } - if(error) { - getExtEvHandler().forceClose(this); - mInterruptResp = e_ProcessDataDataTypeError; - } else { - getExtEvHandler().sendServerAnswer(this, mRequest); - mInterruptResp = e_ProcessDataOk; +void CHttpComLayer::createRequest() { + switch (mRequestType) { + case e_PUT: + case e_POST: + CHttpParser::createPutPostRequest(mRequest, mHost, mPort, mPath, mAuth, mParams, mBody, mContentType, mRequestType); + DEVLOG_INFO( + "[HTTP Layer] FB with PUT/POST request initialized. Host: %s, Path: %s:%d, Parameters: '%s'\n", + mHost.c_str(), mPath.c_str(), mPort, mParams.c_str()); + break; + case e_GET: + CHttpParser::createGetRequest(mRequest, mHost, mPort, mPath, mAuth, mParams); + DEVLOG_INFO("[HTTP Layer] FB with GET request initialized. Host: %s, Path: %s, Parameters: '%s'\n", mHost.c_str(), mPath.c_str(), mParams.c_str()); + break; + default: + break; } } -void CHttpComLayer::sendDataAsClient(const void *paData) { - bool error = false; - if(mHasParameterInSD) { - const CIEC_ANY* apoSDs = static_cast(paData); - if(!serializeData(apoSDs[0])) { - error = true; - DEVLOG_ERROR("[HTTP Layer] Error in data serialization\n"); - } else { - if(!CHttpParser::changePutPostData(mRequest, mReqData)) { - DEVLOG_ERROR("[HTTP Layer] Wrong PUT/POST request when changing the data\n"); - error = true; - } - } - } +void CHttpComLayer::sendDataAsServer(const CIEC_ANY &paSD0, const CIEC_ANY &paSD1, const CIEC_ANY &paSD2) { + serializeData(paSD0, paSD1, paSD2); + createRequest(); + CHttpParser::createResponse(mRequest, "HTTP/1.1 200 OK"s, "text/plain"s, mBody); + getExtEvHandler().sendServerAnswer(this, mRequest); + mInterruptResp = e_ProcessDataOk; +} - if(!error) { - if(getExtEvHandler().sendClientData(this, mRequest)) { - mInterruptResp = e_ProcessDataOk; - } else { - mInterruptResp = e_ProcessDataSendFailed; - DEVLOG_ERROR("[HTTP Layer] Sending request on TCP failed\n"); - } +void CHttpComLayer::sendDataAsClient(const CIEC_ANY &paSD0, const CIEC_ANY &paSD1, const CIEC_ANY &paSD2) { + serializeData(paSD0, paSD1, paSD2); + createRequest(); + if(getExtEvHandler().sendClientData(this, mRequest)) { + mInterruptResp = e_ProcessDataOk; } else { mInterruptResp = e_ProcessDataDataTypeError; + mInterruptResp = e_ProcessDataSendFailed; + DEVLOG_ERROR("[HTTP Layer] Sending request on TCP failed\n"); } } @@ -334,8 +272,8 @@ EComResponse forte::com_infra::CHttpComLayer::recvServerData(CSinglyLinkedList().sendServerAnswerFromRecv(this, toSend); mInterruptResp = e_ProcessDataDataTypeError; } else { @@ -376,25 +314,22 @@ void CHttpComLayer::closeConnection() { getExtEvHandler().forceClose(this); } -bool CHttpComLayer::serializeData(const CIEC_ANY& paCIECData) { - size_t bufferSize = paCIECData.getToStringBufferSize(); - mReqData.reserve(static_cast(bufferSize)); - char *buffer = mReqData.data(); - int nWrittenBytes; - switch(paCIECData.getDataTypeID()){ - case CIEC_ANY::e_WSTRING: - nWrittenBytes = static_cast(paCIECData).toUTF8(buffer, bufferSize, false); - break; - case CIEC_ANY::e_STRING: - nWrittenBytes = static_cast(paCIECData).toUTF8(buffer, bufferSize, false); - break; - default: - nWrittenBytes = paCIECData.toString(buffer, bufferSize); +void CHttpComLayer::serializeData(const CIEC_ANY& paSD0, const CIEC_ANY& paSD1, const CIEC_ANY& paSD2) { + if(CIEC_ANY::e_WSTRING == paSD0.getDataTypeID()){ + mAuth = static_cast(paSD0).getValue(); + }else if(CIEC_ANY::e_STRING == paSD0.getDataTypeID()){ + mAuth = static_cast(paSD0).getStorage(); + } + if(CIEC_ANY::e_WSTRING == paSD1.getDataTypeID()){ + mParams = static_cast(paSD1).getValue(); + }else if(CIEC_ANY::e_STRING == paSD1.getDataTypeID()){ + mParams = static_cast(paSD1).getStorage(); + } + if(CIEC_ANY::e_WSTRING == paSD2.getDataTypeID()){ + mBody = static_cast(paSD2).getValue(); + }else if(CIEC_ANY::e_STRING == paSD2.getDataTypeID()){ + mBody = static_cast(paSD2).getStorage(); } - - nWrittenBytes = nWrittenBytes > -1 ? nWrittenBytes : 0; - mReqData.assign(buffer, static_cast(nWrittenBytes)); - return true; } std::string& forte::com_infra::CHttpComLayer::getHost() { diff --git a/src/com/HTTP/httplayer.h b/src/com/HTTP/httplayer.h index bc6fa6eed..50050da4e 100644 --- a/src/com/HTTP/httplayer.h +++ b/src/com/HTTP/httplayer.h @@ -70,24 +70,26 @@ namespace forte { EComResponse handleHTTPResponse(char *paData); /** Serializes the data to a char* */ - bool serializeData(const CIEC_ANY& paCIECData); + void serializeData(const CIEC_ANY& paSD0, const CIEC_ANY& paSD1, const CIEC_ANY& paSD2); - void sendDataAsServer(const void *paData); + void sendDataAsServer(const CIEC_ANY &paSD0, const CIEC_ANY &paSD1, const CIEC_ANY &paSD2); - void sendDataAsClient(const void *paData); + void sendDataAsClient(const CIEC_ANY &paSD0, const CIEC_ANY &paSD1, const CIEC_ANY &paSD2); - EComResponse openClientConnection(char* paLayerParameter); + const CIEC_ANY& getSDx(void *paData, int paSdNum); - bool checkSDInPOSTAndPUT(size_t paNoOfSD); + EComResponse openClientConnection(char* paLayerParameter); bool checkSDsAndRDsType() const; - bool handleAddress(const char* paAddress, size_t paNoOfSDs); + bool handleAddress(const char* paAddress); bool handleContentAndRequestType(CParameterParser &paParser, size_t paNoOfParameters); bool storeRequestType(const char* paType); + void createRequest(); + EComResponse mInterruptResp; /** Represents the HTTP request type (0 = GET, 1 = PUT). */ @@ -96,10 +98,14 @@ namespace forte { std::string mHost; /** Path in host */ std::string mPath; + /** Parameters */ + std::string mParams; /** Data to be sent */ - std::string mReqData; + std::string mBody; /** Port of the host */ TForteUInt16 mPort; + /** Authentication */ + std::string mAuth; /** Request to be sent to Host */ std::string mRequest; diff --git a/src/com/HTTP/httpparser.cpp b/src/com/HTTP/httpparser.cpp index 760680c64..d56c086bf 100644 --- a/src/com/HTTP/httpparser.cpp +++ b/src/com/HTTP/httpparser.cpp @@ -13,45 +13,41 @@ ********************************************************************************/ #include "httpparser.h" + #include #include -#include "devlog.h" + +#include "../../arch/datatype.h" +#include "../../arch/devlog.h" +#include "../../core/utils/parameterParser.h" using namespace forte::com_infra; using namespace std::string_literals; -void CHttpParser::createGetRequest(std::string& paDest, const std::string& paHost, const std::string& paPath) { - CHttpParser::addCommonHeader(paDest, paHost, paPath, CHttpComLayer::e_GET); +void CHttpParser::createGetRequest (std::string &paDest, const std::string &paHost, const TForteUInt16 paPort, const std::string &paPath, const std::string &paAuth, const std::string &paParams) { + CHttpParser::addCommonHeader(paDest, paHost, paPort, paPath, paAuth, paParams, CHttpComLayer::e_GET); CHttpParser::addHeaderEnding(paDest); } -void CHttpParser::createPutPostRequest(std::string& paDest, const std::string& paHost, const std::string& paPath, const std::string& paData, - const std::string& paContentType, CHttpComLayer::ERequestType paType) { - CHttpParser::addCommonHeader(paDest, paHost, paPath, paType); - paDest.append("\r\nContent-type: "s); - paDest.append(paContentType); - paDest.append("\r\nContent-length: "s); - changePutPostData(paDest, paData); -} - -bool CHttpParser::changePutPostData(std::string& paDest, const std::string& paData) { - char* helperChar = strstr(paDest.data(), "length: "); - if(nullptr != helperChar) { - helperChar += sizeof("length: ") - 1; - *helperChar = '\0'; - paDest = std::string(paDest.c_str()); // will shrink the length of the string to the new ending - char contentLength[std::numeric_limits::digits10 + 1]; - snprintf(contentLength, sizeof(contentLength), "%zu", strlen(paData.c_str())); - paDest.append(contentLength); +void CHttpParser::addBodyToRequest (const std::string &paBody, const std::string &paContentType, std::string &paDest) { + if(!paContentType.empty()){ + paDest += "\r\nContent-Type: "s; + paDest += paContentType; + paDest += "\r\nContent-Length: "s; + paDest += std::to_string(paBody.length()); CHttpParser::addHeaderEnding(paDest); - paDest.append(paData); - return true; - } else { // wrong request? - DEVLOG_ERROR("[HTTP Parser] PUT/POST request was wrongly created\n"); - return false; + } + if (!paBody.empty()) { + paDest += paBody; } } +void CHttpParser::createPutPostRequest (std::string &paDest, const std::string &paHost, const TForteUInt16 paPort, const std::string &paPath, const std::string &paAuth, const std::string &paParams, const std::string &paBody, + const std::string& paContentType, CHttpComLayer::ERequestType paType) { + CHttpParser::addCommonHeader(paDest, paHost, paPort, paPath, paAuth, paParams, paType); + addBodyToRequest(paBody, paContentType, paDest); +} + bool CHttpParser::parseResponse(std::string& paBody, std::string& paResponseCode, char* paSrc) { if(CHttpParser::getHttpResponseCode(paResponseCode, paSrc)) { char* helperChar = strstr(paSrc, "\r\n\r\n"); // Extract data from HTTP response char @@ -139,19 +135,12 @@ CHttpComLayer::ERequestType forte::com_infra::CHttpParser::getTypeOfRequest(cons } void forte::com_infra::CHttpParser::createResponse(std::string& paDest, const std::string& paResult, const std::string& paContentType, - const std::string& paData) { + const std::string& paBody) { paDest = paResult; - if(paData.empty()) { - paDest.append("\r\n"s); - } else { - paDest.append("\r\nContent-type: "s); - paDest.append(paContentType); - paDest.append("\r\nContent-length: "s); - changePutPostData(paDest, paData); - } + addBodyToRequest(paBody, paContentType, paDest); } -void CHttpParser::addCommonHeader(std::string& paDest, const std::string& paHost, const std::string& paPath, CHttpComLayer::ERequestType paType) { +void CHttpParser::addCommonHeader (std::string &paDest, const std::string &paHost, const TForteUInt16 paPort, const std::string &paPath, const std::string &paAuth, const std::string &paParams, CHttpComLayer::ERequestType paType) { switch(paType){ case CHttpComLayer::e_GET: paDest = "GET "s; @@ -166,15 +155,24 @@ void CHttpParser::addCommonHeader(std::string& paDest, const std::string& paHost DEVLOG_ERROR("[HTTP Parser] Unexpected HTTP Type when adding header\n"); break; } - - paDest.append(paPath); - paDest.append(" HTTP/1.1\r\n"s); - paDest.append("Host: "s); - paDest.append(paHost); + paDest += paPath; + if(!paParams.empty()){ + paDest += "?"s; + paDest += paParams; + } + paDest += " HTTP/1.1\r\n"s; + paDest += "Host: "s; + paDest += paHost; + paDest += ":"s; + paDest += std::to_string(paPort); + if(!paAuth.empty()){ + paDest += "\r\nAuthorization: "s; + paDest += paAuth; + } } void CHttpParser::addHeaderEnding(std::string& paDest) { - paDest.append("\r\n\r\n"s); + paDest += "\r\n\r\n"s; } bool CHttpParser::getHttpResponseCode(std::string& paDest, char* paSrc) { diff --git a/src/com/HTTP/httpparser.h b/src/com/HTTP/httpparser.h index 2c6dfbf41..c6f31de40 100644 --- a/src/com/HTTP/httpparser.h +++ b/src/com/HTTP/httpparser.h @@ -31,29 +31,33 @@ namespace forte { * Generates a HTTP GET request. The request is written to paDest * @param paDest place to store the request * @param paHost host of the server to connect + * @param paPort port of the server to connect * @param paPath path to look for + * @param paParams parameters to consider for the request */ - static void createGetRequest(std::string& paDest, const std::string& paHost, const std::string& paPath); + static void createGetRequest(std::string& paDest, const std::string& paHost, const TForteUInt16 paPort, const std::string& paPath, const std::string &paAuth, const std::string& paParams); /** * Generates a HTTP PUT request. The request is written to paDest. * @param paDest place to store the request * @param paHost host of the server to connect + * @param paPort port of the server to connect * @param paPath path to access in the server + * @param paParams parameters to consider for the request * @param paData data in the body to send to the server * @param paContentType content type of the request * @param paType PUT or POST */ - static void createPutPostRequest(std::string& paDest, const std::string& paHost, const std::string& paPath, const std::string& paData, + static void createPutPostRequest(std::string& paDest, const std::string& paHost, const TForteUInt16 paPort, const std::string& paPath, const std::string &paAuth, const std::string& paParams, const std::string& paBody, const std::string& paContentType, CHttpComLayer::ERequestType paType); /** - * Takes a previous PUT request in paDest, and updates the content of it + * Adds a body to the request. * @param paDest old request - * @param paData new data - * @return true if no error happened, false otherwise + * @param paContentType type of the body + * @param paBody body of the request */ - static bool changePutPostData(std::string& paDest, const std::string& paData); + static void addBodyToRequest (const std::string &paBody, const std::string &paContentType, std::string &paDest); /** * Extracts data from a response to a HTTP request @@ -108,10 +112,12 @@ namespace forte { * Creates the common parts of the headers of the supported types * @param paDest place to store the header * @param paHost server host to be written in the header + * @param paPort server port to be written in the header * @param paPath the path to be written in the header + * @param paParams parameters to consider for the request * @param paType the type of request to be written in the header */ - static void addCommonHeader(std::string& paDest, const std::string& paHost, const std::string& paPath, CHttpComLayer::ERequestType paType); + static void addCommonHeader (std::string &paDest, const std::string &paHost, const TForteUInt16 paPort, const std::string &paPath, const std::string &paAuth, const std::string &paParams, CHttpComLayer::ERequestType paType); /** * Appends the ending "\r\n\r\n" to the HTTP request diff --git a/src/core/utils/parameterParser.cpp b/src/core/utils/parameterParser.cpp index 101a12518..c420926a4 100644 --- a/src/core/utils/parameterParser.cpp +++ b/src/core/utils/parameterParser.cpp @@ -19,7 +19,7 @@ CParameterParser::CParameterParser(const char* paParameters, const char paSepara mSeparator(paSeparator) { mParameterLocations.reserve(paExpectedNumParams); if (paParameters != nullptr) - { // make a copy of the parameter string for porcessing + { // make a copy of the parameter string for processing mParameters = new char[strlen(paParameters) + 1](); strcpy(mParameters, paParameters); } else { // if nullptr provide valid empty size-1 char array diff --git a/tests/modules/HTTP/HTTP_test.cpp b/tests/modules/HTTP/HTTP_test.cpp index d47951286..c0606441d 100644 --- a/tests/modules/HTTP/HTTP_test.cpp +++ b/tests/modules/HTTP/HTTP_test.cpp @@ -17,124 +17,114 @@ using namespace std::string_literals; BOOST_AUTO_TEST_SUITE (HTTPParser_function_test) BOOST_AUTO_TEST_CASE(createGetRequest_test) { - - const char* resultValid1 = "GET / HTTP/1.1\r\nHost: 0.0.0.0\r\n\r\n"; - const char* resultValid2 = "GET / HTTP/1.1\r\nHost: 192.168.0.1\r\n\r\n"; - const char* resultValid3 = "GET /lookFor HTTP/1.1\r\nHost: 192.168.0.1\r\n\r\n"; - const char* resultValid4 = "GET /lookFor/something/else HTTP/1.1\r\nHost: 192.168.0.1\r\n\r\n"; - - std::string dest("random text"s); - std::string host("0.0.0.0"s); - std::string path("/"s); - - forte::com_infra::CHttpParser::createGetRequest(dest, host, path); + std::string dest = "random text"s; + std::string host = "0.0.0.0"s; + short unsigned int port = 80; + std::string path = "/"s; + std::string auth = ""s; + std::string params = ""s; + + const char* resultValid1 = "GET / HTTP/1.1\r\nHost: 0.0.0.0:80\r\n\r\n"; + forte::com_infra::CHttpParser::createGetRequest(dest, host, port, path, auth, params); BOOST_TEST(dest == resultValid1); - host = std::string("192.168.0.1"); - forte::com_infra::CHttpParser::createGetRequest(dest, host, path); + const char* resultValid2 = "GET / HTTP/1.1\r\nHost: 192.168.0.1:80\r\n\r\n"; + host = "192.168.0.1"; + forte::com_infra::CHttpParser::createGetRequest(dest, host, port, path, auth, params); BOOST_TEST(dest == resultValid2); - path = std::string("/lookFor"); - forte::com_infra::CHttpParser::createGetRequest(dest, host, path); + const char* resultValid3 = "GET /lookFor HTTP/1.1\r\nHost: 192.168.0.1:80\r\n\r\n"; + path = "/lookFor"; + forte::com_infra::CHttpParser::createGetRequest(dest, host, port, path, auth, params); BOOST_TEST(dest == resultValid3); - path = std::string("/lookFor/something/else"); - forte::com_infra::CHttpParser::createGetRequest(dest, host, path); + const char* resultValid4 = "GET /lookFor/something/else HTTP/1.1\r\nHost: 192.168.0.1:80\r\n\r\n"; + path = "/lookFor/something/else"; + forte::com_infra::CHttpParser::createGetRequest(dest, host, port, path, auth, params); BOOST_TEST(dest == resultValid4); } BOOST_AUTO_TEST_CASE(PUTPOST_test) { - - const char* putResultValid1 = "PUT / HTTP/1.1\r\nHost: 0.0.0.0\r\nContent-type: text/xml\r\nContent-length: 19\r\n\r\nkey1=val1;key2=val2"; - const char* putResultValid1Changed = - "PUT / HTTP/1.1\r\nHost: 0.0.0.0\r\nContent-type: text/xml\r\nContent-length: 33\r\n\r\nkey1=val1Changed;key2Changed=val2"; - const char* putResultValid2 = "PUT / HTTP/1.1\r\nHost: 192.168.0.1\r\nContent-type: text/xml\r\nContent-length: 19\r\n\r\nkey1=val1;key2=val2"; - const char* putResultValid3 = "PUT /lookFor HTTP/1.1\r\nHost: 192.168.0.1\r\nContent-type: text/xml\r\nContent-length: 19\r\n\r\nkey1=val1;key2=val2"; - const char* putResultValid4 = - "PUT /lookFor/something/else HTTP/1.1\r\nHost: 192.168.0.1\r\nContent-type: text/xml\r\nContent-length: 19\r\n\r\nkey1=val1;key2=val2"; - - const char* putEmptyData = "PUT /lookFor/something/else HTTP/1.1\r\nHost: 192.168.0.1\r\nContent-type: text/xml\r\nContent-length: 0\r\n\r\n"; - const char* putJSONType = - "PUT /lookFor/something/else HTTP/1.1\r\nHost: 192.168.0.1\r\nContent-type: application/json\r\nContent-length: 29\r\n\r\n{\"key1\" : val1,\"key2\" : val2}"; - - const char* postResultValid1 = "POST / HTTP/1.1\r\nHost: 0.0.0.0\r\nContent-type: text/xml\r\nContent-length: 19\r\n\r\nkey1=val1;key2=val2"; - const char* postResultValid1Changed = - "POST / HTTP/1.1\r\nHost: 0.0.0.0\r\nContent-type: text/xml\r\nContent-length: 33\r\n\r\nkey1=val1Changed;key2Changed=val2"; - const char* postResultValid2 = "POST / HTTP/1.1\r\nHost: 192.168.0.1\r\nContent-type: text/xml\r\nContent-length: 19\r\n\r\nkey1=val1;key2=val2"; - const char* postResultValid3 = "POST /lookFor HTTP/1.1\r\nHost: 192.168.0.1\r\nContent-type: text/xml\r\nContent-length: 19\r\n\r\nkey1=val1;key2=val2"; - const char* postResultValid4 = - "POST /lookFor/something/else HTTP/1.1\r\nHost: 192.168.0.1\r\nContent-type: text/xml\r\nContent-length: 19\r\n\r\nkey1=val1;key2=val2"; - - const char* postEmptyData = "POST /lookFor/something/else HTTP/1.1\r\nHost: 192.168.0.1\r\nContent-type: text/xml\r\nContent-length: 0\r\n\r\n"; - - const char* postJSONType = - "POST /lookFor/something/else HTTP/1.1\r\nHost: 192.168.0.1\r\nContent-type: application/json\r\nContent-length: 29\r\n\r\n{\"key1\" : val1,\"key2\" : val2}"; - - std::string dest("random text"s); + std::string dest = "random text"s; std::string destEmpty; - std::string host("0.0.0.0"s); - std::string path("/"s); - std::string data("key1=val1;key2=val2"s); - std::string dataChanged("key1=val1Changed;key2Changed=val2"s); - std::string contentType("text/xml"s); - - forte::com_infra::CHttpParser::createPutPostRequest(dest, host, path, data, contentType, forte::com_infra::CHttpComLayer::e_PUT); - BOOST_TEST(dest == putResultValid1); - BOOST_TEST(true == forte::com_infra::CHttpParser::changePutPostData(dest, dataChanged)); - BOOST_TEST(dest == putResultValid1Changed); - BOOST_TEST(true == forte::com_infra::CHttpParser::changePutPostData(dest, data)); + std::string host = "0.0.0.0"s; + short unsigned int port = 80; + std::string path = "/"s; + std::string auth = ""s; + std::string params = "key1=val1;key2=val2"s; + std::string body = "content of the body"s; + std::string contentType = "text/xml"s; + + const char* putResultValid1 = "PUT /?key1=val1;key2=val2 HTTP/1.1\r\nHost: 0.0.0.0:80\r\nContent-Type: text/xml\r\nContent-Length: 19\r\n\r\ncontent of the body"; + const char* postResultValid1 = "POST /?key1=val1;key2=val2 HTTP/1.1\r\nHost: 0.0.0.0:80\r\nContent-Type: text/xml\r\nContent-Length: 19\r\n\r\ncontent of the body"; + forte::com_infra::CHttpParser::createPutPostRequest(dest, host, port, path, auth, params, body, contentType, forte::com_infra::CHttpComLayer::e_PUT); BOOST_TEST(dest == putResultValid1); - - forte::com_infra::CHttpParser::createPutPostRequest(dest, host, path, data, contentType, forte::com_infra::CHttpComLayer::e_POST); - BOOST_TEST(dest == postResultValid1); - BOOST_TEST(true == forte::com_infra::CHttpParser::changePutPostData(dest, dataChanged)); - BOOST_TEST(dest == postResultValid1Changed); - BOOST_TEST(true == forte::com_infra::CHttpParser::changePutPostData(dest, data)); + forte::com_infra::CHttpParser::createPutPostRequest(dest, host, port, path, auth, params, body, contentType, forte::com_infra::CHttpComLayer::e_POST); BOOST_TEST(dest == postResultValid1); - BOOST_TEST(false == forte::com_infra::CHttpParser::changePutPostData(destEmpty, data)); - dataChanged.clear(); - BOOST_TEST(false == forte::com_infra::CHttpParser::changePutPostData(destEmpty, dataChanged)); - - host = std::string("192.168.0.1"s); - forte::com_infra::CHttpParser::createPutPostRequest(dest, host, path, data, contentType, forte::com_infra::CHttpComLayer::e_PUT); + const char* putResultValid2 = "PUT /?key1=val1;key2=val2 HTTP/1.1\r\nHost: 192.168.0.1:80\r\nContent-Type: text/xml\r\nContent-Length: 19\r\n\r\ncontent of the body"; + const char* postResultValid2 = "POST /?key1=val1;key2=val2 HTTP/1.1\r\nHost: 192.168.0.1:80\r\nContent-Type: text/xml\r\nContent-Length: 19\r\n\r\ncontent of the body"; + host = "192.168.0.1"s; + forte::com_infra::CHttpParser::createPutPostRequest(dest, host, port, path, auth, params, body, contentType, forte::com_infra::CHttpComLayer::e_PUT); BOOST_TEST(dest == putResultValid2); - forte::com_infra::CHttpParser::createPutPostRequest(dest, host, path, data, contentType, forte::com_infra::CHttpComLayer::e_POST); + forte::com_infra::CHttpParser::createPutPostRequest(dest, host, port, path, auth, params, body, contentType, forte::com_infra::CHttpComLayer::e_POST); BOOST_TEST(dest == postResultValid2); - path = std::string("/lookFor"s); - forte::com_infra::CHttpParser::createPutPostRequest(dest, host, path, data, contentType, forte::com_infra::CHttpComLayer::e_PUT); + const char* putResultValid3 = "PUT /lookFor?key1=val1;key2=val2 HTTP/1.1\r\nHost: 192.168.0.1:80\r\nContent-Type: text/xml\r\nContent-Length: 19\r\n\r\ncontent of the body"; + const char* postResultValid3 = "POST /lookFor?key1=val1;key2=val2 HTTP/1.1\r\nHost: 192.168.0.1:80\r\nContent-Type: text/xml\r\nContent-Length: 19\r\n\r\ncontent of the body"; + path = "/lookFor"s; + forte::com_infra::CHttpParser::createPutPostRequest(dest, host, port, path, auth, params, body, contentType, forte::com_infra::CHttpComLayer::e_PUT); BOOST_TEST(dest == putResultValid3); - forte::com_infra::CHttpParser::createPutPostRequest(dest, host, path, data, contentType, forte::com_infra::CHttpComLayer::e_POST); + forte::com_infra::CHttpParser::createPutPostRequest(dest, host, port, path, auth, params, body, contentType, forte::com_infra::CHttpComLayer::e_POST); BOOST_TEST(dest == postResultValid3); - path = std::string("/lookFor/something/else"s); - forte::com_infra::CHttpParser::createPutPostRequest(dest, host, path, data, contentType, forte::com_infra::CHttpComLayer::e_PUT); + const char* putResultValid4 = "PUT /lookFor/something/else?key1=val1;key2=val2 HTTP/1.1\r\nHost: 192.168.0.1:80\r\nContent-Type: text/xml\r\nContent-Length: 19\r\n\r\ncontent of the body"; + const char* postResultValid4 = "POST /lookFor/something/else?key1=val1;key2=val2 HTTP/1.1\r\nHost: 192.168.0.1:80\r\nContent-Type: text/xml\r\nContent-Length: 19\r\n\r\ncontent of the body"; + path = "/lookFor/something/else"s; + forte::com_infra::CHttpParser::createPutPostRequest(dest, host, port, path, auth, params, body, contentType, forte::com_infra::CHttpComLayer::e_PUT); BOOST_TEST(dest == putResultValid4); - forte::com_infra::CHttpParser::createPutPostRequest(dest, host, path, data, contentType, forte::com_infra::CHttpComLayer::e_POST); + forte::com_infra::CHttpParser::createPutPostRequest(dest, host, port, path, auth, params, body, contentType, forte::com_infra::CHttpComLayer::e_POST); BOOST_TEST(dest == postResultValid4); - data.clear(); - forte::com_infra::CHttpParser::createPutPostRequest(dest, host, path, data, contentType, forte::com_infra::CHttpComLayer::e_PUT); + const char* putEmptyData = "PUT /lookFor/something/else?key1=val1;key2=val2 HTTP/1.1\r\nHost: 192.168.0.1:80\r\nContent-Type: text/xml\r\nContent-Length: 0\r\n\r\n"; + const char* postEmptyData = "POST /lookFor/something/else?key1=val1;key2=val2 HTTP/1.1\r\nHost: 192.168.0.1:80\r\nContent-Type: text/xml\r\nContent-Length: 0\r\n\r\n"; + body.clear(); + forte::com_infra::CHttpParser::createPutPostRequest(dest, host, port, path, auth, params, body, contentType, forte::com_infra::CHttpComLayer::e_PUT); BOOST_TEST(dest == putEmptyData); - forte::com_infra::CHttpParser::createPutPostRequest(dest, host, path, data, contentType, forte::com_infra::CHttpComLayer::e_POST); + forte::com_infra::CHttpParser::createPutPostRequest(dest, host, port, path, auth, params, body, contentType, forte::com_infra::CHttpComLayer::e_POST); BOOST_TEST(dest == postEmptyData); - contentType = std::string("application/json"s); - data = std::string("{\"key1\" : val1,\"key2\" : val2}"s); - forte::com_infra::CHttpParser::createPutPostRequest(dest, host, path, data, contentType, forte::com_infra::CHttpComLayer::e_PUT); + const char* putJSONType = "PUT /lookFor/something/else?key1=val1;key2=val2 HTTP/1.1\r\nHost: 192.168.0.1:80\r\nContent-Type: application/json\r\nContent-Length: 29\r\n\r\n{\"key1\" : val1,\"key2\" : val2}"; + const char* postJSONType = "POST /lookFor/something/else?key1=val1;key2=val2 HTTP/1.1\r\nHost: 192.168.0.1:80\r\nContent-Type: application/json\r\nContent-Length: 29\r\n\r\n{\"key1\" : val1,\"key2\" : val2}"; + contentType = "application/json"s; + body = "{\"key1\" : val1,\"key2\" : val2}"s; + forte::com_infra::CHttpParser::createPutPostRequest(dest, host, port, path, auth, params, body, contentType, forte::com_infra::CHttpComLayer::e_PUT); BOOST_TEST(dest == putJSONType); - forte::com_infra::CHttpParser::createPutPostRequest(dest, host, path, data, contentType, forte::com_infra::CHttpComLayer::e_POST); + forte::com_infra::CHttpParser::createPutPostRequest(dest, host, port, path, auth, params, body, contentType, forte::com_infra::CHttpComLayer::e_POST); BOOST_TEST(dest == postJSONType); + + const char* putWithoutParams = "PUT /lookFor/something/else HTTP/1.1\r\nHost: 192.168.0.1:80\r\nContent-Type: application/json\r\nContent-Length: 29\r\n\r\n{\"key1\" : val1,\"key2\" : val2}"; + const char* postWithoutParams = "POST /lookFor/something/else HTTP/1.1\r\nHost: 192.168.0.1:80\r\nContent-Type: application/json\r\nContent-Length: 29\r\n\r\n{\"key1\" : val1,\"key2\" : val2}"; + params = ""s; + forte::com_infra::CHttpParser::createPutPostRequest(dest, host, port, path, auth, params, body, contentType, forte::com_infra::CHttpComLayer::e_PUT); + BOOST_TEST(dest == putWithoutParams); + forte::com_infra::CHttpParser::createPutPostRequest(dest, host, port, path, auth, params, body, contentType, forte::com_infra::CHttpComLayer::e_POST); + BOOST_TEST(dest == postWithoutParams); + + const char* putWithAuth = "PUT /lookFor/something/else HTTP/1.1\r\nHost: 192.168.0.1:80\r\nAuthorization: Token hereComesTheToken\r\nContent-Type: application/json\r\nContent-Length: 29\r\n\r\n{\"key1\" : val1,\"key2\" : val2}"; + const char* postWitAuth = "POST /lookFor/something/else HTTP/1.1\r\nHost: 192.168.0.1:80\r\nAuthorization: Token hereComesTheToken\r\nContent-Type: application/json\r\nContent-Length: 29\r\n\r\n{\"key1\" : val1,\"key2\" : val2}"; + auth = "Token hereComesTheToken"s; + forte::com_infra::CHttpParser::createPutPostRequest(dest, host, port, path, auth, params, body, contentType, forte::com_infra::CHttpComLayer::e_PUT); + BOOST_TEST(dest == putWithAuth); + forte::com_infra::CHttpParser::createPutPostRequest(dest, host, port, path, auth, params, body, contentType, forte::com_infra::CHttpComLayer::e_POST); + BOOST_TEST(dest == postWitAuth); } BOOST_AUTO_TEST_CASE(parseResponse_test) { - - std::string validReponse("HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\nkey1=val1;key2=val2"s); - std::string validReponseNoBody("HTTP/1.1 200 OK\r\n"s); - std::string worngFirstLine("HTTP/1.1 200 OK\nContent-Type: text/html"s); - std::string worngStatusLine("HTTP/1.1 200OK\r\nContent-Type: text/html\r\n\r\nkey1=val1;key2=val2"s); - + std::string validReponse = "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\nkey1=val1;key2=val2"s; + std::string validReponseNoBody = "HTTP/1.1 200 OK\r\nContent-Type: application/json\r\nContent-Length: 0\r\n\r\n"s; + std::string worngFirstLine = "HTTP/1.1 200 OK\nContent-Type: text/html"s; + std::string worngStatusLine = "HTTP/1.1 200OK\r\nContent-Type: text/html\r\n\r\nkey1=val1;key2=val2"s; std::string body; std::string responseCode; @@ -152,34 +142,30 @@ BOOST_AUTO_TEST_SUITE (HTTPParser_function_test) } BOOST_AUTO_TEST_CASE(createResponse_test) { - - const char* validResult = "HTTP/1.1 200 OK\r\nContent-type: application/json\r\nContent-length: 29\r\n\r\n{\"key1\" : val1,\"key2\" : val2}"; - const char* validResultNoBody = "HTTP/1.1 200 OK\r\n"; - std::string dest; - std::string result("HTTP/1.1 200 OK"s); - std::string contentType("application/json"s); - std::string data("{\"key1\" : val1,\"key2\" : val2}"s); + std::string result = "HTTP/1.1 200 OK"s; + std::string contentType = "application/json"s; + std::string data = "{\"key1\" : val1,\"key2\" : val2}"s; + const char* validResult = "HTTP/1.1 200 OK\r\nContent-Type: application/json\r\nContent-Length: 29\r\n\r\n{\"key1\" : val1,\"key2\" : val2}"; forte::com_infra::CHttpParser::createResponse(dest, result, contentType, data); BOOST_TEST(dest == validResult); + const char* validResultNoBody = "HTTP/1.1 200 OK\r\nContent-Type: application/json\r\nContent-Length: 0\r\n\r\n"; data.clear(); forte::com_infra::CHttpParser::createResponse(dest, result, contentType, data); BOOST_TEST(dest == validResultNoBody); - } BOOST_AUTO_TEST_CASE(parseGetRequest_test) { - std::string resultValidNoParameters("GET / HTTP/1.1\r\nHost: 0.0.0.0\r\n\r\n"s); - std::string resultValidNoParameters2("GET /path/to/look HTTP/1.1\r\nHost: 0.0.0.0\r\n\r\n"s); - std::string resultValidParam("GET /?key1=val1 HTTP/1.1\r\nHost: 0.0.0.0\r\n\r\n"s); - std::string resultValidParams("GET /?key1=val1&key2=val2 HTTP/1.1\r\nHost: 0.0.0.0\r\n\r\n"s); - std::string resultValidParam2("GET /path/to/look?key1=val1 HTTP/1.1\r\nHost: 0.0.0.0\r\n\r\n"s); - std::string resultValidParams2("GET /path/to/look?key1=val1&key2=val2 HTTP/1.1\r\nHost: 0.0.0.0\r\n\r\n"s); - - std::string invalidGET("Get / HTTP/1.1\r\nHost: 0.0.0.0\r\n\r\n"s); - std::string invalidPath("GET /pathHTTP/1.1\r\n"s); + std::string resultValidNoParameters = "GET / HTTP/1.1\r\nHost: 0.0.0.0\r\n\r\n"s; + std::string resultValidNoParameters2 = "GET /path/to/look HTTP/1.1\r\nHost: 0.0.0.0\r\n\r\n"s; + std::string resultValidParam = "GET /?key1=val1 HTTP/1.1\r\nHost: 0.0.0.0\r\n\r\n"s; + std::string resultValidParams = "GET /?key1=val1&key2=val2 HTTP/1.1\r\nHost: 0.0.0.0\r\n\r\n"s; + std::string resultValidParam2 = "GET /path/to/look?key1=val1 HTTP/1.1\r\nHost: 0.0.0.0\r\n\r\n"s; + std::string resultValidParams2 = "GET /path/to/look?key1=val1&key2=val2 HTTP/1.1\r\nHost: 0.0.0.0\r\n\r\n"s; + std::string invalidGET = "Get / HTTP/1.1\r\nHost: 0.0.0.0\r\n\r\n"s; + std::string invalidPath = "GET /pathHTTP/1.1\r\n"s; std::string path; CSinglyLinkedList parameterNames;