From: Aki Tuomi Date: Wed, 5 Jun 2013 07:15:31 +0000 (+0300) Subject: Support for POST and POST JSON modes X-Git-Tag: rec-3.6.0-rc1~698^2~8 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=5ec8c402fbe1970ecd6e18aad99fae7a2cdbc260;p=thirdparty%2Fpdns.git Support for POST and POST JSON modes --- diff --git a/modules/remotebackend/httpconnector.cc b/modules/remotebackend/httpconnector.cc index b52d858cb8..93ce237ed2 100644 --- a/modules/remotebackend/httpconnector.cc +++ b/modules/remotebackend/httpconnector.cc @@ -4,6 +4,8 @@ #include #include #include +#include "rapidjson/stringbuffer.h" +#include "rapidjson/writer.h" #ifdef REMOTEBACKEND_HTTP #include @@ -22,9 +24,24 @@ HTTPConnector::HTTPConnector(std::map options) { this->d_url_suffix = ""; } this->timeout = 2; + this->d_post = false; + this->d_post_json = false; + if (options.find("timeout") != options.end()) { this->timeout = boost::lexical_cast(options.find("timeout")->second)/1000; } + if (options.find("post") != options.end()) { + std::string val = options.find("post")->second; + if (val == "yes" || val == "true" || val == "on" || val == "1") { + this->d_post = true; + } + } + if (options.find("post_json") != options.end()) { + std::string val = options.find("post_json")->second; + if (val == "yes" || val == "true" || val == "on" || val == "1") { + this->d_post_json = true; + } + } } HTTPConnector::~HTTPConnector() { @@ -88,8 +105,8 @@ template std::string buildMemberListArgs(std::string prefix, const T* return stream.str(); } -// builds our request -void HTTPConnector::requestbuilder(const std::string &method, const rapidjson::Value ¶meters, struct curl_slist **slist) +// builds our request (near-restful) +void HTTPConnector::restful_requestbuilder(const std::string &method, const rapidjson::Value ¶meters, struct curl_slist **slist) { std::stringstream ss; std::string sparam; @@ -258,6 +275,35 @@ void HTTPConnector::requestbuilder(const std::string &method, const rapidjson::V curl_easy_setopt(d_c, CURLOPT_HTTPHEADER, *slist); } +void HTTPConnector::post_requestbuilder(const rapidjson::Document &input, struct curl_slist **slist) { + if (this->d_post_json) { + // simple case, POST JSON into url. nothing fancy. + std::string out = makeStringFromDocument(input); + (*slist) = curl_slist_append((*slist), "Content-Type: text/javascript; charset=utf-8"); + curl_easy_setopt(d_c, CURLOPT_POSTFIELDSIZE, out.size()); + curl_easy_setopt(d_c, CURLOPT_COPYPOSTFIELDS, out.c_str()); + curl_easy_setopt(d_c, CURLOPT_URL, d_url.c_str()); + curl_easy_setopt(d_c, CURLOPT_HTTPHEADER, *slist); + } else { + std::stringstream url,content; + char *tmpstr; + // call url/method.suffix + rapidjson::StringBuffer output; + rapidjson::Writer w(output); + input["parameters"].Accept(w); + url << d_url << "/" << input["method"].GetString() << d_url_suffix; + // then build content + tmpstr = curl_easy_escape(d_c, output.GetString(), 0); + content << "parameters=" << tmpstr; + // convert into parameters=urlencoded + curl_easy_setopt(d_c, CURLOPT_POSTFIELDSIZE, content.str().size()); + curl_easy_setopt(d_c, CURLOPT_COPYPOSTFIELDS, content.str().c_str()); + free(tmpstr); + curl_easy_setopt(d_c, CURLOPT_URL, d_url.c_str()); + curl_easy_setopt(d_c, CURLOPT_URL, url.str().c_str()); + } +} + int HTTPConnector::send_message(const rapidjson::Document &input) { int rv; long rcode; @@ -274,8 +320,12 @@ int HTTPConnector::send_message(const rapidjson::Document &input) { slist = NULL; - // build request - requestbuilder(input["method"].GetString(), input["parameters"], &slist); + // build request based on mode + + if (d_post) + post_requestbuilder(input, &slist); + else + restful_requestbuilder(input["method"].GetString(), input["parameters"], &slist); // setup write function helper curl_easy_setopt(d_c, CURLOPT_WRITEFUNCTION, &(httpconnector_write_data)); diff --git a/modules/remotebackend/remotebackend.hh b/modules/remotebackend/remotebackend.hh index 9e7d052f65..ee2f443d5b 100644 --- a/modules/remotebackend/remotebackend.hh +++ b/modules/remotebackend/remotebackend.hh @@ -66,8 +66,11 @@ class HTTPConnector: public Connector { CURL *d_c; std::string d_data; int timeout; + bool d_post; + bool d_post_json; bool json2string(const rapidjson::Value &input, std::string &output); - void requestbuilder(const std::string &method, const rapidjson::Value ¶meters, struct curl_slist **slist); + void restful_requestbuilder(const std::string &method, const rapidjson::Value ¶meters, struct curl_slist **slist); + void post_requestbuilder(const rapidjson::Document &input, struct curl_slist **slist); void addUrlComponent(const rapidjson::Value ¶meters, const char *element, std::stringstream& ss); }; #endif