summaryrefslogtreecommitdiffstats
path: root/cpp/sca/modules/http/curl.hpp
diff options
context:
space:
mode:
authorjsdelfino <jsdelfino@13f79535-47bb-0310-9956-ffa450edef68>2009-11-16 06:57:41 +0000
committerjsdelfino <jsdelfino@13f79535-47bb-0310-9956-ffa450edef68>2009-11-16 06:57:41 +0000
commitbd0fdbf902f8ca8e7e352582efe938e1d6743dd1 (patch)
tree4ffc871e04f7e22cad2a6ed1d921718e296dc5fe /cpp/sca/modules/http/curl.hpp
parent2cd577564c1e4a37b25f4064b84af15d112b0654 (diff)
Cleaning up SVN structure, moving sca trunk to sca-cpp/trunk.
git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@880633 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'cpp/sca/modules/http/curl.hpp')
-rw-r--r--cpp/sca/modules/http/curl.hpp348
1 files changed, 0 insertions, 348 deletions
diff --git a/cpp/sca/modules/http/curl.hpp b/cpp/sca/modules/http/curl.hpp
deleted file mode 100644
index 5ee3a090b0..0000000000
--- a/cpp/sca/modules/http/curl.hpp
+++ /dev/null
@@ -1,348 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-/* $Rev$ $Date$ */
-
-#ifndef tuscany_curl_hpp
-#define tuscany_curl_hpp
-
-/**
- * CURL HTTP client functions.
- */
-
-#include <curl/curl.h>
-#include <curl/types.h>
-#include <curl/easy.h>
-#include <string>
-#include "list.hpp"
-#include "value.hpp"
-#include "element.hpp"
-#include "monad.hpp"
-#include "../atom/atom.hpp"
-#include "../json/json.hpp"
-
-namespace tuscany {
-namespace http {
-
-/**
- * Set to true to log HTTP content.
- */
-bool logContent = false;
-
-/**
- * CURL library context, one per process.
- */
-class CURLContext {
-public:
- CURLContext() {
- curl_global_init(CURL_GLOBAL_ALL);
- }
- ~CURLContext() {
- curl_global_cleanup();
- }
-};
-
-CURLContext curlContext;
-
-/**
- * Represents a CURL session handle.
- */
-class CURLHandle {
-public:
- CURLHandle() : h(curl_easy_init()) {
- }
- ~CURLHandle() {
- curl_easy_cleanup(h);
- }
-
- operator CURL*() const {
- return h;
- }
-private:
- CURL* h;
-};
-
-/**
- * Context passed to the read callback function.
- */
-class CURLReadContext {
-public:
- CURLReadContext(const list<std::string>& ilist) : ilist(ilist) {
- }
- list<std::string> ilist;
-};
-
-/**
- * Called by CURL to read data to send.
- */
-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();
-}
-
-/**
- * Context passed to CURL write callback function.
- */
-template<typename R> class CURLWriteContext {
-public:
- CURLWriteContext(const lambda<R(std::string, R)>& reduce, const R& accum) : reduce(reduce), accum(accum) {
- }
- const lambda<R(std::string, R)> reduce;
- R accum;
-};
-
-/**
- * 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;
-}
-
-/**
- * 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) {
- if (isNil(h))
- return cl;
- 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) {
-
- // Init the curl session
- curl_easy_reset(ch);
- 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();
- if (sz < 1400)
- curl_easy_setopt(ch, CURLOPT_TCP_NODELAY, true);
-
- // 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_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_WRITEDATA, &wcx);
-
- // Set the request headers
- curl_slist* hl = headers(NULL, car(req));
- if (hl != NULL)
- curl_easy_setopt(ch, CURLOPT_HTTPHEADER, hl);
-
- // Apply the HTTP verb
- curl_easy_setopt(ch, CURLOPT_URL, url.c_str());
- if (verb == "POST") {
- curl_easy_setopt(ch, CURLOPT_POST, true);
- curl_easy_setopt(ch, CURLOPT_POSTFIELDSIZE, sz);
- } else if (verb == "PUT") {
- curl_easy_setopt(ch, CURLOPT_UPLOAD, true);
- curl_easy_setopt(ch, CURLOPT_INFILESIZE, sz);
- } else if (verb == "DELETE")
- curl_easy_setopt(ch, CURLOPT_CUSTOMREQUEST, "DELETE");
- const CURLcode rc = curl_easy_perform(ch);
-
- if (hl != NULL)
- curl_slist_free_all(hl);
-
- // Return the HTTP return code or content
- if (rc)
- return mkfailure<list<R>, std::string>(curl_easy_strerror(rc));
- long httprc;
- curl_easy_getinfo (ch, CURLINFO_RESPONSE_CODE, &httprc);
- if (httprc != 200 && httprc != 201) {
- std::ostringstream es;
- es << "HTTP code " << httprc;
- return mkfailure<list<R>, std::string>(es.str());
- }
- return mklist<R>(hcx.accum, wcx.accum);
-}
-
-/**
- * Evaluate an expression remotely, at the given URL.
- */
-const failable<value, std::string> evalExpr(const value& expr, const std::string& url, const CURLHandle& ch) {
-
- // 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);
- if (!hasValue(jsreq))
- return mkfailure<value, std::string>(reason(jsreq));
-
- if (logContent) {
- std::cout<< "content: " << std::endl;
- write(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, jsreq), rcons<std::string>, list<std::string>(), url, "POST", ch);
- if (!hasValue(res))
- return mkfailure<value, std::string>(reason(res));
-
- // Return result
- if (logContent) {
- std::cout << "content:" << std::endl;
- write(cadr<list<std::string> >(res), std::cout);
- std::cout << std::endl;
- }
- const list<value> val = elementsToValues(json::readJSON(cadr<list<std::string> >(res), cx));
- return cadr<value>(cadr<value>(val));
-}
-
-/**
- * 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) {
- const list<list<std::string> > req = mklist(list<std::string>(), list<std::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 CURLHandle& ch) {
-
- // 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 (!hasValue(res))
- return mkfailure<value, std::string>(reason(res));
- const list<list<std::string> > ls = res;
-
- const std::string ct;
- if (ct.find("application/atom+xml") != std::string::npos) {
- // TODO Return an ATOM feed
- }
-
- // Return the content as a string value
- std::ostringstream os;
- write(reverse(cadr(ls)), os);
- return value(os.str());
-}
-
-/**
- * HTTP POST.
- */
-const failable<value, std::string> post(const value& val, const std::string& url, const CURLHandle& ch) {
-
- // Convert value to an ATOM entry
- const failable<list<std::string>, std::string> entry = atom::writeATOMEntry(atom::entryValuesToElements(val));
- if (!hasValue(entry))
- return mkfailure<value, std::string>(reason(entry));
- if (logContent) {
- std::cout << "content:" << std::endl;
- write(list<std::string>(entry), std::cout);
- std::cout << std::endl;
- }
-
- // 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, entry);
- const failable<list<list<std::string> >, std::string> res = apply<list<std::string> >(req, rcons<std::string>, list<std::string>(), url, "POST", ch);
- if (!hasValue(res))
- return mkfailure<value, std::string>(reason(res));
- return value(true);
-}
-
-/**
- * HTTP PUT.
- */
-const failable<value, std::string> put(const value& val, const std::string& url, const CURLHandle& ch) {
-
- // Convert value to an ATOM entry
- const failable<list<std::string>, std::string> entry = atom::writeATOMEntry(atom::entryValuesToElements(val));
- if (!hasValue(entry))
- return mkfailure<value, std::string>(reason(entry));
- if (logContent) {
- std::cout << "content:" << std::endl;
- write(list<std::string>(entry), std::cout);
- std::cout << std::endl;
- }
-
- // 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, entry);
- const failable<list<list<std::string> >, std::string> res = apply<list<std::string> >(req, rcons<std::string>, list<std::string>(), url, "PUT", ch);
- if (!hasValue(res))
- return mkfailure<value, std::string>(reason(res));
- return value(true);
-}
-
-/**
- * HTTP DELETE.
- */
-const failable<value, std::string> del(const std::string& url, const CURLHandle& ch) {
- 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 (!hasValue(res))
- return mkfailure<value, std::string>(reason(res));
- return value(true);
-}
-
-/**
- * HTTP client proxy function.
- */
-struct proxy {
- proxy(const std::string& url, const CURLHandle& ch) : url(url), ch(ch) {
- }
-
- const value operator()(const list<value>& args) const {
- failable<value, std::string> val = evalExpr(args, url, ch);
- if (!hasValue(val))
- return value();
- return val;
- }
-
- const std::string url;
- const CURLHandle& ch;
-};
-
-}
-}
-
-#endif /* tuscany_curl_hpp */