diff options
-rw-r--r-- | sca-cpp/trunk/modules/http/http.hpp | 7 | ||||
-rw-r--r-- | sca-cpp/trunk/modules/http/httpd.hpp | 75 | ||||
-rw-r--r-- | sca-cpp/trunk/modules/http/mod-ssltunnel.cpp | 4 | ||||
-rw-r--r-- | sca-cpp/trunk/modules/scdl/scdl.hpp | 36 | ||||
-rw-r--r-- | sca-cpp/trunk/modules/server/mod-cpp.hpp | 2 | ||||
-rw-r--r-- | sca-cpp/trunk/modules/server/mod-eval.hpp | 75 | ||||
-rw-r--r-- | sca-cpp/trunk/modules/server/mod-scheme.hpp | 2 | ||||
-rw-r--r-- | sca-cpp/trunk/modules/server/mod-wiring.cpp | 17 | ||||
-rw-r--r-- | sca-cpp/trunk/samples/store-cluster/domains/jane/store.composite | 4 | ||||
-rw-r--r-- | sca-cpp/trunk/samples/store-cluster/domains/joe/store.composite | 4 |
10 files changed, 186 insertions, 40 deletions
diff --git a/sca-cpp/trunk/modules/http/http.hpp b/sca-cpp/trunk/modules/http/http.hpp index b6de790028..6180518e23 100644 --- a/sca-cpp/trunk/modules/http/http.hpp +++ b/sca-cpp/trunk/modules/http/http.hpp @@ -314,9 +314,9 @@ const failable<value> evalExpr(const value& expr, const string& url, const CURLS // Parse and return JSON-RPC result const failable<value> rval = json::jsonResultValue(cadr<list<string> >(content(res)), cx); + debug(rval, "http::evalExpr::result"); if (!hasContent(rval)) return mkfailure<value>(reason(rval)); - debug(content(rval), "http::evalExpr::result"); return content(rval); } @@ -602,21 +602,22 @@ const failable<int> recv(char* c, const int l, const CURLSession& cs) { * HTTP client proxy function. */ struct proxy { - proxy(const string& uri, const string& ca, const string& cert, const string& key) : uri(uri), ca(ca), cert(cert), key(key) { + proxy(const string& uri, const string& ca, const string& cert, const string& key, const gc_pool& p) : p(p), uri(uri), ca(ca), cert(cert), key(key), cs(*(new (gc_new<CURLSession>(p)) CURLSession(ca, cert, key))) { } const value operator()(const list<value>& args) const { - CURLSession cs(ca, cert, key); failable<value> val = evalExpr(args, uri, cs); if (!hasContent(val)) return value(); return content(val); } + const gc_pool p; const string uri; const string ca; const string cert; const string key; + const CURLSession& cs; }; } diff --git a/sca-cpp/trunk/modules/http/httpd.hpp b/sca-cpp/trunk/modules/http/httpd.hpp index 3c759d770c..f1b54d79ad 100644 --- a/sca-cpp/trunk/modules/http/httpd.hpp +++ b/sca-cpp/trunk/modules/http/httpd.hpp @@ -61,7 +61,7 @@ namespace httpd { * Returns a server-scoped module configuration. */ template<typename C> void* makeServerConf(apr_pool_t *p, server_rec *s) { - return new (gc_new<C>(p)) C(s); + return new (gc_new<C>(p)) C(p, s); } template<typename C> const C& serverConf(const request_rec* r, const module* mod) { @@ -132,6 +132,13 @@ const bool isVirtualHostRequest(const server_rec* s, request_rec* r) { } /** + * Return true if a URI is absolute. + */ +const bool isAbsolute(const string& uri) { + return contains(uri, "://"); +} + +/** * Return the protocol scheme for a server. */ const string scheme(const server_rec* s, const string& def = "http") { @@ -405,6 +412,72 @@ const int internalRedirect(const string& uri, request_rec* r) { } /** + * Create an HTTPD sub request. + * Similar to httpd/server/request.c::make_sub_request + */ +const failable<request_rec*, int> internalSubRequest(const string& nr_uri, request_rec* r) { + if (ap_is_recursion_limit_exceeded(r)) + return mkfailure<request_rec*, int>(HTTP_INTERNAL_SERVER_ERROR); + + // Create a new sub pool + apr_pool_t *nrp; + apr_pool_create(&nrp, r->pool); + apr_pool_tag(nrp, "subrequest"); + + // Create a new POST request + request_rec* nr = (request_rec*)apr_pcalloc(nrp, sizeof(request_rec)); + nr->connection = r->connection; + nr->server = r->server; + nr->pool = nrp; + nr->method = "POST"; + nr->method_number = M_POST; + nr->allowed_methods = ap_make_method_list(nr->pool, 2); + ap_parse_uri(nr, apr_pstrdup(nr->pool, c_str(nr_uri))); + nr->filename = apr_pstrdup(nr->pool, c_str(string("/subreq:") + nr_uri)); + nr->request_config = ap_create_request_config(r->pool); + nr->per_dir_config = r->server->lookup_defaults; + + // Inherit some of the protocol info from the parent request + nr->the_request = r->the_request; + nr->hostname = r->hostname; + nr->request_time = r->request_time; + nr->allowed = r->allowed; + nr->status = HTTP_OK; + nr->assbackwards = r->assbackwards; + nr->header_only = r->header_only; + nr->protocol = const_cast<char*>("INCLUDED"); + nr->hostname = r->hostname; + nr->request_time = r->request_time; + nr->main = r; + nr->headers_in = apr_table_make(r->pool, 12); + nr->headers_out = apr_table_make(r->pool, 12); + nr->err_headers_out = apr_table_make(nr->pool, 5); + nr->subprocess_env = r->subprocess_env; + nr->subprocess_env = apr_table_copy(nr->pool, r->subprocess_env); + nr->notes = apr_table_make(r->pool, 5); + nr->htaccess = r->htaccess; + nr->no_cache = r->no_cache; + nr->expecting_100 = r->expecting_100; + nr->no_local_copy = r->no_local_copy; + nr->read_length = 0; + nr->vlist_validator = r->vlist_validator; + nr->user = r->user; + + // Setup input and output filters + nr->proto_output_filters = r->proto_output_filters; + nr->proto_input_filters = r->proto_input_filters; + nr->output_filters = nr->proto_output_filters; + nr->input_filters = nr->proto_input_filters; + ap_add_output_filter_handle(ap_subreq_core_filter_handle, NULL, nr, nr->connection); + + // Run create request hook + ap_run_create_request(nr); + nr->used_path_info = AP_REQ_DEFAULT_PATH_INFO; + + return nr; +} + +/** * Put a value in the process user data. */ const bool putUserData(const string& k, const void* v, const server_rec* s) { diff --git a/sca-cpp/trunk/modules/http/mod-ssltunnel.cpp b/sca-cpp/trunk/modules/http/mod-ssltunnel.cpp index 5337a4cac2..0d4fe3045f 100644 --- a/sca-cpp/trunk/modules/http/mod-ssltunnel.cpp +++ b/sca-cpp/trunk/modules/http/mod-ssltunnel.cpp @@ -47,8 +47,10 @@ namespace modssltunnel { */ class ServerConf { public: - ServerConf(server_rec* s) : server(s) { + ServerConf(apr_pool_t* p, server_rec* s) : p(p), server(s) { } + + const gc_pool p; server_rec* server; string pass; string host; diff --git a/sca-cpp/trunk/modules/scdl/scdl.hpp b/sca-cpp/trunk/modules/scdl/scdl.hpp index 531144e219..0f008dc3a8 100644 --- a/sca-cpp/trunk/modules/scdl/scdl.hpp +++ b/sca-cpp/trunk/modules/scdl/scdl.hpp @@ -117,10 +117,33 @@ const list<value> references(const value& l) { } /** + * Returns a list of bindings in a service or reference. + */ +const bool filterBinding(const value& v) { + return isElement(v) && contains(string(cadr<value>(v)), "binding."); +} + +const list<value> bindings(const value& l) { + return filter<value>(filterBinding, l); +} + +/** * Returns the target of a reference. */ +const value bindingsTarget(const list<value>& l) { + if (isNil(l)) + return value(); + const value u = uri(car(l)); + if (!isNil(u)) + return u; + return bindingsTarget(cdr(l)); +} + const value target(const value& l) { - return attributeValue("target", l); + const value target = attributeValue("target", l); + if (!isNil(target)) + return target; + return bindingsTarget(bindings(l)); } /** @@ -134,17 +157,6 @@ const list<value> referenceToTargetAssoc(const list<value>& r) { } /** - * Returns a list of bindings in a service or reference. - */ -const bool filterBinding(const value& v) { - return isElement(v) && contains(string(cadr<value>(v)), "binding."); -} - -const list<value> bindings(const value& l) { - return filter<value>(filterBinding, l); -} - -/** * Returns a list of properties in a component. */ const list<value> properties(const value& l) { diff --git a/sca-cpp/trunk/modules/server/mod-cpp.hpp b/sca-cpp/trunk/modules/server/mod-cpp.hpp index b3828dd7d2..8cae35e493 100644 --- a/sca-cpp/trunk/modules/server/mod-cpp.hpp +++ b/sca-cpp/trunk/modules/server/mod-cpp.hpp @@ -64,8 +64,10 @@ struct applyImplementation { const lib ilib; const lambda<value(const list<value>&)> impl; const list<value> px; + applyImplementation(const lib& ilib, const lambda<value(const list<value>&)>& impl, const list<value>& px) : ilib(ilib), impl(impl), px(px) { } + const value operator()(const list<value>& params) const { debug(params, "modeval::cpp::applyImplementation::input"); diff --git a/sca-cpp/trunk/modules/server/mod-eval.hpp b/sca-cpp/trunk/modules/server/mod-eval.hpp index 391f5b8325..5eb9d5af72 100644 --- a/sca-cpp/trunk/modules/server/mod-eval.hpp +++ b/sca-cpp/trunk/modules/server/mod-eval.hpp @@ -53,9 +53,10 @@ namespace modeval { */ class ServerConf { public: - ServerConf(server_rec* s) : server(s), wiringServerName(""), contributionPath(""), compositeName(""), virtualHostContributionPath(""), virtualHostCompositeName(""), ca(""), cert(""), key("") { + ServerConf(apr_pool_t* p, server_rec* s) : p(p), server(s), wiringServerName(""), contributionPath(""), compositeName(""), virtualHostContributionPath(""), virtualHostCompositeName(""), ca(""), cert(""), key("") { } + const gc_pool p; server_rec* server; lambda<value(const list<value>&)> lifecycle; string wiringServerName; @@ -259,16 +260,68 @@ int translate(request_rec *r) { } /** - * Convert a list of component references to a list of HTTP proxy lambdas. + * Make an HTTP proxy lambda. */ -const value mkrefProxy(const value& ref, const string& base, const string& ca, const string& cert, const string& key) { - return lambda<value(const list<value>&)>(http::proxy(base + string(scdl::name(ref)), ca, cert, key)); +const value mkhttpProxy(const ServerConf& sc, const string& ref, const string& base) { + const string uri = base + ref; + debug(uri, "modeval::mkhttpProxy::uri"); + return lambda<value(const list<value>&)>(http::proxy(uri, sc.ca, sc.cert, sc.key, sc.p)); } -const list<value> refProxies(const list<value>& refs, const string& base, const string& ca, const string& cert, const string& key) { +/** + * Return a component implementation proxy lambda. + */ +class implProxy { +public: + implProxy(const ServerConf& sc, const value& name) : sc(sc), name(name) { + } + + const value operator()(const list<value>& params) const { + debug(params, "modeval::implProxy::input"); + + // Lookup the component implementation + const list<value> impl(assoctree<value>(name, sc.implTree)); + if (isNil(impl)) + return mkfailure<value>(string("Couldn't find component implementation: ") + name); + + // Call its lambda function + const lambda<value(const list<value>&)> l(cadr<value>(impl)); + const value func = c_str(car(params)); + const failable<value> val = failableResult(l(cons(func, cdr(params)))); + debug(val, "modeval::implProxy::result"); + if (!hasContent(val)) + return value(); + return content(val); + } + +private: + const ServerConf& sc; + const value name; +}; + +const value mkimplProxy(const ServerConf& sc, const value& name) { + debug(name, "modeval::implProxy::impl"); + return lambda<value(const list<value>&)>(implProxy(sc, name)); +} + +/** + * Convert a list of component references to a list of proxy lambdas. + */ +const value mkrefProxy(const ServerConf& sc, const value& ref, const string& base) { + const value target = scdl::target(ref); + debug(ref, "modeval::mkrefProxy::ref"); + debug(target, "modeval::mkrefProxy::target"); + + // Use an HTTP proxy or an internal proxy to the component implementation + if (isNil(target) || httpd::isAbsolute(target)) + return mkhttpProxy(sc, scdl::name(ref), base); + return mkimplProxy(sc, car(pathValues(target))); +} + +const list<value> refProxies(const ServerConf& sc, const list<value>& refs, const string& base) { if (isNil(refs)) return refs; - return cons(mkrefProxy(car(refs), base, ca, cert, key), refProxies(cdr(refs), base, ca, cert, key)); + return cons(mkrefProxy(sc, car(refs), base), refProxies(sc, cdr(refs), base)); } /** @@ -375,11 +428,13 @@ const value evalComponent(ServerConf& sc, const value& comp) { extern const failable<lambda<value(const list<value>&)> > evalImplementation(const string& cpath, const value& impl, const list<value>& px, const lambda<value(const list<value>&)>& lifecycle); const value impl = scdl::implementation(comp); + debug(comp, "modeval::evalComponent::comp"); + debug(impl, "modeval::evalComponent::impl"); // Convert component references to configured proxy lambdas ostringstream base; base << sc.wiringServerName << "/references/" << string(scdl::name(comp)) << "/"; - const list<value> rpx(refProxies(scdl::references(comp), str(base), sc.ca, sc.cert, sc.key)); + const list<value> rpx(refProxies(sc, scdl::references(comp), str(base))); // Convert component proxies to configured proxy lambdas const list<value> ppx(propProxies(scdl::properties(comp))); @@ -486,7 +541,7 @@ const failable<bool> startComponents(ServerConf& sc) { */ class VirtualHostConf { public: - VirtualHostConf(const ServerConf& ssc) : sc(ssc.server) { + VirtualHostConf(const gc_pool& p, const ServerConf& ssc) : sc(pool(p), ssc.server) { sc.virtualHostContributionPath = ssc.virtualHostContributionPath; sc.virtualHostCompositeName = ssc.virtualHostCompositeName; sc.ca = ssc.ca; @@ -559,7 +614,7 @@ int handler(request_rec *r) { const ServerConf& sc = httpd::serverConf<ServerConf>(r, &mod_tuscany_eval); // Process dynamic virtual host configuration, if any - VirtualHostConf vhc(sc); + VirtualHostConf vhc(gc_pool(r->pool), sc); const bool usevh = hasVirtualCompositeConf(vhc.sc) && httpd::isVirtualHostRequest(sc.server, r); if (usevh) { const failable<bool> cr = virtualHostConfig(vhc.sc, r); @@ -571,7 +626,7 @@ int handler(request_rec *r) { const list<value> path(pathValues(r->uri)); const list<value> impl(assoctree<value>(cadr(path), usevh? vhc.sc.implTree : sc.implTree)); if (isNil(impl)) - return httpd::reportStatus(mkfailure<int>(string("Couldn't find component implementation"))); + return httpd::reportStatus(mkfailure<int>(string("Couldn't find component implementation: ") + cadr(path))); // Handle HTTP method const lambda<value(const list<value>&)> l(cadr<value>(impl)); diff --git a/sca-cpp/trunk/modules/server/mod-scheme.hpp b/sca-cpp/trunk/modules/server/mod-scheme.hpp index f5b9554c3f..43d7bf4041 100644 --- a/sca-cpp/trunk/modules/server/mod-scheme.hpp +++ b/sca-cpp/trunk/modules/server/mod-scheme.hpp @@ -54,8 +54,10 @@ const list<value> primitiveProcedures(const list<value>& l) { struct applyImplementation { const value impl; const list<value> px; + applyImplementation(const value& impl, const list<value>& px) : impl(impl), px(scheme::quotedParameters(primitiveProcedures(px))) { } + const value operator()(const list<value>& params) const { const value expr = cons<value>(car(params), append(scheme::quotedParameters(cdr(params)), px)); debug(expr, "modeval::scheme::applyImplementation::input"); diff --git a/sca-cpp/trunk/modules/server/mod-wiring.cpp b/sca-cpp/trunk/modules/server/mod-wiring.cpp index 17cfcaae0e..188aa620fb 100644 --- a/sca-cpp/trunk/modules/server/mod-wiring.cpp +++ b/sca-cpp/trunk/modules/server/mod-wiring.cpp @@ -53,8 +53,10 @@ const bool useModProxy = true; */ class ServerConf { public: - ServerConf(server_rec* s) : server(s), contributionPath(""), compositeName(""), virtualHostContributionPath(""), virtualHostCompositeName("") { + ServerConf(apr_pool_t* p, server_rec* s) : p(p), server(s), contributionPath(""), compositeName(""), virtualHostContributionPath(""), virtualHostCompositeName("") { } + + const gc_pool p; server_rec* server; string contributionPath; string compositeName; @@ -79,13 +81,6 @@ const bool hasVirtualCompositeConf(const ServerConf& sc) { } /** - * Returns true if a URI is absolute. - */ -const bool isAbsolute(const string& uri) { - return contains(uri, "://"); -} - -/** * Route a /references/component-name/reference-name request, * to the target of the component reference. */ @@ -107,7 +102,7 @@ int translateReference(const ServerConf& sc, request_rec *r) { debug(target, "modwiring::translateReference::target"); // Route to an absolute target URI using mod_proxy or an HTTP client redirect - if (isAbsolute(target)) { + if (httpd::isAbsolute(target)) { if (useModProxy) { // Build proxy URI using current request's protocol scheme r->filename = apr_pstrdup(r->pool, c_str(string("proxy:") + httpd::scheme(r) + substr(target, find(target, "://")))); @@ -270,7 +265,7 @@ const bool confComponents(ServerConf& sc) { */ class VirtualHostConf { public: - VirtualHostConf(const ServerConf& ssc) : sc(ssc.server) { + VirtualHostConf(const gc_pool& p, const ServerConf& ssc) : sc(pool(p), ssc.server) { sc.virtualHostContributionPath = ssc.virtualHostContributionPath; sc.virtualHostCompositeName = ssc.virtualHostCompositeName; } @@ -316,7 +311,7 @@ int translate(request_rec *r) { const ServerConf& sc = httpd::serverConf<ServerConf>(r, &mod_tuscany_wiring); // Process dynamic virtual host configuration - VirtualHostConf vhc(sc); + VirtualHostConf vhc(gc_pool(r->pool), sc); const bool usevh = hasVirtualCompositeConf(vhc.sc) && httpd::isVirtualHostRequest(sc.server, r); if (usevh) { const failable<bool> cr = virtualHostConfig(vhc.sc, r); diff --git a/sca-cpp/trunk/samples/store-cluster/domains/jane/store.composite b/sca-cpp/trunk/samples/store-cluster/domains/jane/store.composite index eeb5387588..be67d20955 100644 --- a/sca-cpp/trunk/samples/store-cluster/domains/jane/store.composite +++ b/sca-cpp/trunk/samples/store-cluster/domains/jane/store.composite @@ -51,7 +51,9 @@ <service name="Total"> <t:binding.jsonrpc uri="total"/> </service> - <reference name="cache" target="http://sca-store.com/cache"/> + <reference name="cache"> + <t:binding.jsonrpc uri="http://sca-store.com/cache"/> + </reference> </component> <component name="CurrencyConverter"> diff --git a/sca-cpp/trunk/samples/store-cluster/domains/joe/store.composite b/sca-cpp/trunk/samples/store-cluster/domains/joe/store.composite index eeb5387588..be67d20955 100644 --- a/sca-cpp/trunk/samples/store-cluster/domains/joe/store.composite +++ b/sca-cpp/trunk/samples/store-cluster/domains/joe/store.composite @@ -51,7 +51,9 @@ <service name="Total"> <t:binding.jsonrpc uri="total"/> </service> - <reference name="cache" target="http://sca-store.com/cache"/> + <reference name="cache"> + <t:binding.jsonrpc uri="http://sca-store.com/cache"/> + </reference> </component> <component name="CurrencyConverter"> |