summaryrefslogtreecommitdiffstats
path: root/sca-cpp/trunk/modules/http/curl.hpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--sca-cpp/trunk/modules/http/curl.hpp190
1 files changed, 98 insertions, 92 deletions
diff --git a/sca-cpp/trunk/modules/http/curl.hpp b/sca-cpp/trunk/modules/http/curl.hpp
index 85665c2785..3478a590fd 100644
--- a/sca-cpp/trunk/modules/http/curl.hpp
+++ b/sca-cpp/trunk/modules/http/curl.hpp
@@ -29,7 +29,7 @@
#include <curl/curl.h>
#include <curl/types.h>
#include <curl/easy.h>
-#include <string>
+#include "string.hpp"
#include "gc.hpp"
#include "list.hpp"
#include "value.hpp"
@@ -62,7 +62,7 @@ CURLContext curlContext;
*/
class CURLSession {
public:
- CURLSession() : ch(new CURLHandle()) {
+ CURLSession() : ch(new (gc_new<CURLHandle>()) CURLHandle()) {
}
~CURLSession() {
@@ -103,9 +103,9 @@ CURL* handle(const CURLSession& c) {
*/
class CURLReadContext {
public:
- CURLReadContext(const list<std::string>& ilist) : ilist(ilist) {
+ CURLReadContext(const list<string>& ilist) : ilist(ilist) {
}
- list<std::string> ilist;
+ list<string> ilist;
};
/**
@@ -115,11 +115,11 @@ size_t readCallback(void *ptr, size_t size, size_t nmemb, void *data) {
CURLReadContext& rcx = *static_cast<CURLReadContext*>(data);
if (isNil(rcx.ilist))
return 0;
- rcx.ilist = fragment(rcx.ilist, size * nmemb);
- const std::string s = car(rcx.ilist);
- rcx.ilist = cdr(rcx.ilist);
- s.copy((char*)ptr, s.length());
- return s.length();
+ const list<string> f(fragment(rcx.ilist, size * nmemb));
+ const string s = car(f);
+ rcx.ilist = cdr(f);
+ memcpy(ptr, c_str(s), length(s));
+ return length(s);
}
/**
@@ -127,9 +127,9 @@ size_t readCallback(void *ptr, size_t size, size_t nmemb, void *data) {
*/
template<typename R> class CURLWriteContext {
public:
- CURLWriteContext(const lambda<R(const std::string&, const R)>& reduce, const R& accum) : reduce(reduce), accum(accum) {
+ CURLWriteContext(const lambda<R(const string&, const R)>& reduce, const R& accum) : reduce(reduce), accum(accum) {
}
- const lambda<R(const std::string&, const R)> reduce;
+ const lambda<R(const string&, const R)> reduce;
R accum;
};
@@ -137,33 +137,23 @@ public:
* Called by CURL to write received data.
*/
template<typename R> size_t writeCallback(void *ptr, size_t size, size_t nmemb, void *data) {
- CURLWriteContext<R>& wcx = *(static_cast<CURLWriteContext<R>*> (data));
- const size_t realsize = size * nmemb;
- wcx.accum = wcx.reduce(std::string((const char*)ptr, realsize), wcx.accum);
- return realsize;
-}
-
-/**
- * Called by CURL to write received header data.
- */
-template<typename R> size_t headerCallback(void *ptr, size_t size, size_t nmemb, void *data) {
- CURLWriteContext<R>& wcx = *(static_cast<CURLWriteContext<R>*> (data));
- const size_t realsize = size * nmemb;
- wcx.accum = wcx.reduce(std::string((const char*)ptr, realsize), wcx.accum);
- return realsize;
+ CURLWriteContext<R>& wcx = *(static_cast<CURLWriteContext<R>*> (data));
+ const size_t realsize = size * nmemb;
+ wcx.accum = wcx.reduce(string((const char*)ptr, realsize), wcx.accum);
+ return realsize;
}
/**
* Apply an HTTP verb to a list containing a list of headers and a list of content, and
* a reduce function used to process the response.
*/
-curl_slist* headers(curl_slist* cl, const list<std::string>& h) {
+curl_slist* headers(curl_slist* cl, const list<string>& h) {
if (isNil(h))
return cl;
- return headers(curl_slist_append(cl, std::string(car(h)).c_str()), cdr(h));
+ return headers(curl_slist_append(cl, c_str(string(car(h)))), cdr(h));
}
-template<typename R> const failable<list<R>, std::string> apply(const list<list<std::string> >& req, const lambda<R(const std::string&, const R)>& reduce, const R& initial, const std::string& url, const std::string& verb, const CURLSession& cs) {
+template<typename R> const failable<list<R> > apply(const list<list<string> >& hdr, const lambda<R(const string&, const R)>& reduce, const R& initial, const string& url, const string& verb, const CURLSession& cs) {
// Init the curl session
CURL* ch = handle(cs);
@@ -171,30 +161,30 @@ template<typename R> const failable<list<R>, std::string> apply(const list<list<
curl_easy_setopt(ch, CURLOPT_USERAGENT, "libcurl/1.0");
//TODO use HTTP chunking, for now just convert request to a single string
- std::ostringstream os;
- write(cadr(req), os);
- const std::string s = os.str();
- const int sz = s.length();
+ ostringstream os;
+ write(cadr(hdr), os);
+ const string s = str(os);
+ const int sz = length(s);
// Setup the read, header and write callbacks
CURLReadContext rcx(mklist(s));
curl_easy_setopt(ch, CURLOPT_READFUNCTION, (size_t (*)(void*, size_t, size_t, void*))readCallback);
curl_easy_setopt(ch, CURLOPT_READDATA, &rcx);
CURLWriteContext<R> hcx(reduce, initial);
- curl_easy_setopt(ch, CURLOPT_HEADERFUNCTION, (size_t (*)(void*, size_t, size_t, void*))headerCallback<R>);
+ curl_easy_setopt(ch, CURLOPT_HEADERFUNCTION, (size_t (*)(void*, size_t, size_t, void*))(writeCallback<R>));
curl_easy_setopt(ch, CURLOPT_HEADERDATA, &hcx);
CURLWriteContext<R> wcx(reduce, initial);
- curl_easy_setopt(ch, CURLOPT_WRITEFUNCTION, (size_t (*)(void*, size_t, size_t, void*))writeCallback<R>);
+ curl_easy_setopt(ch, CURLOPT_WRITEFUNCTION, (size_t (*)(void*, size_t, size_t, void*))(writeCallback<R>));
curl_easy_setopt(ch, CURLOPT_WRITEDATA, &wcx);
curl_easy_setopt(ch, CURLOPT_TCP_NODELAY, true);
// Set the request headers
- curl_slist* hl = headers(NULL, car(req));
+ curl_slist* hl = headers(NULL, car(hdr));
if (hl != NULL)
curl_easy_setopt(ch, CURLOPT_HTTPHEADER, hl);
// Apply the HTTP verb
- curl_easy_setopt(ch, CURLOPT_URL, url.c_str());
+ curl_easy_setopt(ch, CURLOPT_URL, c_str(url));
if (verb == "POST") {
curl_easy_setopt(ch, CURLOPT_POST, true);
curl_easy_setopt(ch, CURLOPT_POSTFIELDSIZE, sz);
@@ -210,13 +200,13 @@ template<typename R> const failable<list<R>, std::string> apply(const list<list<
// Return the HTTP return code or content
if (rc)
- return mkfailure<list<R>, std::string>(curl_easy_strerror(rc));
+ return mkfailure<list<R> >(string(curl_easy_strerror(rc)));
long httprc;
curl_easy_getinfo (ch, CURLINFO_RESPONSE_CODE, &httprc);
if (httprc != 200 && httprc != 201) {
- std::ostringstream es;
+ ostringstream es;
es << "HTTP code " << httprc;
- return mkfailure<list<R>, std::string>(es.str());
+ return mkfailure<list<R> >(str(es));
}
return mklist<R>(hcx.accum, wcx.accum);
}
@@ -224,26 +214,26 @@ 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 CURLSession& ch) {
+const failable<value> evalExpr(const value& expr, const 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;
- const failable<list<std::string>, std::string> jsreq = jsonRequest(1, car<value>(expr), cdr<value>(expr), cx);
+ const failable<list<string> > jsreq = json::jsonRequest(1, car<value>(expr), cdr<value>(expr), cx);
if (!hasContent(jsreq))
- return mkfailure<value, std::string>(reason(jsreq));
+ return mkfailure<value>(reason(jsreq));
// 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);
+ const list<string> h = mklist<string>("Content-Type: application/json-rpc");
+ const failable<list<list<string> > > res = apply<list<string> >(mklist<list<string> >(h, content(jsreq)), rcons<string>, list<string>(), url, "POST", ch);
if (!hasContent(res))
- return mkfailure<value, std::string>(reason(res));
+ return mkfailure<value>(reason(res));
// Return result
- failable<list<value>, std::string> jsres = json::readJSON(cadr<list<std::string> >(content(res)), cx);
+ failable<list<value> > jsres = json::readJSON(cadr<list<string> >(content(res)), cx);
if (!hasContent(jsres))
- return mkfailure<value, std::string>(reason(jsres));
+ return mkfailure<value>(reason(jsres));
const list<value> val = elementsToValues(content(jsres));
const value rval(cadr<value>(cadr<value>(val)));
@@ -254,72 +244,88 @@ const failable<value, std::string> evalExpr(const value& expr, const std::string
/**
* Find and return a header.
*/
-const failable<std::string, std::string> header(const std::string& prefix, const list<std::string>& h) {
+const failable<string> header(const char* prefix, const list<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 mkfailure<string>(string("Couldn't find header: ") + prefix);
+ const string s = car(h);
+ if (find(s, 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"));
+ const string l(substr(s, length(prefix)));
+ return substr(l, 0, find_first_of(l, "\r\n"));
}
/**
* Find and return a location header.
*/
-const failable<std::string, std::string> location(const list<std::string>& h) {
+const failable<string> location(const list<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) {
+const failable<value> entryId(const failable<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));
+ return mkfailure<value>(reason(l));
+ const string ls(content(l));
+ return value(string(substr(ls, find_last(ls, '/') + 1)));
}
/**
* Find and return a content-type header.
*/
-const failable<std::string, std::string> contentType(const list<std::string>& h) {
+const failable<string> contentType(const list<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(const std::string&, const R)>& reduce, const R& initial, const std::string& url, const CURLSession& ch) {
+template<typename R> const failable<list<R> > get(const lambda<R(const string&, const R)>& reduce, const R& initial, const string& url, const CURLSession& ch) {
debug(url, "http::get::url");
- const list<list<std::string> > req = mklist(list<std::string>(), list<std::string>());
+ const list<list<string> > req = mklist(list<string>(), list<string>());
return apply(req, reduce, initial, url, "GET", ch);
}
/**
* 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 CURLSession& ch) {
+const failable<value> getcontent(const string& url, const CURLSession& ch) {
+ debug(url, "http::get::url");
+
+ // Get the contents of the resource at the given URL
+ const failable<list<list<string> > > res = get<list<string>>(rcons<string>, list<string>(), url, ch);
+ if (!hasContent(res))
+ return mkfailure<value>(reason(res));
+ const list<string> ls(reverse(cadr(content(res))));
+
+ // Return the content as a list of values
+ const value val(mkvalues(ls));
+ debug(val, "http::get::result");
+ return val;
+}
+
+/**
+ * HTTP GET, return a list of values representing the resource at the given URL.
+ */
+const failable<value> get(const 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);
+ const failable<list<list<string> > > res = get<list<string> >(rcons<string>, list<string>(), url, ch);
if (!hasContent(res))
- return mkfailure<value, std::string>(reason(res));
- const list<std::string> ls(reverse(cadr(content(res))));
+ return mkfailure<value>(reason(res));
+ const list<string> ls(reverse(cadr(content(res))));
- const std::string ct(content(contentType(car(content(res)))));
+ const 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(ls, os);
- const value val(os.str());
+ // Return the content as a list of values
+ const value val(mkvalues(ls));
debug(val, "http::get::result");
return val;
}
@@ -327,24 +333,24 @@ const failable<value, std::string> get(const std::string& url, const CURLSession
/**
* HTTP POST.
*/
-const failable<value, std::string> post(const value& val, const std::string& url, const CURLSession& ch) {
+const failable<value> post(const value& val, const string& url, const CURLSession& ch) {
// Convert value to an ATOM entry
- const failable<list<std::string>, std::string> entry = atom::writeATOMEntry(atom::entryValuesToElements(val));
+ const failable<list<string> > entry = atom::writeATOMEntry(atom::entryValuesToElements(val));
if (!hasContent(entry))
- return mkfailure<value, std::string>(reason(entry));
+ return mkfailure<value>(reason(entry));
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");
- const list<list<std::string> > req = mklist<list<std::string> >(h, content(entry));
- const failable<list<list<std::string> >, std::string> res = apply<list<std::string> >(req, rcons<std::string>, list<std::string>(), url, "POST", ch);
+ const list<string> h = mklist<string>("Content-Type: application/atom+xml");
+ const list<list<string> > req = mklist<list<string> >(h, content(entry));
+ const failable<list<list<string> > > res = apply<list<string>>(req, rcons<string>, list<string>(), url, "POST", ch);
if (!hasContent(res))
- return mkfailure<value, std::string>(reason(res));
+ return mkfailure<value>(reason(res));
// Return the new entry id from the HTTP location header
- const failable<value, std::string> eid(entryId(location(car(content(res)))));
+ const failable<value> eid(entryId(location(car(content(res)))));
debug(eid, "http::post::result");
return eid;
}
@@ -352,21 +358,21 @@ const failable<value, std::string> post(const value& val, const std::string& url
/**
* HTTP PUT.
*/
-const failable<value, std::string> put(const value& val, const std::string& url, const CURLSession& ch) {
+const failable<value> put(const value& val, const string& url, const CURLSession& ch) {
// Convert value to an ATOM entry
- const failable<list<std::string>, std::string> entry = atom::writeATOMEntry(atom::entryValuesToElements(val));
+ const failable<list<string> > entry = atom::writeATOMEntry(atom::entryValuesToElements(val));
if (!hasContent(entry))
- return mkfailure<value, std::string>(reason(entry));
+ return mkfailure<value>(reason(entry));
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");
- const list<list<std::string> > req = mklist<list<std::string> >(h, content(entry));
- const failable<list<list<std::string> >, std::string> res = apply<list<std::string> >(req, rcons<std::string>, list<std::string>(), url, "PUT", ch);
+ const list<string> h = mklist<string>("Content-Type: application/atom+xml");
+ const list<list<string> > req = mklist<list<string> >(h, content(entry));
+ const failable<list<list<string> > > res = apply<list<string> >(req, rcons<string>, list<string>(), url, "PUT", ch);
if (!hasContent(res))
- return mkfailure<value, std::string>(reason(res));
+ return mkfailure<value>(reason(res));
debug(true, "http::put::result");
return value(true);
@@ -375,13 +381,13 @@ const failable<value, std::string> put(const value& val, const std::string& url,
/**
* HTTP DELETE.
*/
-const failable<value, std::string> del(const std::string& url, const CURLSession& ch) {
+const failable<value, string> del(const 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);
+ const list<list<string> > req = mklist(list<string>(), list<string>());
+ const failable<list<list<string> > > res = apply<list<string> >(req, rcons<string>, list<string>(), url, "DELETE", ch);
if (!hasContent(res))
- return mkfailure<value, std::string>(reason(res));
+ return mkfailure<value>(reason(res));
debug(true, "http::delete::result");
return value(true);
@@ -391,18 +397,18 @@ const failable<value, std::string> del(const std::string& url, const CURLSession
* HTTP client proxy function.
*/
struct proxy {
- proxy(const std::string& url) : url(url) {
+ proxy(const string& url) : url(url) {
}
const value operator()(const list<value>& args) const {
CURLSession cs;
- failable<value, std::string> val = evalExpr(args, url, cs);
+ failable<value> val = evalExpr(args, url, cs);
if (!hasContent(val))
return value();
return content(val);
}
- const std::string url;
+ const string url;
};
}