diff --git a/lib/downloader.cpp b/lib/downloader.cpp index 592b60ef..7d9c39ef 100644 --- a/lib/downloader.cpp +++ b/lib/downloader.cpp @@ -64,8 +64,8 @@ namespace HTTP{ Downloader::~Downloader(){S.close();} - /// Sends a request for the given URL, does no waiting. - void Downloader::doRequest(const HTTP::URL &link, const std::string &method, const std::string &body){ + /// Prepares a request for the given URL, does not send anything + void Downloader::prepareRequest(const HTTP::URL &link, const std::string &method){ if (!canRequest(link)){return;} bool needSSL = (link.protocol == "https"); H.Clean(); @@ -131,12 +131,22 @@ namespace HTTP{ H.SetHeader(it->first, it->second); } } - nbLink = link; - H.SendRequest(getSocket(), body); + } + + /// Sends a request for the given URL, does no waiting. + void Downloader::doRequest(const HTTP::URL &link, const std::string &method, const void * body, const size_t bodyLen){ + prepareRequest(link, method); + H.sendRequest(getSocket(), body, bodyLen, false); H.Clean(); } + /// Sends a request for the given URL, does no waiting. + void Downloader::doRequest(const HTTP::URL &link, const std::string &method, const std::string &body){ + doRequest(link, method, body.data(), body.size()); + } + + /// Do a HEAD request to download the HTTP headers only, returns true on success bool Downloader::head(const HTTP::URL &link, uint8_t maxRecursiveDepth){ if (!canRequest(link)){return false;} @@ -361,11 +371,15 @@ namespace HTTP{ } bool Downloader::post(const HTTP::URL &link, const std::string &payload, bool sync, uint8_t maxRecursiveDepth){ + return post(link, payload.data(), payload.size(), sync, maxRecursiveDepth); + } + + bool Downloader::post(const HTTP::URL &link, const void * payload, const size_t payloadLen, bool sync, uint8_t maxRecursiveDepth){ if (!canRequest(link)){return false;} size_t loop = retryCount; // max 5 attempts while (--loop){// loop while we are unsuccessful MEDIUM_MSG("Posting to %s (%zu/%" PRIu32 ")", link.getUrl().c_str(), retryCount - loop + 1, retryCount); - doRequest(link, "POST", payload); + doRequest(link, "POST", payload, payloadLen); // Not synced? Ignore the response and immediately return true. if (!sync){return true;} uint64_t reqTime = Util::bootSecs(); @@ -390,9 +404,9 @@ namespace HTTP{ } if (!canContinue(link)){return false;} if (getStatusCode() >= 300 && getStatusCode() < 400){ - return post(link.link(getHeader("Location")), payload, sync, --maxRecursiveDepth); + return post(link.link(getHeader("Location")), payload, payloadLen, sync, --maxRecursiveDepth); }else{ - return post(link, payload, sync, --maxRecursiveDepth); + return post(link, payload, payloadLen, sync, --maxRecursiveDepth); } } return true; // Success! diff --git a/lib/downloader.h b/lib/downloader.h index 55c1c3d6..5f49ccdb 100644 --- a/lib/downloader.h +++ b/lib/downloader.h @@ -10,13 +10,17 @@ namespace HTTP{ ~Downloader(); std::string &data(); const std::string &const_data() const; - void doRequest(const HTTP::URL &link, const std::string &method = "", - const std::string &body = ""); + void prepareRequest(const HTTP::URL &link, const std::string &method = ""); + void doRequest(const HTTP::URL &link, const std::string &method = "", const void * body = 0, const size_t bodyLen = 0); + void doRequest(const HTTP::URL &link, const std::string &method, const std::string &body); bool get(const std::string &link, Util::DataCallback &cb = Util::defaultDataCallback); bool get(const HTTP::URL &link, uint8_t maxRecursiveDepth = 6, Util::DataCallback &cb = Util::defaultDataCallback); - bool head(const HTTP::URL &link,uint8_t maxRecursiveDepth = 6); - bool getRange(const HTTP::URL &link, size_t byteStart, size_t byteEnd, Util::DataCallback &cb = Util::defaultDataCallback); - bool getRangeNonBlocking(const HTTP::URL &link, size_t byteStart, size_t byteEnd, Util::DataCallback &cb = Util::defaultDataCallback); + bool head(const HTTP::URL &link, uint8_t maxRecursiveDepth = 6); + bool getRange(const HTTP::URL &link, size_t byteStart, size_t byteEnd, + Util::DataCallback &cb = Util::defaultDataCallback); + bool getRangeNonBlocking(const HTTP::URL &link, size_t byteStart, size_t byteEnd, + Util::DataCallback &cb = Util::defaultDataCallback); + bool post(const HTTP::URL &link, const void * payload, const size_t payloadLen, bool sync = true, uint8_t maxRecursiveDepth = 6); bool post(const HTTP::URL &link, const std::string &payload, bool sync = true, uint8_t maxRecursiveDepth = 6); diff --git a/lib/http_parser.cpp b/lib/http_parser.cpp index 8c6a79c4..222c474d 100644 --- a/lib/http_parser.cpp +++ b/lib/http_parser.cpp @@ -163,6 +163,10 @@ std::string &HTTP::Parser::BuildRequest(){ /// The request is build from internal variables set before this call is made. /// To be precise, method, url, protocol, headers and body are used. void HTTP::Parser::SendRequest(Socket::Connection &conn, const std::string &reqbody, bool allAtOnce){ + sendRequest(conn, reqbody.data(), reqbody.size(), allAtOnce); +} + +void HTTP::Parser::sendRequest(Socket::Connection &conn, const void * reqbody, const size_t reqbodyLen, bool allAtOnce){ /// \todo Include GET/POST variable parsing? if (allAtOnce){ /// \TODO Make this less duplicated / more pretty. @@ -170,15 +174,15 @@ void HTTP::Parser::SendRequest(Socket::Connection &conn, const std::string &reqb std::map::iterator it; if (protocol.size() < 5 || protocol[4] != '/'){protocol = "HTTP/1.0";} builder = method + " " + url + " " + protocol + "\r\n"; - if (reqbody.size()){SetHeader("Content-Length", reqbody.length());} + if (reqbodyLen){SetHeader("Content-Length", reqbodyLen);} for (it = headers.begin(); it != headers.end(); it++){ if ((*it).first != "" && (*it).second != ""){ builder += (*it).first + ": " + (*it).second + "\r\n"; } } builder += "\r\n"; - if (reqbody.size()){ - builder += reqbody; + if (reqbodyLen){ + builder += std::string((char*)reqbody, reqbodyLen); }else{ builder += body; } @@ -189,7 +193,7 @@ void HTTP::Parser::SendRequest(Socket::Connection &conn, const std::string &reqb if (protocol.size() < 5 || protocol[4] != '/'){protocol = "HTTP/1.0";} builder = method + " " + url + " " + protocol + "\r\n"; conn.SendNow(builder); - if (reqbody.size()){SetHeader("Content-Length", reqbody.length());} + if (reqbodyLen){SetHeader("Content-Length", reqbodyLen);} for (it = headers.begin(); it != headers.end(); it++){ if ((*it).first != "" && (*it).second != ""){ builder = (*it).first + ": " + (*it).second + "\r\n"; @@ -197,8 +201,8 @@ void HTTP::Parser::SendRequest(Socket::Connection &conn, const std::string &reqb } } conn.SendNow("\r\n", 2); - if (reqbody.size()){ - conn.SendNow(reqbody); + if (reqbodyLen){ + conn.SendNow((char*)reqbody, reqbodyLen); }else{ conn.SendNow(body); } diff --git a/lib/http_parser.h b/lib/http_parser.h index b35ee08d..bec9b1b8 100644 --- a/lib/http_parser.h +++ b/lib/http_parser.h @@ -39,6 +39,7 @@ namespace HTTP{ std::string &BuildResponse(); std::string &BuildResponse(std::string code, std::string message); void SendRequest(Socket::Connection &conn, const std::string &reqbody = "", bool allAtOnce = false); + void sendRequest(Socket::Connection &conn, const void * body = 0, const size_t bodyLen = 0, bool allAtOnce = false); void SendResponse(std::string code, std::string message, Socket::Connection &conn); void StartResponse(std::string code, std::string message, Parser &request, Socket::Connection &conn, bool bufferAllChunks = false);