diff options
author | jsdelfino <jsdelfino@13f79535-47bb-0310-9956-ffa450edef68> | 2012-02-20 07:20:22 +0000 |
---|---|---|
committer | jsdelfino <jsdelfino@13f79535-47bb-0310-9956-ffa450edef68> | 2012-02-20 07:20:22 +0000 |
commit | 4f245967cb241021844b678e75ff48c6783113d3 (patch) | |
tree | 3375eb90f619656950d07a14090abf9d3e381707 /sca-cpp | |
parent | 8fdc6a6dc4b2b23b923d8cbfba5190933155e95d (diff) |
Optimize server modules a bit. Pass individual config elements instead of the whole server config. Load target composite once into the request. Enable loading of shared component implementations from the main contribution.
git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@1291134 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'sca-cpp')
-rw-r--r-- | sca-cpp/trunk/components/webservice/webservice-listener.cpp | 4 | ||||
-rwxr-xr-x | sca-cpp/trunk/hosting/server/ssl-start | 17 | ||||
-rwxr-xr-x | sca-cpp/trunk/hosting/server/start | 27 | ||||
-rw-r--r-- | sca-cpp/trunk/kernel/element.hpp | 2 | ||||
-rw-r--r-- | sca-cpp/trunk/modules/http/httpd.hpp | 27 | ||||
-rw-r--r-- | sca-cpp/trunk/modules/http/mod-ssltunnel.cpp | 4 | ||||
-rw-r--r-- | sca-cpp/trunk/modules/oauth/mod-oauth1.cpp | 18 | ||||
-rw-r--r-- | sca-cpp/trunk/modules/oauth/mod-oauth2.cpp | 18 | ||||
-rw-r--r-- | sca-cpp/trunk/modules/server/mod-eval.hpp | 757 |
9 files changed, 441 insertions, 433 deletions
diff --git a/sca-cpp/trunk/components/webservice/webservice-listener.cpp b/sca-cpp/trunk/components/webservice/webservice-listener.cpp index 78a0ea9580..3741f7a1a7 100644 --- a/sca-cpp/trunk/components/webservice/webservice-listener.cpp +++ b/sca-cpp/trunk/components/webservice/webservice-listener.cpp @@ -67,9 +67,7 @@ const failable<value> handle(const list<value>& params) { cout << "relay: " << &relay << endl; // Redirect HTTPD request to Mod-axis2 - if (r->args == NULL) - return redirectToAxis2(httpd::redirectURI("/axis2", string(r->uri)), r, relay); - return redirectToAxis2(httpd::redirectURI("/axis2", string(r->uri), string(r->args)), r, relay); + return redirectToAxis2(string("/axis2") + r->uri + r->args != NULL? string("?") + r->args : string(""), r, relay); } } diff --git a/sca-cpp/trunk/hosting/server/ssl-start b/sca-cpp/trunk/hosting/server/ssl-start index 9be614fa8e..4689566176 100755 --- a/sca-cpp/trunk/hosting/server/ssl-start +++ b/sca-cpp/trunk/hosting/server/ssl-start @@ -80,7 +80,6 @@ fi if [ -x ../../components/log/scribe-cat ]; then cat >tmp/conf/log.conf <<EOF # Generated by: ssl-start $* -LogLevel notice ErrorLog "|$here/../../components/log/scribe-cat server" CustomLog "|$here/../../components/log/scribe-cat server" combined @@ -101,7 +100,6 @@ EOF else cat >tmp/conf/log.conf <<EOF # Generated by: ssl=start $* -LogLevel debug ErrorLog $here/tmp/logs/error_log CustomLog $here/tmp/logs/access_log combined @@ -137,6 +135,7 @@ cat >>tmp/conf/svhost-ssl.conf <<EOF # Error pages ErrorDocument 404 /public/notfound/ ErrorDocument 401 /public/notauth/ +ErrorDocument 403 /public/notauth/ ErrorDocument 500 /public/oops/ ErrorDocument 405 /public/oops/ @@ -150,8 +149,9 @@ SCAContribution $here/ SCAComposite server.composite # Configure SCA Composite for mass dynamic virtual Hosting -SCAVirtualContribution $here/apps/ -SCAVirtualComposite app.composite +#SCAVirtualContribution $here/data/apps/ +#SCAVirtualComposite app.composite +SCAVirtualContributor Composites EOF @@ -163,8 +163,13 @@ Alias /home/home.b64 $here/htdocs/home/home.b64 EOF -# Create app resource links -./mkapplinks data ../../../../.. ../../../../../../nuvem +# Create app implementation resource links +if [ ! -e "nuvem" ]; then + ln -s "../../../nuvem/nuvem-parallel/nuvem" "nuvem" +fi +if [ ! -e "lib" ]; then + ln -s "../../components" "lib" +fi # Configure app resource aliases cat >>tmp/conf/svhost-ssl.conf <<EOF diff --git a/sca-cpp/trunk/hosting/server/start b/sca-cpp/trunk/hosting/server/start index da0dcecf40..a74581aa59 100755 --- a/sca-cpp/trunk/hosting/server/start +++ b/sca-cpp/trunk/hosting/server/start @@ -53,12 +53,6 @@ CustomLog "|$here/../../components/log/scribe-cat server" combined EOF - cat >tmp/conf/log-ssl.conf <<EOF -# Generated by: start $* -CustomLog "|$here/../../components/log/scribe-cat server" sslcombined - -EOF - else cat >tmp/conf/log.conf <<EOF # Generated by: start $* @@ -68,12 +62,6 @@ CustomLog $here/tmp/logs/access_log combined EOF - cat >tmp/conf/log-ssl.conf <<EOF -# Generated by: start $* -CustomLog $here/tmp/logs/ssl_access_log sslcombined - -EOF - fi # Configure error pages @@ -82,6 +70,7 @@ cat >>tmp/conf/svhost.conf <<EOF # Error pages ErrorDocument 404 /public/notfound/ ErrorDocument 401 /public/notauth/ +ErrorDocument 403 /public/notauth/ ErrorDocument 500 /public/oops/ ErrorDocument 405 /public/oops/ @@ -95,8 +84,9 @@ SCAContribution $here/ SCAComposite server.composite # Configure SCA Composite for mass dynamic virtual Hosting -SCAVirtualContribution $here/data/apps/ -SCAVirtualComposite app.composite +#SCAVirtualContribution $here/data/apps/ +#SCAVirtualComposite app.composite +SCAVirtualContributor Composites EOF @@ -108,8 +98,13 @@ Alias /home/home.b64 $here/htdocs/home/home.b64 EOF -# Create app resource links -./mkapplinks data ../../../../.. ../../../../../../nuvem +# Create app implementation resource links +if [ ! -e "nuvem" ]; then + ln -s "../../../nuvem/nuvem-parallel/nuvem" "nuvem" +fi +if [ ! -e "lib" ]; then + ln -s "../../components" "lib" +fi # Configure app resource aliases cat >>tmp/conf/svhost.conf <<EOF diff --git a/sca-cpp/trunk/kernel/element.hpp b/sca-cpp/trunk/kernel/element.hpp index fb21aa60ad..c69d3bbf07 100644 --- a/sca-cpp/trunk/kernel/element.hpp +++ b/sca-cpp/trunk/kernel/element.hpp @@ -200,7 +200,7 @@ const value valueToElement(const value& t) { // Convert a single value to an attribute or an element if (!isList(v)) { if (substr(n, 0, 1) == atsign) - return mklist<value>(attribute, substr(n, 1), v); + return mklist<value>(attribute, c_str(substr(n, 1)), v); return mklist(element, n, v); } diff --git a/sca-cpp/trunk/modules/http/httpd.hpp b/sca-cpp/trunk/modules/http/httpd.hpp index 7c839c1306..af075a04e8 100644 --- a/sca-cpp/trunk/modules/http/httpd.hpp +++ b/sca-cpp/trunk/modules/http/httpd.hpp @@ -120,6 +120,22 @@ template<typename C> C& dirConf(const void* c) { } /** + * Returns a request-scoped module configuration. + */ +template<typename C> C& makeRequestConf(const request_rec* r, const module* mod) { + C* c = new (gc_new<C>(r->pool)) C(r->pool, r); + ap_set_module_config(r->request_config, mod, c); + return *c; +} + +template<typename C> C& requestConf(const request_rec* r, const module* mod) { + C* c = (C*)ap_get_module_config(r->request_config, mod); + if (c == NULL) + return makeRequestConf<C>(r, mod); + return *c; +} + +/** * Return the host name for a server. */ const string hostName(const server_rec* s, const string& def = "localhost") { @@ -425,17 +441,6 @@ const int reportStatus(const failable<int>& rc) { } /** - * Construct a redirect URI. - */ -const string redirectURI(const string& file, const string& pi) { - return file + pi; -} - -const string redirectURI(const string& file, const string& pi, const string& args) { - return file + pi + "?" + args; -} - -/** * Convert a value to an HTTPD request struc */ request_rec* request(const value& v) { diff --git a/sca-cpp/trunk/modules/http/mod-ssltunnel.cpp b/sca-cpp/trunk/modules/http/mod-ssltunnel.cpp index 49ce6bbe52..f6a239efe1 100644 --- a/sca-cpp/trunk/modules/http/mod-ssltunnel.cpp +++ b/sca-cpp/trunk/modules/http/mod-ssltunnel.cpp @@ -78,7 +78,7 @@ int postConfigMerge(ServerConf& mainsc, apr_pool_t* p, server_rec* s) { if (s == NULL) return OK; ServerConf& sc = httpd::serverConf<ServerConf>(s, &mod_tuscany_ssltunnel); - debug(httpd::serverName(s), "modwiring::postConfigMerge::serverName"); + debug(httpd::serverName(s), "modssltunnel::postConfigMerge::serverName"); // Merge configuration from main server if (length(sc.ca) == 0 && length(mainsc.ca) !=0) @@ -105,7 +105,7 @@ int postConfigMerge(ServerConf& mainsc, apr_pool_t* p, server_rec* s) { int postConfig(apr_pool_t* p, unused apr_pool_t* plog, unused apr_pool_t* ptemp, server_rec* s) { gc_scoped_pool pool(p); ServerConf& sc = httpd::serverConf<ServerConf>(s, &mod_tuscany_ssltunnel); - debug(httpd::serverName(s), "modwiring::postConfig::serverName"); + debug(httpd::serverName(s), "modssltunnel::postConfig::serverName"); // Register the SSLTUNNEL method M_SSLTUNNEL = ap_method_register(p, "SSLTUNNEL"); diff --git a/sca-cpp/trunk/modules/oauth/mod-oauth1.cpp b/sca-cpp/trunk/modules/oauth/mod-oauth1.cpp index 833dfc96c5..1276ea4855 100644 --- a/sca-cpp/trunk/modules/oauth/mod-oauth1.cpp +++ b/sca-cpp/trunk/modules/oauth/mod-oauth1.cpp @@ -172,7 +172,7 @@ const list<string> sign(const string& verb, const string& uri, const list<value> /** * Handle an authorize request. */ -const failable<int> authorize(const list<list<value> >& args, request_rec* r, const ServerConf& sc) { +const failable<int> authorize(const list<list<value> >& args, request_rec* r, const list<list<value> >& appkeys, const memcache::MemCached& mc) { // Extract authorize, access_token, client ID and info URIs const list<value> req = assoc<value>("mod_oauth1_request_token", args); if (isNil(req) || isNil(cdr(req))) @@ -196,7 +196,7 @@ const failable<int> authorize(const list<list<value> >& args, request_rec* r, co debug(redir, "modoauth1::authorize::redir"); // Lookup client app configuration - const list<value> app = assoc<value>(cadr(cid), sc.appkeys); + const list<value> app = assoc<value>(cadr(cid), appkeys); if (isNil(app) || isNil(cdr(app))) return mkfailure<int>(string("client id not found: ") + cadr(cid)); list<value> appkey = cadr(app); @@ -230,7 +230,7 @@ const failable<int> authorize(const list<list<value> >& args, request_rec* r, co return mkfailure<int>("Couldn't retrieve oauth_token_secret"); // Store the request token in memcached - const failable<bool> prc = memcache::put(mklist<value>("tuscanyOAuth1Token", cadr(tv)), cadr(sv), sc.mc); + const failable<bool> prc = memcache::put(mklist<value>("tuscanyOAuth1Token", cadr(tv)), cadr(sv), mc); if (!hasContent(prc)) return mkfailure<int>(reason(prc)); @@ -294,7 +294,7 @@ const failable<list<value> > profileUserInfo(const value& cid, const string& inf /** * Handle an access_token request. */ -const failable<int> access_token(const list<list<value> >& args, request_rec* r, const ServerConf& sc) { +const failable<int> accessToken(const list<list<value> >& args, request_rec* r, const list<list<value> >& appkeys, const memcache::MemCached& mc) { // Extract access_token URI, client ID and verification code const list<value> tok = assoc<value>("mod_oauth1_access_token", args); if (isNil(tok) || isNil(cdr(tok))) @@ -313,13 +313,13 @@ const failable<int> access_token(const list<list<value> >& args, request_rec* r, return mkfailure<int>("Missing oauth_verifier parameter"); // Lookup client app configuration - const list<value> app = assoc<value>(cadr(cid), sc.appkeys); + const list<value> app = assoc<value>(cadr(cid), appkeys); if (isNil(app) || isNil(cdr(app))) return mkfailure<int>(string("client id not found: ") + cadr(cid)); list<value> appkey = cadr(app); // Retrieve the request token from memcached - const failable<value> sv = memcache::get(mklist<value>("tuscanyOAuth1Token", cadr(tv)), sc.mc); + const failable<value> sv = memcache::get(mklist<value>("tuscanyOAuth1Token", cadr(tv)), mc); if (!hasContent(sv)) return mkfailure<int>(reason(sv)); @@ -372,7 +372,7 @@ const failable<int> access_token(const list<list<value> >& args, request_rec* r, // Store user info in memcached keyed by session ID const value sid = string("OAuth1_") + mkrand(); - const failable<bool> prc = memcache::put(mklist<value>("tuscanyOpenAuth", sid), content(iv), sc.mc); + const failable<bool> prc = memcache::put(mklist<value>("tuscanyOpenAuth", sid), content(iv), mc); if (!hasContent(prc)) return mkfailure<int>(reason(prc)); @@ -433,13 +433,13 @@ static int checkAuthn(request_rec *r) { // Handle OAuth authorize request step if (step == "authorize") { r->ap_auth_type = const_cast<char*>(atype); - return httpd::reportStatus(authorize(args, r, sc)); + return httpd::reportStatus(authorize(args, r, sc.appkeys, sc.mc)); } // Handle OAuth access_token request step if (step == "access_token") { r->ap_auth_type = const_cast<char*>(atype); - return httpd::reportStatus(access_token(args, r, sc)); + return httpd::reportStatus(accessToken(args, r, sc.appkeys, sc.mc)); } // Redirect to the login page diff --git a/sca-cpp/trunk/modules/oauth/mod-oauth2.cpp b/sca-cpp/trunk/modules/oauth/mod-oauth2.cpp index e8c27a5709..ace611d3dc 100644 --- a/sca-cpp/trunk/modules/oauth/mod-oauth2.cpp +++ b/sca-cpp/trunk/modules/oauth/mod-oauth2.cpp @@ -124,7 +124,7 @@ const failable<int> authenticated(const list<list<value> >& attrs, const list<li /** * Handle an authorize request. */ -const failable<int> authorize(const list<list<value> >& args, request_rec* r, const ServerConf& sc) { +const failable<int> authorize(const list<list<value> >& args, request_rec* r, const list<list<value> >& appkeys) { // Extract authorize, access_token, client ID and info URIs const list<value> auth = assoc<value>("mod_oauth2_authorize", args); if (isNil(auth) || isNil(cdr(auth))) @@ -146,7 +146,7 @@ const failable<int> authorize(const list<list<value> >& args, request_rec* r, co debug(redir, "modoauth2::authorize::redir"); // Lookup client app configuration - const list<value> app = assoc<value>(cadr(cid), sc.appkeys); + const list<value> app = assoc<value>(cadr(cid), appkeys); if (isNil(app) || isNil(cdr(app))) return mkfailure<int>(string("client id not found: ") + cadr(cid)); list<value> appkey = cadr(app); @@ -171,7 +171,7 @@ const failable<list<value> > profileUserInfo(const value& cid, const list<value> /** * Handle an access_token request. */ -const failable<int> access_token(const list<list<value> >& args, request_rec* r, const ServerConf& sc) { +const failable<int> accessToken(const list<list<value> >& args, request_rec* r, const list<list<value> >& appkeys, const perthread_ptr<http::CURLSession>& cs, const memcache::MemCached& mc) { // Extract access_token URI, client ID and authorization code const list<value> tok = assoc<value>("mod_oauth2_access_token", args); if (isNil(tok) || isNil(cdr(tok))) @@ -187,7 +187,7 @@ const failable<int> access_token(const list<list<value> >& args, request_rec* r, return mkfailure<int>("Missing code parameter"); // Lookup client app configuration - const list<value> app = assoc<value>(cadr(cid), sc.appkeys); + const list<value> app = assoc<value>(cadr(cid), appkeys); if (isNil(app) || isNil(cdr(app))) return mkfailure<int>(string("client id not found: ") + cadr(cid)); list<value> appkey = cadr(app); @@ -201,7 +201,7 @@ const failable<int> access_token(const list<list<value> >& args, request_rec* r, const list<list<value> > targs = mklist<list<value> >(mklist<value>("client_id", car(appkey)), mklist<value>("redirect_uri", httpd::escape(redir)), mklist<value>("client_secret", cadr(appkey)), code); const string turi = httpd::unescape(cadr(tok)) + string("?") + http::queryString(targs); debug(turi, "modoauth2::access_token::tokenuri"); - const failable<value> tr = http::get(turi, *(sc.cs)); + const failable<value> tr = http::get(turi, *(cs)); if (!hasContent(tr)) return mkfailure<int>(reason(tr)); debug(tr, "modoauth2::access_token::response"); @@ -215,7 +215,7 @@ const failable<int> access_token(const list<list<value> >& args, request_rec* r, const list<list<value> > iargs = mklist<list<value> >(tv); const string iuri = httpd::unescape(cadr(info)) + string("?") + http::queryString(iargs); debug(iuri, "modoauth2::access_token::infouri"); - const failable<value> profres = http::get(iuri, *(sc.cs)); + const failable<value> profres = http::get(iuri, *(cs)); if (!hasContent(profres)) return mkfailure<int>("Couldn't retrieve user info"); debug(content(profres), "modoauth2::access_token::info"); @@ -227,7 +227,7 @@ const failable<int> access_token(const list<list<value> >& args, request_rec* r, // Store user info in memcached keyed by session ID const value sid = string("OAuth2_") + mkrand(); - const failable<bool> prc = memcache::put(mklist<value>("tuscanyOpenAuth", sid), content(iv), sc.mc); + const failable<bool> prc = memcache::put(mklist<value>("tuscanyOpenAuth", sid), content(iv), mc); if (!hasContent(prc)) return mkfailure<int>(reason(prc)); @@ -288,13 +288,13 @@ static int checkAuthn(request_rec *r) { // Handle OAuth authorize request step if (step == "authorize") { r->ap_auth_type = const_cast<char*>(atype); - return httpd::reportStatus(authorize(args, r, sc)); + return httpd::reportStatus(authorize(args, r, sc.appkeys)); } // Handle OAuth access_token request step if (step == "access_token") { r->ap_auth_type = const_cast<char*>(atype); - return httpd::reportStatus(access_token(args, r, sc)); + return httpd::reportStatus(accessToken(args, r, sc.appkeys, sc.cs, sc.mc)); } // Redirect to the login page diff --git a/sca-cpp/trunk/modules/server/mod-eval.hpp b/sca-cpp/trunk/modules/server/mod-eval.hpp index 999a5793ad..6595c36266 100644 --- a/sca-cpp/trunk/modules/server/mod-eval.hpp +++ b/sca-cpp/trunk/modules/server/mod-eval.hpp @@ -1,6 +1,6 @@ /* * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file + * or more provider 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 @@ -52,62 +52,97 @@ namespace server { namespace modeval { /** - * Set to true to wire using mod_proxy, false to wire using HTTP client redirects. + * SSL certificate configuration. */ -const bool useModProxy = true; +class SSLConf { +public: + SSLConf() { + } + + string ca; + string cert; + string key; +}; /** - * Server configuration. + * Virtual host configuration. */ -class ServerConf { +class VhostConf { public: - ServerConf(apr_pool_t* p, server_rec* s) : p(p), server(s) { + VhostConf() { } - ServerConf(apr_pool_t* p, const ServerConf& ssc, const string& name) : p(p), server(ssc.server), lifecycle(ssc.lifecycle), vhostName(name), compositeName(ssc.vhostCompositeName), ca(ssc.ca), cert(ssc.cert), key(ssc.key), vhostContributor(ssc.vhostContributor) { - contributionPath = length(ssc.vhostContributionPath) != 0? ssc.vhostContributionPath + name + "/" : ssc.contributionPath; + string domain; + string contribPath; + string composName; + string providerName; + value provider; +}; + +/** + * Contribution configuration. + */ +class ContribConf { +public: + ContribConf() { } - const gc_pool p; - server_rec* server; - lambda<value(const list<value>&)> lifecycle; - string vhostName; - string contributionPath; - string compositeName; - string vhostDomain; - string vhostContributionPath; - string vhostCompositeName; - string vhostContributorName; - string ca; - string cert; - string key; - list<value> references; - list<value> services; - list<value> implementations; - list<value> implTree; - value vhostContributor; + string contribPath; + string composName; }; /** - * Return true if a server contains a contribution configuration. + * Composite assocs. */ -const bool hasContributionConf(const ServerConf& sc) { - return length(sc.contributionPath) != 0; -} +class Composite { +public: + Composite() { + } + + Composite(const list<value>& refs, const list<value>& svcs, const list<value>& impls) : refs(refs), svcs(svcs), impls(impls) { + } + + list<value> refs; + list<value> svcs; + list<value> impls; +}; /** - * Return true if a server contains a virtual host domain configuration. + * Server configuration. */ -const bool hasVhostDomainConf(const ServerConf& sc) { - return length(sc.vhostDomain) != 0; -} +class ServerConf { +public: + ServerConf() { + } + + ServerConf(apr_pool_t* p, const server_rec* s) : p(p), server(s) { + } + + const gc_pool p; + const server_rec* server; + lambda<value(const list<value>&)> lifecycle; + ContribConf contribc; + SSLConf sslc; + VhostConf vhostc; + Composite compos; +}; /** - * Return true if a server contains a virtual host contribution configuration. + * Request configuration. */ -const bool hasVhostContributionConf(const ServerConf& sc) { - return length(sc.vhostContributionPath) != 0 || length(sc.vhostContributorName) != 0; -} +class RequestConf { +public: + RequestConf(apr_pool_t* p, const request_rec* r) : p(p), request(r), vhost(false), valias(false) { + } + + const gc_pool p; + const request_rec* request; + bool vhost; + bool valias; + list<value> rpath; + list<value> vpath; + list<value> impls; +}; /** * Convert a result represented as a content + failure pair to a @@ -140,20 +175,11 @@ public: }; /** - * Make an HTTP proxy lambda to a component reference. - */ -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)); -} - -/** * Make an HTTP proxy lambda to an absolute URI */ -const value mkhttpProxy(const ServerConf& sc, const string& uri) { +const value mkhttpProxy(const string& uri, const gc_pool& p) { debug(uri, "modeval::mkhttpProxy::uri"); - return lambda<value(const list<value>&)>(http::proxy(uri, "", "", "", "", sc.p)); + return lambda<value(const list<value>&)>(http::proxy(uri, "", "", "", "", p)); } /** @@ -161,13 +187,14 @@ const value mkhttpProxy(const ServerConf& sc, const string& uri) { */ class implProxy { public: - implProxy(const ServerConf& sc, const value& name) : sc(sc), name(name) { + implProxy(const value& name, const list<value>& impls, const SSLConf& sslc) : name(name), impls(impls), sslc(sslc) { } const value callImpl(const value& cname, const list<value>& aparams) const { + debug(impls, "modeval::implProxy::callImpl::impls"); // Lookup the component implementation - const list<value> impl(assoctree<value>(cname, sc.implTree)); + const list<value> impl(assoctree<value>(cname, impls)); if (isNil(impl)) return mkfailure<value>(string("Couldn't find component implementation: ") + cname); @@ -202,19 +229,19 @@ public: ostringstream appuri; appuri << httpd::scheme(currentRequest) << "://" << substr(uri, 6) << "." << http::topDomain(httpd::hostName(currentRequest)) << ":" << httpd::port(currentRequest) << "/"; debug(str(appuri), "modeval::implProxy::httpproxy::appuri"); - const lambda<value(const list<value>&)> px = lambda<value(const list<value>&)>(http::proxy(str(appuri), sc.ca, sc.cert, sc.key, httpd::cookie(currentRequest), p)); + const lambda<value(const list<value>&)> px = lambda<value(const list<value>&)>(http::proxy(str(appuri), sslc.ca, sslc.cert, sslc.key, httpd::cookie(currentRequest), p)); return px(aparams); } - // Pass our certificate and the cookie from the current request + // Pass our SSL certificate and the cookie from the current request // only if the target is in the same top level domain if (http::topDomain(http::hostName(uri, p)) == http::topDomain(httpd::hostName(currentRequest))) { debug(uri, "modeval::implProxy::httpproxy::samedomain"); - const lambda<value(const list<value>&)> px = lambda<value(const list<value>&)>(http::proxy(uri, sc.ca, sc.cert, sc.key, httpd::cookie(currentRequest), p)); + const lambda<value(const list<value>&)> px = lambda<value(const list<value>&)>(http::proxy(uri, sslc.ca, sslc.cert, sslc.key, httpd::cookie(currentRequest), p)); return px(aparams); } - // No certificate or cookie on a cross domain call + // No SSL certificate or cookie on a cross domain call debug(uri, "modeval::implProxy::httpproxy::crossdomain"); const lambda<value(const list<value>&)> px = lambda<value(const list<value>&)>(http::proxy(uri, "", "", "", "", p)); return px(aparams); @@ -229,13 +256,14 @@ public: } private: - const ServerConf& sc; const value name; + const list<value>& impls; + const SSLConf& sslc; }; -const value mkimplProxy(const ServerConf& sc, const value& name) { +const value mkimplProxy(const value& name, const list<value>& impls, const SSLConf& sslc) { debug(name, "modeval::implProxy::impl"); - return lambda<value(const list<value>&)>(implProxy(sc, name)); + return lambda<value(const list<value>&)>(implProxy(name, impls, sslc)); } /** @@ -275,7 +303,7 @@ const value mkunwiredProxy(const string& ref) { /** * Convert a list of component references to a list of proxy lambdas. */ -const value mkrefProxy(const ServerConf& sc, const value& ref) { +const value mkrefProxy(const value& ref, const list<value>& impls, const SSLConf& sslc, const gc_pool& p) { const value target = scdl::target(ref); const bool wbyimpl = scdl::wiredByImpl(ref); debug(ref, "modeval::mkrefProxy::ref"); @@ -284,18 +312,18 @@ const value mkrefProxy(const ServerConf& sc, const value& ref) { // Use an HTTP proxy or an internal proxy to the component implementation if (wbyimpl) - return mkimplProxy(sc, value()); + return mkimplProxy(value(), impls, sslc); if (isNil(target)) return mkunwiredProxy(scdl::name(ref)); if (http::isAbsolute(target)) - return mkhttpProxy(sc, target); - return mkimplProxy(sc, car(pathValues(target))); + return mkhttpProxy(target, p); + return mkimplProxy(car(pathValues(target)), impls, sslc); } -const list<value> refProxies(const ServerConf& sc, const list<value>& refs) { +const list<value> refProxies(const list<value>& refs, const list<value>& impls, const SSLConf& sslc, const gc_pool& p) { if (isNil(refs)) return refs; - return cons(mkrefProxy(sc, car(refs)), refProxies(sc, cdr(refs))); + return cons(mkrefProxy(car(refs), impls, sslc, p), refProxies(cdr(refs), impls, sslc, p)); } /** @@ -328,8 +356,8 @@ struct appPropProxy { appPropProxy(const value& v) : v(v) { } const value operator()(unused const list<value>& params) const { - const char* n = apr_table_get(currentRequest->notes, "X-Request-AppName"); - const value a = n != NULL? value(string(n)) : v; + const RequestConf& reqc = httpd::requestConf<RequestConf>(currentRequest, &mod_tuscany_eval); + const value a = isNil(reqc.vpath)? v : car(reqc.vpath); debug(a, "modeval::appPropProxy::value"); return a; } @@ -339,8 +367,8 @@ struct pathPropProxy { pathPropProxy(unused const value& v) { } const value operator()(unused const list<value>& params) const { - const char* u = apr_table_get(currentRequest->notes, "X-Request-URI"); - const value v = u != NULL? pathValues(string(u)) : list<value>(); + const RequestConf& reqc = httpd::requestConf<RequestConf>(currentRequest, &mod_tuscany_eval); + const value v = reqc.rpath; debug(v, "modeval::pathPropProxy::value"); return v; } @@ -433,7 +461,7 @@ struct implementationFailure { } }; -const value evalComponent(ServerConf& sc, const value& comp) { +const value evalComponent(const string& contribPath, const value& comp, const list<value>& impls, const lambda<value(const list<value>&)> lifecycle, const SSLConf& sslc, const gc_pool& p) { 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); @@ -441,13 +469,13 @@ const value evalComponent(ServerConf& sc, const value& comp) { debug(impl, "modeval::evalComponent::impl"); // Convert component references to configured proxy lambdas - const list<value> rpx(refProxies(sc, scdl::references(comp))); + const list<value> rpx(refProxies(scdl::references(comp), impls, sslc, p)); // Convert component properties to configured proxy lambdas const list<value> ppx(propProxies(scdl::properties(comp))); // Evaluate the component implementation and convert it to an applicable lambda function - const failable<lambda<value(const list<value>&)> > cimpl(evalImplementation(sc.contributionPath, impl, append(rpx, ppx), sc.lifecycle)); + const failable<lambda<value(const list<value>&)> > cimpl(evalImplementation(contribPath, impl, append(rpx, ppx), lifecycle)); if (!hasContent(cimpl)) return lambda<value(const list<value>&)>(implementationFailure(reason(cimpl))); return content(cimpl); @@ -456,10 +484,12 @@ const value evalComponent(ServerConf& sc, const value& comp) { /** * Return a list of component-name + configured-implementation pairs. */ -const list<value> componentToImplementationAssoc(ServerConf& sc, const list<value>& c) { +const list<value> componentToImplementationAssoc(const list<value>& c, const string& contribPath, const list<value>& impls, const lambda<value(const list<value>&)> lifecycle, const SSLConf& sslc, const gc_pool& p) { if (isNil(c)) return c; - return cons<value>(mklist<value>(scdl::name(car(c)), evalComponent(sc, car(c))), componentToImplementationAssoc(sc, cdr(c))); + return cons<value>(mklist<value>(scdl::name(car(c)), + evalComponent(contribPath, car(c), impls, lifecycle, sslc, p)), + componentToImplementationAssoc(cdr(c), contribPath, impls, lifecycle, sslc, p)); } /** @@ -473,6 +503,22 @@ const failable<list<value> > readComponents(const string& path) { } /** + * Get the components returned by a provider. + */ +const failable<list<value> > getComponents(const lambda<value(const list<value>&)>& provider, const string& name) { + const failable<value> val = failableResult(provider(cons<value>("get", mklist<value>(mklist<value>(name))))); + if (!hasContent(val)) + return mkfailure<list<value> >(reason(val)); + const list<value> c = assoc<value>(value("content"), (list<list<value> >)cdr<value>(content(val))); + if (isNil(c)) + return mkfailure<list<value> >(string("Could not get composite: ") + name); + const failable<list<string> > x = writeXML(car<value>(valuesToElements(mklist<value>(mklist<value>(cadr(c)))))); + if (!hasContent(x)) + return mkfailure<list<value> >(reason(x)); + return scdl::components(readXML(content(x))); +} + +/** * Apply a list of component implementations to a start or restart lifecycle expression. * Return the functions returned by the component implementations. */ @@ -547,105 +593,56 @@ const list<value> uriToComponentAssoc(const list<value>& c) { /** * Configure the components declared in the deployed composite. */ -const failable<bool> confComponents(ServerConf& sc) { - if (!hasContributionConf(sc)) - return false; - debug(sc.contributionPath, "modeval::confComponents::contributionPath"); - debug(sc.contributionPath, "modeval::confComponents::contributorName"); - debug(sc.compositeName, "modeval::confComponents::compositeName"); - if (sc.ca != "") debug(sc.ca, "modeval::confComponents::sslCA"); - if (sc.cert != "") debug(sc.cert, "modeval::confComponents::sslCert"); - if (sc.key != "") debug(sc.key, "modeval::confComponents::sslKey"); - - // Read the components and get their services, references and implementation - // lambda functions - const failable<list<value> > comps = readComponents(scdl::resourcePath(sc.contributionPath, sc.compositeName)); - if (!hasContent(comps)) - return mkfailure<bool>(reason(comps)); - - const list<value> refs = componentReferenceToTargetAssoc(content(comps)); - debug(refs, "modeval::confComponents::references"); - sc.references = mkbtree(sort(refs)); - - const list<value> svcs = uriToComponentAssoc(content(comps)); - debug(svcs, "modeval::confComponents::services"); - sc.services = mkbtree(sort(svcs)); - - sc.implementations = componentToImplementationAssoc(sc, content(comps)); - debug(sc.implementations, "modeval::confComponents::implementations"); - return true; -} - -/** - * Start the components declared in the deployed composite. - */ -const failable<bool> startComponents(ServerConf& sc) { - - // Start the components and record the returned implementation lambda functions - debug(sc.implementations, "modeval::startComponents::start"); - const failable<list<value> > impls = applyLifecycleExpr(sc.implementations, mklist<value>("start")); - if (!hasContent(impls)) - return mkfailure<bool>(reason(impls)); - sc.implementations = content(impls); - debug(sc.implementations, "modeval::startComponents::implementations"); - return true; -} - -/** - * Configure and start the components deployed in a virtual host. - */ -const failable<bool> vhostConfig(ServerConf& sc, const ServerConf& ssc, request_rec* r) { - debug(httpd::serverName(ssc.server), "modeval::vhostConfig::serverName"); - debug(httpd::serverName(r), "modeval::vhostConfig::vhostName"); - debug(ssc.vhostContributionPath, "modeval::vhostConfig::vhostContributionPath"); - debug(sc.contributionPath, "modeval::vhostConfig::contributionPath"); - - // Configure the deployed components - const failable<bool> cr = confComponents(sc); - if (!hasContent(cr)) - return cr; - - // Store the virtual host configuration in the request config - - return true; +const failable<Composite> confComponents(const string& contribPath, const string& composName, const value& provider, const string& vhost, const list<value>& impls, const lambda<value(const list<value>&)> lifecycle, const SSLConf& sslc, const gc_pool& p) { + debug(contribPath, "modeval::confComponents::contribPath"); + debug(composName, "modeval::confComponents::composName"); + debug(provider, "modeval::confComponents::provider"); + debug(vhost, "modeval::confComponents::vhost"); + debug(impls, "modeval::confComponents::impls"); + + const failable<list<value> > fcomps = isNil(provider)? + readComponents(scdl::resourcePath(length(vhost) != 0? contribPath + vhost + "/" : contribPath, composName)) : + getComponents(provider, vhost); + if (!hasContent(fcomps)) + return mkfailure<Composite>(reason(fcomps)); + + const list<value> comps = content(fcomps); + debug(comps, "modeval::confComponents::comps"); + + const list<value> refs = mkbtree(sort(componentReferenceToTargetAssoc(comps))); + debug(flatten(refs), "modeval::confComponents::refs"); + + const list<value> svcs = mkbtree(sort(uriToComponentAssoc(comps))); + debug(flatten(svcs), "modeval::confComponents::svcs"); + + const list<value> cimpls = mkbtree(sort(componentToImplementationAssoc(comps, + isNil(provider)? length(vhost) != 0? contribPath + vhost + "/" : contribPath : contribPath, + impls, lifecycle, sslc, p))); + debug(flatten(cimpls), "modeval::confComponents::impls"); + + return Composite(refs, svcs, cimpls); } /** - * Start the components deployed in a virtual host. + * Start the components declared in a composite. */ -const failable<bool> vhostStart(ServerConf& sc, const ServerConf& ssc, request_rec* r) { - debug(httpd::serverName(ssc.server), "modeval::vhostStart::serverName"); - debug(httpd::serverName(r), "modeval::vhostStart::vhostName"); - debug(ssc.vhostContributionPath, "modeval::vhostStart::vhostContributionPath"); - debug(sc.contributionPath, "modeval::vhostStart::contributionPath"); - - // Configure the components deployed in a virtual host - const failable<bool> cr = vhostConfig(sc, ssc, r); - if (!hasContent(cr)) - return cr; - - // Start the configured components - const failable<bool> sr = startComponents(sc); - if (!hasContent(sr)) - return sr; - - // Store the implementation lambda functions (from both the virtual host and the - // main server) in a tree for fast retrieval - sc.implTree = mkbtree(sort(append(sc.implementations, ssc.implementations))); - return true; +const failable<list<value> > startComponents(const list<value>& impls) { + debug(flatten(impls), "modeval::startComponents::impls"); + const failable<list<value> > fsimpls = applyLifecycleExpr(flatten(impls), mklist<value>("start")); + if (!hasContent(fsimpls)) + return mkfailure<list<value> >(reason(fsimpls)); + + const list<value> simpls = content(fsimpls); + debug(impls, "modeval::startComponents::simpls"); + return mkbtree(sort(simpls)); } /** - * Stop a virtual host. + * Stop the components declared in a composite. */ -const failable<bool> vhostStop(const ServerConf& sc, unused const ServerConf& ssc) { - if (!hasContributionConf(sc)) - return true; - debug("modeval::vhostStop"); - - // Stop the component implementations - applyLifecycleExpr(sc.implementations, mklist<value>("stop")); - +const failable<bool> stopComponents(const list<value>& simpls) { + debug(flatten(simpls), "modeval::stopComponents::simpls"); + applyLifecycleExpr(flatten(simpls), mklist<value>("stop")); return true; } @@ -678,7 +675,7 @@ const failable<int> get(const list<value>& rpath, request_rec* r, const lambda<v } // Evaluate the GET expression - const list<value> params(append<value>(cddr(rpath), mkvalues(args))); + const list<value> params(cddr(rpath)); const failable<value> val = failableResult(impl(cons<value>("get", mklist<value>(params)))); if (!hasContent(val)) return mkfailure<int>(reason(val)); @@ -794,10 +791,10 @@ const failable<int> post(const list<value>& rpath, request_rec* r, const lambda< return rc; const list<string> ls = httpd::read(r); debug(ls, "modeval::post::input"); - const value entry = elementsToValues(content(atom::readATOMEntry(ls))); + const value aval = elementsToValues(content(atom::isATOMEntry(ls)? atom::readATOMEntry(ls) : atom::readATOMFeed(ls))); // Evaluate the POST expression - const failable<value> val = failableResult(impl(cons<value>("post", mklist<value>(cddr(rpath), entry)))); + const failable<value> val = failableResult(impl(cons<value>("post", mklist<value>(cddr(rpath), aval)))); if (!hasContent(val)) return mkfailure<int>(reason(val)); @@ -828,10 +825,10 @@ const failable<int> put(const list<value>& rpath, request_rec* r, const lambda<v return rc; const list<string> ls = httpd::read(r); debug(ls, "modeval::put::input"); - const value entry = elementsToValues(content(atom::readATOMEntry(ls))); + const value aval = elementsToValues(content(atom::isATOMEntry(ls)? atom::readATOMEntry(ls) : atom::readATOMFeed(ls))); // Evaluate the PUT expression and update the corresponding resource - const failable<value> val = failableResult(impl(cons<value>("put", mklist<value>(cddr(rpath), entry)))); + const failable<value> val = failableResult(impl(cons<value>("put", mklist<value>(cddr(rpath), aval)))); if (!hasContent(val)) return mkfailure<int>(reason(val)); if (val == value(false)) @@ -855,57 +852,83 @@ const failable<int> del(const list<value>& rpath, request_rec* r, const lambda<v } /** + * Proceed to handle a service component request. + */ +int proceedToHandler(request_rec* r, const bool valias, const list<value>& rpath, const list<value>& vpath, const list<value>& impls) { + r->handler = "mod_tuscany_eval"; + r->filename = apr_pstrdup(r->pool, c_str(string("/redirect:") + r->uri)); + + // Store the selected vhost, path and composite in the request + RequestConf& reqc = httpd::requestConf<RequestConf>(r, &mod_tuscany_eval); + reqc.valias = valias; + reqc.rpath = rpath; + reqc.vpath = vpath; + reqc.impls = impls; + return OK; +} + +/** + * Route a component request to the specified component. + */ +int translateComponent(request_rec *r, const list<value>& rpath, const list<value>& vpath, const list<value>& impls) { + debug(rpath, "modeval::translateComponent::rpath"); + debug(flatten(impls), "modeval::translateComponent::impls"); + + // Find the requested component + if (isNil(cdr(rpath))) + return HTTP_NOT_FOUND; + const list<value> impl(assoctree(cadr(rpath), impls)); + if (isNil(impl)) + return HTTP_NOT_FOUND; + debug(impl, "modeval::translateComponent::impl"); + + return proceedToHandler(r, false, rpath, vpath, impls);; +} + +/** * Route a /references/component-name/reference-name request, * to the target of the component reference. */ -int translateReference(const ServerConf& sc, request_rec *r, const list<value>& rpath, const list<value>& apath) { - httpdDebugRequest(r, "modeval::translateReference::input"); - debug(r->uri, "modeval::translateReference::uri"); - debug(apath, "modeval::translateReference::apath"); +int translateReference(request_rec *r, const list<value>& rpath, const list<value>& vpath, const list<value>& refs, const list<value>& impls) { debug(rpath, "modeval::translateReference::rpath"); + debug(flatten(refs), "modeval::translateReference::refs"); // Find the requested component if (isNil(cdr(rpath))) return HTTP_NOT_FOUND; - const list<value> comp(assoctree(cadr(rpath), sc.references)); + const list<value> comp(assoctree(cadr(rpath), refs)); if (isNil(comp)) return HTTP_NOT_FOUND; + debug(comp, "modeval::translateReference::comp"); // Find the requested reference and target configuration const list<value> ref(assoctree<value>(caddr(rpath), cadr(comp))); if (isNil(ref)) return HTTP_NOT_FOUND; + debug(ref, "modeval::translateReference::ref"); + const string target(cadr(ref)); debug(target, "modeval::translateReference::target"); // Route to an absolute target URI using mod_proxy or an HTTP client redirect const list<value> pathInfo = cdddr(rpath); if (http::isAbsolute(target)) { - if (useModProxy) { - // Build proxy URI - string turi = target + path(pathInfo) + (r->args != NULL? string("?") + r->args : string("")); - const string proxy(string("proxy:") + turi); - debug(proxy, "modeval::translateReference::proxy"); - r->filename = apr_pstrdup(r->pool, c_str(proxy)); - r->proxyreq = PROXYREQ_REVERSE; - r->handler = "proxy-server"; - apr_table_setn(r->notes, "proxy-nocanon", "1"); - return OK; - } - - debug(target, "modeval::translateReference::location"); - r->handler = "mod_tuscany_eval"; - return httpd::externalRedirect(target, r); + string turi = target + path(pathInfo) + (r->args != NULL? string("?") + string(r->args) : string("")); + const string proxy(string("proxy:") + turi); + debug(proxy, "modeval::translateReference::proxy"); + r->filename = apr_pstrdup(r->pool, c_str(proxy)); + r->proxyreq = PROXYREQ_REVERSE; + r->handler = "proxy-server"; + apr_table_setn(r->notes, "proxy-nocanon", "1"); + return OK; } // Route to a relative target URI using a local internal redirect - // /components/, target component name and request path info + // / c / target component name / request path info const value tname = substr(target, 0, find(target, '/')); - const string redir = path(append(apath, cons<value>(string("c"), cons(tname, pathInfo)))); + const list<value> redir = cons<value>(string("c"), cons(tname, pathInfo)); debug(redir, "modeval::translateReference::redirect"); - r->uri = apr_pstrdup(r->pool, c_str(redir)); - r->handler = "mod_tuscany_eval"; - return OK; + return proceedToHandler(r, false, redir, vpath, impls);; } /** @@ -934,121 +957,80 @@ const list<value> assocPath(const value& k, const list<value>& tree) { /** * Route a service request to the component providing the requested service. */ -int translateService(const ServerConf& sc, request_rec *r, const list<value>& rpath, const list<value>& apath) { - httpdDebugRequest(r, "modeval::translateService::input"); - debug(r->uri, "modeval::translateService::uri"); +int translateService(request_rec *r, const list<value>& rpath, const list<value>& vpath, const list<value>& svcs, const list<value>& impls) { + debug(rpath, "modeval::translateService::rpath"); + debug(flatten(svcs), "modeval::translateService::svcs"); // Find the requested component - debug(sc.services, "modeval::translateService::services"); - const list<value> svc(assocPath(rpath, sc.services)); + if (isNil(rpath)) + return HTTP_NOT_FOUND; + const list<value> svc(assocPath(rpath, svcs)); if (isNil(svc)) return DECLINED; - debug(svc, "modeval::translateService::service"); - - // Build a component-name + path-info URI - const list<value> target(append(apath, cons<value>(string("c"), cons<value>(cadr(svc), httpd::pathInfo(rpath, car(svc)))))); - debug(target, "modeval::translateService::target"); + debug(svc, "modeval::translateService::svc"); // Dispatch to the target component using a local internal redirect - const string redir(path(target)); + // / c / target component name / request path info + const list<value> redir = cons<value>(string("c"), cons<value>(cadr(svc), httpd::pathInfo(rpath, car(svc)))); debug(redir, "modeval::translateService::redirect"); - r->uri = apr_pstrdup(r->pool, c_str(redir)); - r->handler = "mod_tuscany_eval"; - return OK; + return proceedToHandler(r, false, redir, vpath, impls); } /** * Translate a request to the target app and component. */ -const int translateRequest(const ServerConf& sc, request_rec* r, const list<value>& rpath, const list<value>& apath) { - debug(apath, "modeval::translateRequest::apath"); +const int translateRequest(request_rec* r, const list<value>& rpath, const list<value>& vpath, const list<value>& refs, const list<value>& svcs, const list<value>& impls) { + debug(vpath, "modeval::translateRequest::vpath"); debug(rpath, "modeval::translateRequest::rpath"); - if (isNil(apath) && isNil(rpath)) - return DECLINED; + const string prefix = isNil(rpath)? "" : car(rpath); - if (!isNil(rpath)) { - - // If the request is targeting a virtual host, use the corresponding - // virtual host configuration - if (isNil(apath)) { - if (hasVhostDomainConf(sc) && hasVhostContributionConf(sc) && httpd::isVhostRequest(sc.server, sc.vhostDomain, r)) { - const string aname = httpd::hostName(r); - ServerConf vsc(r->pool, sc, aname); - if (!hasContent(vhostConfig(vsc, sc, r))) - return DECLINED; - return translateRequest(vsc, r, rpath, mklist<value>(aname)); - } - } - - // Let default handler handle a resource request - const value prefix = car(rpath); - if (prefix == string("vhosts") || prefix == string("v")) - return DECLINED; + // Translate a component request + if ((prefix == string("components") || prefix == string("c")) && translateComponent(r, rpath, vpath, impls) == OK) + return OK; - // Let our handler handle a component request - if (prefix == string("components") || prefix == string("c")) { - r->handler = "mod_tuscany_eval"; - return OK; - } + // Translate a component reference request + if ((prefix == string("references") || prefix == string("r")) && translateReference(r, rpath, vpath, refs, impls) == OK) + return OK; - // Translate a component reference request - if (prefix == string("references") || prefix == string("r")) - return translateReference(sc, r, rpath, apath); - - // Attempt to translate the request to a service request - if (translateService(sc, r, rpath, apath) == OK) - return OK; - - // Attempt to map the request to an actual file - if (isNil(apath)) { - const failable<request_rec*, int> fnr = httpd::internalSubRequest(r->uri, r); - if (!hasContent(fnr)) - return HTTP_INTERNAL_SERVER_ERROR; - request_rec* nr = content(fnr); - nr->uri = r->filename; - const int tr = ap_core_translate(nr); - if (tr != OK) - return tr; - if (ap_directory_walk(nr) == OK && ap_file_walk(nr) == OK && nr->finfo.filetype != APR_NOFILE) { - debug(nr->filename, "modeval::translateRequest::file"); - return DECLINED; - } + // Attempt to translate the request to a service request + if (translateService(r, rpath, vpath, svcs, impls) == OK) + return OK; - // If the request is targeting a virtual app, use the corresponding - // virtual host configuration - if (hasVhostContributionConf(sc)) { - const string cp = sc.vhostContributionPath + string(prefix) + "/" + sc.vhostCompositeName; - ServerConf vsc(r->pool, sc, string(prefix)); - if (!hasContent(vhostConfig(vsc, sc, r))) - return DECLINED; - return translateRequest(vsc, r, cdr(rpath), mklist<value>(car(rpath))); - } + // Attempt to map a request targeting the main host to an actual file + if (isNil(vpath)) { + const failable<request_rec*, int> fnr = httpd::internalSubRequest(r->uri, r); + if (!hasContent(fnr)) + return HTTP_INTERNAL_SERVER_ERROR; + request_rec* nr = content(fnr); + nr->uri = r->filename; + const int tr = ap_core_translate(nr); + if (tr != OK) + return tr; + if (ap_directory_walk(nr) == OK && ap_file_walk(nr) == OK && nr->finfo.filetype != APR_NOFILE) { + + // Found the target file, let the default handler serve it + debug(nr->filename, "modeval::translateRequest::file"); + return DECLINED; } - } - - // If we're in a virtual app and the request didn't match a service, - // reference or component, redirect it to /v/<uri>. This will allow - // mapping to the actual app resources using HTTPD aliases. - if (!isNil(apath)) { - if (isNil(rpath) && r->uri[strlen(r->uri) -1] != '/') { + } else { - // Make sure a document root request ends with a '/', using - // an external redirect - const string target = string(r->uri) + string("/") + (r->args != NULL? string("?") + r->args : string(""));; + // Make sure a document root request ends with a '/' using + // an external redirect + if (isNil(rpath) && r->uri[strlen(r->uri) - 1] != '/') { + const string target = string(r->uri) + string("/") + (r->args != NULL? string("?") + string(r->args) : string("")); debug(target, "modeval::translateRequest::location"); r->handler = "mod_tuscany_eval"; return httpd::externalRedirect(target, r); } - // Do an internal redirect to /v/<uri> - const string redir = string("/redirect:") + string("/v") + string(r->uri); - debug(redir, "modeval::translateRequest::redirect"); - r->filename = apr_pstrdup(r->pool, c_str(redir)); - r->handler = "mod_tuscany_eval"; - return OK; + // If the request didn't match a service, reference or component, + // redirect it to / v / app / path. This will allow mapping to + // the actual app resource using HTTPD aliases. + debug(true, "modeval::translateRequest::valias"); + return proceedToHandler(r, true, rpath, vpath, impls); } - return DECLINED; + return HTTP_NOT_FOUND; } /** @@ -1066,59 +1048,63 @@ int translate(request_rec *r) { // Get the server configuration const ServerConf& sc = httpd::serverConf<ServerConf>(r, &mod_tuscany_eval); - // Translate the request - return translateRequest(sc, r, pathValues(r->uri), list<value>()); -} + // Parse the request path + const list<value> rpath = pathValues(r->uri); -/** - * Handle a component request. - */ -const int handleRequest(const ServerConf& sc, const list<value>& rpath, request_rec *r) { - debug(rpath, "modeval::handleRequest::path"); - if (isNil(cdr(rpath))) - return HTTP_NOT_FOUND; + // Let default handler handle a resource request + const string prefix = isNil(rpath)? "" : car(rpath); + if (prefix == string("vhosts") || prefix == string("v")) + return DECLINED; - if (hasVhostContributionConf(sc)) { + // Get the request configuration + RequestConf& reqc = httpd::requestConf<RequestConf>(r, &mod_tuscany_eval); - // Handle a request targeting a component in a virtual host - if (hasVhostDomainConf(sc) && httpd::isVhostRequest(sc.server, sc.vhostDomain, r)) { + // If the request is targeting a virtual host, configure the components + // in that virtual host + if (length(sc.vhostc.domain) != 0 && (length(sc.vhostc.contribPath) != 0 || !isNil(sc.vhostc.provider)) && httpd::isVhostRequest(sc.server, sc.vhostc.domain, r)) { + const string vname = http::subDomain(httpd::hostName(r)); + const failable<Composite> fvcompos = confComponents(sc.vhostc.contribPath, sc.vhostc.composName, sc.vhostc.provider, vname, reqc.impls, sc.lifecycle, sc.sslc, sc.p); + if (!hasContent(fvcompos)) + return DECLINED; + const Composite vcompos = content(fvcompos); - // Determine the app name from the host sub-domain name, and - // store it in a request note - const string app = http::subDomain(httpd::hostName(r)); - apr_table_setn(r->notes, "X-Request-AppName", apr_pstrdup(r->pool, c_str(app))); - ServerConf vsc(r->pool, sc, app); - if (!hasContent(vhostStart(vsc, sc, r))) - return HTTP_INTERNAL_SERVER_ERROR; - const int rc = handleRequest(vsc, rpath, r); - vhostStop(vsc, sc); - return rc; - } + // Flag the request as virtual host based + reqc.vhost = true; - // Handle a request targeting a component in a virtual app - const value c = car(rpath); - if (c != string("components") && c != string("c")) { - - // Determine the app name from the request URI path and - // store it in a request note - const string app = string(c); - const string cp = sc.vhostContributionPath + app + "/" + sc.vhostCompositeName; - apr_table_setn(r->notes, "X-Request-AppName", apr_pstrdup(r->pool, c_str(app))); - - ServerConf vsc(r->pool, sc, app); - if (!hasContent(vhostStart(vsc, sc, r))) - return HTTP_INTERNAL_SERVER_ERROR; - const int rc = handleRequest(vsc, cdr(rpath), r); - vhostStop(vsc, sc); - return rc; - } + // Translate the request + reqc.impls = vcompos.impls; + return translateRequest(r, rpath, mklist<value>(vname), vcompos.refs, vcompos.svcs, reqc.impls); } - // Store the request uri path in a request note - apr_table_setn(r->notes, "X-Request-URI", apr_pstrdup(r->pool, c_str(path(rpath)))); + // Translate a request targeting the main host + const int rc = translateRequest(r, rpath, list<value>(), sc.compos.refs, sc.compos.svcs, sc.compos.impls); + if (rc != HTTP_NOT_FOUND) + return rc; + + // Attempt to map the first segment of the request path to a virtual host + if (length(prefix) != 0 && (length(sc.vhostc.contribPath) != 0 || !isNil(sc.vhostc.provider))) { + const string vname = prefix; + const failable<Composite> fvcompos = confComponents(sc.vhostc.contribPath, sc.vhostc.composName, sc.vhostc.provider, vname, reqc.impls, sc.lifecycle, sc.sslc, sc.p); + if (!hasContent(fvcompos)) + return DECLINED; + const Composite vcompos = content(fvcompos); + + // Translate the request + reqc.impls = vcompos.impls; + return translateRequest(r, cdr(rpath), mklist<value>(vname), vcompos.refs, vcompos.svcs, reqc.impls); + } + + return DECLINED; +} + +/** + * Handle a component request. + */ +const int handleRequest(const list<value>& rpath, request_rec *r, const list<value>& impls) { + debug(rpath, "modeval::handleRequest::path"); // Get the component implementation lambda - const list<value> impl(assoctree<value>(cadr(rpath), sc.implTree)); + const list<value> impl(assoctree<value>(cadr(rpath), impls)); if (isNil(impl)) { mkfailure<int>(string("Couldn't find component implementation: ") + cadr(rpath)); return HTTP_NOT_FOUND; @@ -1152,22 +1138,49 @@ int handler(request_rec *r) { if (r->status == HTTP_MOVED_TEMPORARILY) return OK; - // Handle an internal redirect as directed by the translate hook - if (r->filename != NULL && !strncmp(r->filename, "/redirect:", 10)) { - if (r->args == NULL) - return httpd::internalRedirect(httpd::redirectURI(string(r->filename + 10), string(r->path_info)), r); - return httpd::internalRedirect(httpd::redirectURI(string(r->filename + 10), string(r->path_info), string(r->args)), r); - } + // Create a scoped memory pool and a scope for the current request + gc_scoped_pool pool(r->pool); + ScopedRequest sr(r); + httpdDebugRequest(r, "modeval::handler::input"); - // Create a scope for the current request - ScopedRequest sr(r); + // Get the request configuration + RequestConf& reqc = httpd::requestConf<RequestConf>(r, &mod_tuscany_eval); + + // Handle an internal redirect as directed by the translate hook + if (reqc.valias) { + const string redir = path(cons<value>(string("v"), reqc.vhost? reqc.vpath : list<value>())) + string(r->uri) + (r->args != NULL? string("?") + string(r->args) : string("")); + debug(redir, "modeval::handler::internalredirect"); + return httpd::internalRedirect(redir, r); + } + if (isNil(reqc.rpath)) + return HTTP_NOT_FOUND; // Get the server configuration const ServerConf& sc = httpd::serverConf<ServerConf>(r, &mod_tuscany_eval); - // Handle the request - return handleRequest(sc, pathValues(r->uri), r); + // Handle a request targeting a component in a virtual host + if (!isNil(reqc.vpath)) { + + // Start the components in the virtual host + const failable<list<value> > fsimpls = startComponents(reqc.impls); + if (!hasContent(fsimpls)) + return HTTP_INTERNAL_SERVER_ERROR; + const list<value> simpls = content(fsimpls); + + // Merge the components in the virtual host with the components in the main host + reqc.impls = mkbtree(sort(append(flatten(sc.compos.impls), flatten(simpls)))); + + // Handle the request against the running components + const int rc = handleRequest(reqc.rpath, r, reqc.impls); + + // Stop the components in the virtual host + stopComponents(simpls); + return rc; + } + + // Handle a request targeting a component in the main host + return handleRequest(reqc.rpath, r, sc.compos.impls); } /** @@ -1179,7 +1192,7 @@ apr_status_t serverCleanup(void* v) { debug("modeval::serverCleanup"); // Stop the component implementations - applyLifecycleExpr(sc.implementations, mklist<value>("stop")); + stopComponents(sc.compos.impls); // Call the module lifecycle function if (isNil(sc.lifecycle)) @@ -1200,21 +1213,12 @@ const int postConfigMerge(const ServerConf& mainsc, server_rec* s) { ServerConf& sc = httpd::serverConf<ServerConf>(s, &mod_tuscany_eval); debug(httpd::serverName(s), "modeval::postConfigMerge::serverName"); sc.lifecycle = mainsc.lifecycle; - sc.vhostName = mainsc.vhostName; - sc.contributionPath = mainsc.contributionPath; - sc.compositeName = mainsc.compositeName; - sc.vhostDomain = mainsc.vhostDomain; - sc.vhostContributionPath = mainsc.vhostContributionPath; - sc.vhostCompositeName = mainsc.vhostCompositeName; - sc.vhostContributorName = mainsc.vhostContributorName; - if (sc.ca == "") sc.ca = mainsc.ca; - if (sc.cert == "") sc.cert = mainsc.cert; - if (sc.key == "") sc.key = mainsc.key; - sc.references = mainsc.references; - sc.services = mainsc.services; - sc.implementations = mainsc.implementations; - sc.implTree = mainsc.implTree; - sc.vhostContributor = mainsc.vhostContributor; + sc.contribc = mainsc.contribc; + sc.vhostc = mainsc.vhostc; + if (sc.sslc.ca == "") sc.sslc.ca = mainsc.sslc.ca; + if (sc.sslc.cert == "") sc.sslc.cert = mainsc.sslc.cert; + if (sc.sslc.key == "") sc.sslc.key = mainsc.sslc.key; + sc.compos = mainsc.compos; return postConfigMerge(mainsc, s->next); } @@ -1226,6 +1230,8 @@ int postConfig(apr_pool_t *p, unused apr_pool_t *plog, unused apr_pool_t *ptemp, // Get the server configuration and determine the server name ServerConf& sc = httpd::serverConf<ServerConf>(s, &mod_tuscany_eval); debug(httpd::serverName(s), "modeval::postConfig::serverName"); + debug(sc.contribc.contribPath, "modeval::postConfig::contribPath"); + debug(sc.contribc.composName, "modeval::postConfig::composName"); // Count the calls to post config const string k("tuscany::modeval::postConfig"); @@ -1239,8 +1245,8 @@ int postConfig(apr_pool_t *p, unused apr_pool_t *plog, unused apr_pool_t *ptemp, if (count == 1) { // Chdir to the deployed contribution - if (chdir(c_str(sc.contributionPath)) != 0) { - mkfailure<bool>(string("Couldn't chdir to the deployed contribution: ") + sc.contributionPath); + if (chdir(c_str(sc.contribc.contribPath)) != 0) { + mkfailure<bool>(string("Couldn't chdir to the deployed contribution: ") + sc.contribc.contribPath); return -1; } @@ -1261,11 +1267,12 @@ int postConfig(apr_pool_t *p, unused apr_pool_t *plog, unused apr_pool_t *ptemp, } // Configure the deployed components - const failable<bool> res = confComponents(sc); - if (!hasContent(res)) { + const failable<Composite> compos = confComponents(sc.contribc.contribPath, sc.contribc.composName, value(), "", sc.compos.impls, sc.lifecycle, sc.sslc, sc.p); + if (!hasContent(compos)) { cfailure << "[Tuscany] Due to one or more errors mod_tuscany_eval loading failed. Causing apache to stop loading." << endl; return -1; } + sc.compos = content(compos); // Register a cleanup callback, called when the server is stopped or restarted apr_pool_pre_cleanup_register(p, (void*)&sc, serverCleanup); @@ -1287,18 +1294,16 @@ void childInit(apr_pool_t* p, server_rec* s) { ServerConf& sc = *psc; // Start the components in the child process - const failable<bool> res = startComponents(sc); - if (!hasContent(res)) { + const failable<list<value> > fsimpls = startComponents(sc.compos.impls); + if (!hasContent(fsimpls)) { cfailure << "[Tuscany] Due to one or more errors mod_tuscany_eval loading failed. Causing apache to stop loading." << endl; exit(APEXIT_CHILDFATAL); } + sc.compos.impls = content(fsimpls); - // Store the implementation lambda functions in a tree for fast retrieval - sc.implTree = mkbtree(sort(sc.implementations)); - - // Create a proxy for the vhost contributor if needed - if (length(sc.vhostContributorName) != 0) - sc.vhostContributor = mkimplProxy(sc, sc.vhostContributorName); + // Create a proxy for the vhost provider if needed + if (length(sc.vhostc.providerName) != 0) + sc.vhostc.provider = mkimplProxy(sc.vhostc.providerName, sc.compos.impls, sc.sslc); // Merge the updated configuration into the virtual hosts postConfigMerge(sc, s->next); @@ -1313,55 +1318,55 @@ void childInit(apr_pool_t* p, server_rec* s) { const char* confContribution(cmd_parms *cmd, unused void *c, const char *arg) { gc_scoped_pool pool(cmd->pool); ServerConf& sc = httpd::serverConf<ServerConf>(cmd, &mod_tuscany_eval); - sc.contributionPath = arg; + sc.contribc.contribPath = arg; return NULL; } const char* confComposite(cmd_parms *cmd, unused void *c, const char *arg) { gc_scoped_pool pool(cmd->pool); ServerConf& sc = httpd::serverConf<ServerConf>(cmd, &mod_tuscany_eval); - sc.compositeName = arg; + sc.contribc.composName = arg; return NULL; } const char* confVirtualDomain(cmd_parms *cmd, unused void *c, const char *arg) { gc_scoped_pool pool(cmd->pool); ServerConf& sc = httpd::serverConf<ServerConf>(cmd, &mod_tuscany_eval); - sc.vhostDomain = arg; + sc.vhostc.domain = arg; return NULL; } const char* confVirtualContribution(cmd_parms *cmd, unused void *c, const char *arg) { gc_scoped_pool pool(cmd->pool); ServerConf& sc = httpd::serverConf<ServerConf>(cmd, &mod_tuscany_eval); - sc.vhostContributionPath = arg; + sc.vhostc.contribPath = arg; return NULL; } -const char* confVirtualContributor(cmd_parms *cmd, unused void *c, const char *arg) { +const char* confVirtualprovider(cmd_parms *cmd, unused void *c, const char *arg) { gc_scoped_pool pool(cmd->pool); ServerConf& sc = httpd::serverConf<ServerConf>(cmd, &mod_tuscany_eval); - sc.vhostContributorName = arg; + sc.vhostc.providerName = arg; return NULL; } const char* confVirtualComposite(cmd_parms *cmd, unused void *c, const char *arg) { gc_scoped_pool pool(cmd->pool); ServerConf& sc = httpd::serverConf<ServerConf>(cmd, &mod_tuscany_eval); - sc.vhostCompositeName = arg; + sc.vhostc.composName = arg; return NULL; } const char* confCAFile(cmd_parms *cmd, unused void *c, const char *arg) { gc_scoped_pool pool(cmd->pool); ServerConf& sc = httpd::serverConf<ServerConf>(cmd, &mod_tuscany_eval); - sc.ca = arg; + sc.sslc.ca = arg; return NULL; } const char* confCertFile(cmd_parms *cmd, unused void *c, const char *arg) { gc_scoped_pool pool(cmd->pool); ServerConf& sc = httpd::serverConf<ServerConf>(cmd, &mod_tuscany_eval); - sc.cert = arg; + sc.sslc.cert = arg; return NULL; } const char* confCertKeyFile(cmd_parms *cmd, unused void *c, const char *arg) { gc_scoped_pool pool(cmd->pool); ServerConf& sc = httpd::serverConf<ServerConf>(cmd, &mod_tuscany_eval); - sc.key = arg; + sc.sslc.key = arg; return NULL; } const char* confEnv(unused cmd_parms *cmd, unused void *c, const char *name, const char *value) { @@ -1378,7 +1383,7 @@ const command_rec commands[] = { AP_INIT_TAKE1("SCAComposite", (const char*(*)())confComposite, NULL, RSRC_CONF, "SCA composite location"), AP_INIT_TAKE1("SCAVirtualDomain", (const char*(*)())confVirtualDomain, NULL, RSRC_CONF, "SCA virtual host domain"), AP_INIT_TAKE1("SCAVirtualContribution", (const char*(*)())confVirtualContribution, NULL, RSRC_CONF, "SCA virtual host contribution path"), - AP_INIT_TAKE1("SCAVirtualContributor", (const char*(*)())confVirtualContributor, NULL, RSRC_CONF, "SCA virtual host contributor component"), + AP_INIT_TAKE1("SCAVirtualContributor", (const char*(*)())confVirtualprovider, NULL, RSRC_CONF, "SCA virtual host provider component"), AP_INIT_TAKE1("SCAVirtualComposite", (const char*(*)())confVirtualComposite, NULL, RSRC_CONF, "SCA virtual composite location"), AP_INIT_TAKE12("SCASetEnv", (const char*(*)())confEnv, NULL, OR_FILEINFO, "Environment variable name and optional value"), AP_INIT_TAKE1("SCAWiringSSLCACertificateFile", (const char*(*)())confCAFile, NULL, RSRC_CONF, "SCA wiring SSL CA certificate file"), |