diff options
author | jsdelfino <jsdelfino@13f79535-47bb-0310-9956-ffa450edef68> | 2009-11-30 08:36:32 +0000 |
---|---|---|
committer | jsdelfino <jsdelfino@13f79535-47bb-0310-9956-ffa450edef68> | 2009-11-30 08:36:32 +0000 |
commit | ff124040623879bc48a0ba5cf06a841642adef53 (patch) | |
tree | e0bee552780b0852c10744017b7826b08f57d377 /sca-cpp/trunk/modules/http/curl.hpp | |
parent | cd7dae28b034deebc9c2c2469ed9d8f1f3dab1ed (diff) |
Fixes to the http client, httpd modules and memcached component to get the store and shopping cart test case working end to end.
git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@885349 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to '')
-rw-r--r-- | sca-cpp/trunk/modules/http/curl.hpp | 166 |
1 files changed, 115 insertions, 51 deletions
diff --git a/sca-cpp/trunk/modules/http/curl.hpp b/sca-cpp/trunk/modules/http/curl.hpp index 6c3a3a47dc..fd2e9857d1 100644 --- a/sca-cpp/trunk/modules/http/curl.hpp +++ b/sca-cpp/trunk/modules/http/curl.hpp @@ -30,6 +30,7 @@ #include <curl/types.h> #include <curl/easy.h> #include <string> +#include "gc.hpp" #include "list.hpp" #include "value.hpp" #include "element.hpp" @@ -41,11 +42,6 @@ namespace tuscany { namespace http { /** - * Set to true to log HTTP content. - */ -bool logContent = false; - -/** * CURL library context, one per process. */ class CURLContext { @@ -63,22 +59,45 @@ CURLContext curlContext; /** * Represents a CURL session handle. */ -class CURLHandle { +class CURLSession { public: - CURLHandle() : h(curl_easy_init()) { + CURLSession() : ch(new CURLHandle()) { } - ~CURLHandle() { - curl_easy_cleanup(h); + + ~CURLSession() { } - operator CURL*() const { - return h; + CURLSession(const CURLSession& c) : ch(c.ch) { } + private: - CURL* h; + class CURLHandle { + public: + CURLHandle() : h(curl_easy_init()) { + } + ~CURLHandle() { + curl_easy_cleanup(h); + h = NULL; + } + private: + CURL* h; + + friend CURL* handle(const CURLSession& c); + }; + + const gc_ptr<CURLHandle> ch; + + friend CURL* handle(const CURLSession& c); }; /** + * Returns the CURL handle used by a CURL session. + */ +CURL* handle(const CURLSession& c) { + return c.ch->h; +} + +/** * Context passed to the read callback function. */ class CURLReadContext { @@ -143,9 +162,10 @@ curl_slist* headers(curl_slist* cl, const list<std::string>& h) { return headers(curl_slist_append(cl, std::string(car(h)).c_str()), cdr(h)); } -template<typename R> const failable<list<R>, std::string> apply(const list<list<std::string> >& req, const lambda<R(std::string, R)>& reduce, const R& initial, const std::string& url, const std::string& verb, const CURLHandle& ch) { +template<typename R> const failable<list<R>, std::string> apply(const list<list<std::string> >& req, const lambda<R(std::string, R)>& reduce, const R& initial, const std::string& url, const std::string& verb, const CURLSession& cs) { // Init the curl session + CURL* ch = handle(cs); curl_easy_reset(ch); curl_easy_setopt(ch, CURLOPT_USERAGENT, "libcurl/1.0"); @@ -204,7 +224,9 @@ template<typename R> const failable<list<R>, std::string> apply(const list<list< /** * Evaluate an expression remotely, at the given URL. */ -const failable<value, std::string> evalExpr(const value& expr, const std::string& url, const CURLHandle& ch) { +const failable<value, std::string> evalExpr(const value& expr, const std::string& url, const CURLSession& ch) { + debug(url, "http::evalExpr::url"); + debug(expr, "http::evalExpr::input"); // Convert expression to a JSON-RPC request json::JSONContext cx; @@ -212,13 +234,6 @@ const failable<value, std::string> evalExpr(const value& expr, const std::string if (!hasContent(jsreq)) return mkfailure<value, std::string>(reason(jsreq)); - if (logContent) { - std::cout<< "content: " << std::endl; - write(content(jsreq), std::cout); - std::cout<< std::endl; - std::cout.flush(); - } - // POST it to the URL const list<std::string> h = mklist<std::string>("Content-Type: application/json-rpc"); const failable<list<list<std::string> >, std::string> res = apply<list<std::string> >(mklist<list<std::string> >(h, content(jsreq)), rcons<std::string>, list<std::string>(), url, "POST", ch); @@ -226,19 +241,58 @@ const failable<value, std::string> evalExpr(const value& expr, const std::string return mkfailure<value, std::string>(reason(res)); // Return result - if (logContent) { - std::cout << "content:" << std::endl; - write(cadr<list<std::string> >(content(res)), std::cout); - std::cout << std::endl; - } - const list<value> val = elementsToValues(content(json::readJSON(cadr<list<std::string> >(content(res)), cx))); - return cadr<value>(cadr<value>(val)); + failable<list<value>, std::string> jsres = json::readJSON(cadr<list<std::string> >(content(res)), cx); + if (!hasContent(jsres)) + return mkfailure<value, std::string>(reason(jsres)); + const list<value> val = elementsToValues(content(jsres)); + + const value rval(cadr<value>(cadr<value>(val))); + debug(rval, "http::evalExpr::result"); + return rval; +} + +/** + * Find and return a header. + */ +const failable<std::string, std::string> header(const std::string& prefix, const list<std::string>& h) { + if (isNil(h)) + return mkfailure<std::string, std::string>(std::string("Couldn't find header: ") + prefix); + const std::string s = car(h); + if (s.find(prefix) != 0) + return header(prefix, cdr(h)); + const std::string l(s.substr(prefix.length())); + return l.substr(0, l.find_first_of("\r\n")); +} + +/** + * Find and return a location header. + */ +const failable<std::string, std::string> location(const list<std::string>& h) { + return header("Location: ", h); +} + +/** + * Convert a location to an entry id. + */ +const failable<value, std::string> entryId(const failable<std::string, std::string> l) { + if (!hasContent(l)) + return mkfailure<value, std::string>(reason(l)); + const std::string ls(content(l)); + return value(ls.substr(ls.find_last_of("/") + 1)); +} + +/** + * Find and return a content-type header. + */ +const failable<std::string, std::string> contentType(const list<std::string>& h) { + return header("Content-Type: ", h); } /** * HTTP GET, return the resource at the given URL. */ -template<typename R> const failable<list<R>, std::string> get(const lambda<R(std::string, R)>& reduce, const R& initial, const std::string& url, const CURLHandle& ch) { +template<typename R> const failable<list<R>, std::string> get(const lambda<R(std::string, R)>& reduce, const R& initial, const std::string& url, const CURLSession& ch) { + debug(url, "http::get::url"); const list<list<std::string> > req = mklist(list<std::string>(), list<std::string>()); return apply(req, reduce, initial, url, "GET", ch); } @@ -246,38 +300,41 @@ template<typename R> const failable<list<R>, std::string> get(const lambda<R(std /** * HTTP GET, return a list of values representing the resource at the given URL. */ -const failable<value, std::string> get(const std::string& url, const CURLHandle& ch) { +const failable<value, std::string> get(const std::string& url, const CURLSession& ch) { + debug(url, "http::get::url"); // Get the contents of the resource at the given URL const failable<list<list<std::string> >, std::string> res = get<list<std::string> >(rcons<std::string>, list<std::string>(), url, ch); if (!hasContent(res)) return mkfailure<value, std::string>(reason(res)); + const list<std::string> ls(reverse(cadr(content(res)))); - const std::string ct; - if (ct.find("application/atom+xml") != std::string::npos) { - // TODO Return an ATOM feed + const std::string ct(content(contentType(car(content(res))))); + if (ct == "application/atom+xml;type=entry") { + const value val(atom::entryValue(content(atom::readEntry(ls)))); + debug(val, "http::get::result"); + return val; } // Return the content as a string value std::ostringstream os; - write(reverse(cadr(content(res))), os); - return value(os.str()); + write(ls, os); + const value val(os.str()); + debug(val, "http::get::result"); + return val; } /** * HTTP POST. */ -const failable<value, std::string> post(const value& val, const std::string& url, const CURLHandle& ch) { +const failable<value, std::string> post(const value& val, const std::string& url, const CURLSession& ch) { // Convert value to an ATOM entry const failable<list<std::string>, std::string> entry = atom::writeATOMEntry(atom::entryValuesToElements(val)); if (!hasContent(entry)) return mkfailure<value, std::string>(reason(entry)); - if (logContent) { - std::cout << "content:" << std::endl; - write(list<std::string>(content(entry)), std::cout); - std::cout << std::endl; - } + debug(url, "http::post::url"); + debug(content(entry), "http::post::input"); // POST it to the URL const list<std::string> h = mklist<std::string>("Content-Type: application/atom+xml"); @@ -285,23 +342,24 @@ const failable<value, std::string> post(const value& val, const std::string& url const failable<list<list<std::string> >, std::string> res = apply<list<std::string> >(req, rcons<std::string>, list<std::string>(), url, "POST", ch); if (!hasContent(res)) return mkfailure<value, std::string>(reason(res)); - return value(true); + + // Return the new entry id from the HTTP location header + const failable<value, std::string> eid(entryId(location(car(content(res))))); + debug(eid, "http::post::result"); + return eid; } /** * HTTP PUT. */ -const failable<value, std::string> put(const value& val, const std::string& url, const CURLHandle& ch) { +const failable<value, std::string> put(const value& val, const std::string& url, const CURLSession& ch) { // Convert value to an ATOM entry const failable<list<std::string>, std::string> entry = atom::writeATOMEntry(atom::entryValuesToElements(val)); if (!hasContent(entry)) return mkfailure<value, std::string>(reason(entry)); - if (logContent) { - std::cout << "content:" << std::endl; - write(list<std::string>(content(entry)), std::cout); - std::cout << std::endl; - } + debug(url, "http::put::url"); + debug(content(entry), "http::put::input"); // PUT it to the URL const list<std::string> h = mklist<std::string>("Content-Type: application/atom+xml"); @@ -309,17 +367,23 @@ const failable<value, std::string> put(const value& val, const std::string& url, const failable<list<list<std::string> >, std::string> res = apply<list<std::string> >(req, rcons<std::string>, list<std::string>(), url, "PUT", ch); if (!hasContent(res)) return mkfailure<value, std::string>(reason(res)); + + debug(true, "http::put::result"); return value(true); } /** * HTTP DELETE. */ -const failable<value, std::string> del(const std::string& url, const CURLHandle& ch) { +const failable<value, std::string> del(const std::string& url, const CURLSession& ch) { + debug(url, "http::delete::url"); + const list<list<std::string> > req = mklist(list<std::string>(), list<std::string>()); const failable<list<list<std::string> >, std::string> res = apply<list<std::string> >(req, rcons<std::string>, list<std::string>(), url, "DELETE", ch); if (!hasContent(res)) return mkfailure<value, std::string>(reason(res)); + + debug(true, "http::delete::result"); return value(true); } @@ -327,7 +391,7 @@ const failable<value, std::string> del(const std::string& url, const CURLHandle& * HTTP client proxy function. */ struct proxy { - proxy(const std::string& url, const CURLHandle& ch) : url(url), ch(ch) { + proxy(const std::string& url, const CURLSession& ch) : url(url), ch(ch) { } const value operator()(const list<value>& args) const { @@ -338,7 +402,7 @@ struct proxy { } const std::string url; - const CURLHandle& ch; + const CURLSession ch; }; } |