diff options
author | jsdelfino <jsdelfino@13f79535-47bb-0310-9956-ffa450edef68> | 2011-06-13 07:57:13 +0000 |
---|---|---|
committer | jsdelfino <jsdelfino@13f79535-47bb-0310-9956-ffa450edef68> | 2011-06-13 07:57:13 +0000 |
commit | ba223e693c0f6e652fd70c05d83d69956262ff09 (patch) | |
tree | a29db0715d2274f13de355a7e4fbcf5919399282 | |
parent | eb7ad1a0241d049f10c9e62a8eb4d9e1dd3000a9 (diff) |
Improve support for HTTP verbs and enable calls inside a domain without having to repeat the domain name in all the URLs.
git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@1135047 13f79535-47bb-0310-9956-ffa450edef68
18 files changed, 874 insertions, 95 deletions
diff --git a/sca-cpp/trunk/components/http/Makefile.am b/sca-cpp/trunk/components/http/Makefile.am index 4388ec8057..1a081b8da6 100644 --- a/sca-cpp/trunk/components/http/Makefile.am +++ b/sca-cpp/trunk/components/http/Makefile.am @@ -19,8 +19,8 @@ compdir=$(prefix)/components/http EXTRA_DIST = http.composite httpget.componentType httpdelete.componentType *.scm -comp_LTLIBRARIES = libhttpget.la libhttpdelete.la -noinst_DATA = libhttpget.so libhttpdelete.so +comp_LTLIBRARIES = libhttpget.la libhttpdelete.la libhttppost.la libhttpput.la +noinst_DATA = libhttpget.so libhttpdelete.so libhttppost.so libhttpput.so libhttpget_la_SOURCES = httpget.cpp libhttpget_la_LDFLAGS = -lxml2 -lmozjs -curl @@ -32,6 +32,21 @@ libhttpdelete_la_LDFLAGS = -lxml2 -lmozjs -curl libhttpdelete.so: ln -s .libs/libhttpdelete.so +libhttppost_la_SOURCES = httppost.cpp +libhttppost_la_LDFLAGS = -lxml2 -lmozjs -curl +libhttppost.so: + ln -s .libs/libhttppost.so + +libhttpput_la_SOURCES = httpput.cpp +libhttpput_la_LDFLAGS = -lxml2 -lmozjs -curl +libhttpput.so: + ln -s .libs/libhttpput.so + +libhttppatch_la_SOURCES = httppatch.cpp +libhttppatch_la_LDFLAGS = -lxml2 -lmozjs -curl +libhttppatch.so: + ln -s .libs/libhttppatch.so + client_test_SOURCES = client-test.cpp client_test_LDFLAGS = -lxml2 -lcurl -lmozjs diff --git a/sca-cpp/trunk/components/http/client-test.cpp b/sca-cpp/trunk/components/http/client-test.cpp index a83bf55252..3ce9f1ae68 100644 --- a/sca-cpp/trunk/components/http/client-test.cpp +++ b/sca-cpp/trunk/components/http/client-test.cpp @@ -36,15 +36,16 @@ namespace tuscany { namespace http { -const string uri("http://localhost:8090/httpget"); +const string getURI("http://localhost:8090/httpget"); +const string postURI("http://localhost:8090/httppost"); +const string putURI("http://localhost:8090/httpput"); +const string deleteURI("http://localhost:8090/httpdelete"); bool testGet() { http::CURLSession cs("", "", "", ""); - const failable<value> val = http::get(uri, cs); + const failable<value> val = http::get(getURI, cs); assert(hasContent(val)); - assert(contains(string(car<value>(cadr<value>(content(val)))), "It works")); - return true; } @@ -53,9 +54,8 @@ struct getLoop { getLoop(http::CURLSession cs) : cs(cs) { } const bool operator()() const { - const failable<value> val = http::get(uri, cs); + const failable<value> val = http::get(getURI, cs); assert(hasContent(val)); - assert(contains(string(car<value>(cadr<value>(content(val)))), "It works")); return true; } }; @@ -69,6 +69,30 @@ bool testGetPerf() { return true; } +bool testPost() { + http::CURLSession cs("", "", "", ""); + + const failable<value> val = http::get(postURI, cs); + assert(hasContent(val)); + return true; +} + +bool testPut() { + http::CURLSession cs("", "", "", ""); + + const failable<value> val = http::get(putURI, cs); + assert(hasContent(val)); + return true; +} + +bool testDelete() { + http::CURLSession cs("", "", "", ""); + + const failable<value> val = http::get(deleteURI, cs); + assert(hasContent(val)); + return true; +} + } } @@ -77,6 +101,9 @@ int main() { tuscany::http::testGet(); tuscany::http::testGetPerf(); + tuscany::http::testPost(); + tuscany::http::testPut(); + tuscany::http::testDelete(); tuscany::cout << "OK" << tuscany::endl; diff --git a/sca-cpp/trunk/components/http/content-test.scm b/sca-cpp/trunk/components/http/content-test.scm new file mode 100644 index 0000000000..f381546190 --- /dev/null +++ b/sca-cpp/trunk/components/http/content-test.scm @@ -0,0 +1,23 @@ +; 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. + +; Content test case + +(define (get id) + (list (list 'entry '(title "Item") '(id "111") '(content (item (name "Apple") (currencyCode "USD") (currencySymbol "$") (price 2.99))))) +) + diff --git a/sca-cpp/trunk/components/http/http.composite b/sca-cpp/trunk/components/http/http.composite index 43d9fb6413..48fe1c3b55 100644 --- a/sca-cpp/trunk/components/http/http.composite +++ b/sca-cpp/trunk/components/http/http.composite @@ -29,6 +29,41 @@ <reference name="url" target="url-test"/> </component> + <component name="httppost"> + <implementation.cpp path="." library="libhttppost"/> + <service name="httppost"> + <binding.http uri="httppost"/> + </service> + <reference name="url" target="url-test"/> + <reference name="content" target="content-test"/> + </component> + + <component name="httpput"> + <implementation.cpp path="." library="libhttpput"/> + <service name="httpput"> + <binding.http uri="httpput"/> + </service> + <reference name="url" target="url-test"/> + <reference name="content" target="content-test"/> + </component> + + <component name="httppatch"> + <implementation.cpp path="." library="libhttppatch"/> + <service name="httppatch"> + <binding.http uri="httppatch"/> + </service> + <reference name="url" target="url-test"/> + <reference name="content" target="content-test"/> + </component> + + <component name="httpdelete"> + <implementation.cpp path="." library="libhttpdelete"/> + <service name="httpdelete"> + <binding.http uri="httpdelete"/> + </service> + <reference name="url" target="url-test"/> + </component> + <component name="url-test"> <implementation.scheme script="url-test.scm"/> <service name="url-test"> @@ -36,4 +71,18 @@ </service> </component> + <component name="content-test"> + <implementation.scheme script="content-test.scm"/> + <service name="content-test"> + <binding.http uri="content-test"/> + </service> + </component> + + <component name="scheme-test"> + <implementation.scheme script="server-test.scm"/> + <service name="test"> + <binding.http uri="test"/> + </service> + </component> + </composite> diff --git a/sca-cpp/trunk/components/http/httppatch.componentType b/sca-cpp/trunk/components/http/httppatch.componentType new file mode 100644 index 0000000000..8f3173be85 --- /dev/null +++ b/sca-cpp/trunk/components/http/httppatch.componentType @@ -0,0 +1,29 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + * 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. +--> +<componentType xmlns="http://docs.oasis-open.org/ns/opencsa/sca/200912" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:t="http://tuscany.apache.org/xmlns/sca/1.1" + targetNamespace="http://tuscany.apache.org/xmlns/sca/components"> + + <service name="http"/> + <reference name="url"/> + <reference name="content"/> + +</composite> diff --git a/sca-cpp/trunk/components/http/httppatch.cpp b/sca-cpp/trunk/components/http/httppatch.cpp new file mode 100644 index 0000000000..4debca045e --- /dev/null +++ b/sca-cpp/trunk/components/http/httppatch.cpp @@ -0,0 +1,93 @@ +/* + * 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$ */ + +/** + * HTTP client component implementation. + */ + +#include "string.hpp" +#include "function.hpp" +#include "list.hpp" +#include "value.hpp" +#include "monad.hpp" +#include "../../modules/http/http.hpp" + +namespace tuscany { +namespace httppatch { + +/** + * Evaluate an HTTP patch. + */ +const failable<value> get(const lambda<value(const list<value>&)> url, const lambda<value(const list<value>&)> val, http::CURLSession& ch) { + debug("httppatch::get"); + const value u = url(mklist<value>("get", list<value>())); + const value v = val(mklist<value>("get", list<value>())); + debug(u, "httppatch::get::url"); + debug(v, "httppatch::get::val"); + return http::patch(v, u, ch); +} + +/** + * Component implementation lambda function. + */ +class applyhttp { +public: + applyhttp(const lambda<value(const list<value>&)> url, const lambda<value(const list<value>&)> val, http::CURLSession& ch) : url(url), val(val), ch(ch) { + } + + const value operator()(const list<value>& params) const { + debug(params, "httppatch::applyhttp::params"); + const value func(car(params)); + if (func == "get") + return get(url, val, ch); + return tuscany::mkfailure<tuscany::value>(); + } + +private: + const lambda<value(const list<value>&)> url; + const lambda<value(const list<value>&)> val; + http::CURLSession& ch; +}; + +/** + * Start the component. + */ +const failable<value> start(const list<value>& params) { + // Create a CURL session + http::CURLSession& ch = *(new (gc_new<http::CURLSession>()) http::CURLSession("", "", "", "")); + + // Return the component implementation lambda function + return value(lambda<value(const list<value>&)>(applyhttp(car(params), cadr(params), ch))); +} + +} +} + +extern "C" { + +const tuscany::value apply(const tuscany::list<tuscany::value>& params) { + const tuscany::value func(car(params)); + if (func == "start") + return tuscany::httppatch::start(cdr(params)); + return tuscany::mkfailure<tuscany::value>(); +} + +} diff --git a/sca-cpp/trunk/components/http/httppost.componentType b/sca-cpp/trunk/components/http/httppost.componentType new file mode 100644 index 0000000000..8f3173be85 --- /dev/null +++ b/sca-cpp/trunk/components/http/httppost.componentType @@ -0,0 +1,29 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + * 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. +--> +<componentType xmlns="http://docs.oasis-open.org/ns/opencsa/sca/200912" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:t="http://tuscany.apache.org/xmlns/sca/1.1" + targetNamespace="http://tuscany.apache.org/xmlns/sca/components"> + + <service name="http"/> + <reference name="url"/> + <reference name="content"/> + +</composite> diff --git a/sca-cpp/trunk/components/http/httppost.cpp b/sca-cpp/trunk/components/http/httppost.cpp new file mode 100644 index 0000000000..9784c4513c --- /dev/null +++ b/sca-cpp/trunk/components/http/httppost.cpp @@ -0,0 +1,93 @@ +/* + * 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$ */ + +/** + * HTTP client component implementation. + */ + +#include "string.hpp" +#include "function.hpp" +#include "list.hpp" +#include "value.hpp" +#include "monad.hpp" +#include "../../modules/http/http.hpp" + +namespace tuscany { +namespace httppost { + +/** + * Evaluate an HTTP post. + */ +const failable<value> get(const lambda<value(const list<value>&)> url, const lambda<value(const list<value>&)> val, http::CURLSession& ch) { + debug("httppost::get"); + const value u = url(mklist<value>("get", list<value>())); + const value v = val(mklist<value>("get", list<value>())); + debug(u, "httppost::get::url"); + debug(v, "httppost::get::val"); + return http::post(v, u, ch); +} + +/** + * Component implementation lambda function. + */ +class applyhttp { +public: + applyhttp(const lambda<value(const list<value>&)> url, const lambda<value(const list<value>&)> val, http::CURLSession& ch) : url(url), val(val), ch(ch) { + } + + const value operator()(const list<value>& params) const { + debug(params, "httppost::applyhttp::params"); + const value func(car(params)); + if (func == "get") + return get(url, val, ch); + return tuscany::mkfailure<tuscany::value>(); + } + +private: + const lambda<value(const list<value>&)> url; + const lambda<value(const list<value>&)> val; + http::CURLSession& ch; +}; + +/** + * Start the component. + */ +const failable<value> start(const list<value>& params) { + // Create a CURL session + http::CURLSession& ch = *(new (gc_new<http::CURLSession>()) http::CURLSession("", "", "", "")); + + // Return the component implementation lambda function + return value(lambda<value(const list<value>&)>(applyhttp(car(params), cadr(params), ch))); +} + +} +} + +extern "C" { + +const tuscany::value apply(const tuscany::list<tuscany::value>& params) { + const tuscany::value func(car(params)); + if (func == "start") + return tuscany::httppost::start(cdr(params)); + return tuscany::mkfailure<tuscany::value>(); +} + +} diff --git a/sca-cpp/trunk/components/http/httpput.componentType b/sca-cpp/trunk/components/http/httpput.componentType new file mode 100644 index 0000000000..8f3173be85 --- /dev/null +++ b/sca-cpp/trunk/components/http/httpput.componentType @@ -0,0 +1,29 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + * 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. +--> +<componentType xmlns="http://docs.oasis-open.org/ns/opencsa/sca/200912" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:t="http://tuscany.apache.org/xmlns/sca/1.1" + targetNamespace="http://tuscany.apache.org/xmlns/sca/components"> + + <service name="http"/> + <reference name="url"/> + <reference name="content"/> + +</composite> diff --git a/sca-cpp/trunk/components/http/httpput.cpp b/sca-cpp/trunk/components/http/httpput.cpp new file mode 100644 index 0000000000..4ec63dabce --- /dev/null +++ b/sca-cpp/trunk/components/http/httpput.cpp @@ -0,0 +1,93 @@ +/* + * 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$ */ + +/** + * HTTP client component implementation. + */ + +#include "string.hpp" +#include "function.hpp" +#include "list.hpp" +#include "value.hpp" +#include "monad.hpp" +#include "../../modules/http/http.hpp" + +namespace tuscany { +namespace httpput { + +/** + * Evaluate an HTTP put. + */ +const failable<value> get(const lambda<value(const list<value>&)> url, const lambda<value(const list<value>&)> val, http::CURLSession& ch) { + debug("httpput::get"); + const value u = url(mklist<value>("get", list<value>())); + const value v = val(mklist<value>("get", list<value>())); + debug(u, "httpput::get::url"); + debug(v, "httpput::get::val"); + return http::put(v, u, ch); +} + +/** + * Component implementation lambda function. + */ +class applyhttp { +public: + applyhttp(const lambda<value(const list<value>&)> url, const lambda<value(const list<value>&)> val, http::CURLSession& ch) : url(url), val(val), ch(ch) { + } + + const value operator()(const list<value>& params) const { + debug(params, "httpput::applyhttp::params"); + const value func(car(params)); + if (func == "get") + return get(url, val, ch); + return tuscany::mkfailure<tuscany::value>(); + } + +private: + const lambda<value(const list<value>&)> url; + const lambda<value(const list<value>&)> val; + http::CURLSession& ch; +}; + +/** + * Start the component. + */ +const failable<value> start(const list<value>& params) { + // Create a CURL session + http::CURLSession& ch = *(new (gc_new<http::CURLSession>()) http::CURLSession("", "", "", "")); + + // Return the component implementation lambda function + return value(lambda<value(const list<value>&)>(applyhttp(car(params), cadr(params), ch))); +} + +} +} + +extern "C" { + +const tuscany::value apply(const tuscany::list<tuscany::value>& params) { + const tuscany::value func(car(params)); + if (func == "start") + return tuscany::httpput::start(cdr(params)); + return tuscany::mkfailure<tuscany::value>(); +} + +} diff --git a/sca-cpp/trunk/components/http/server-test.scm b/sca-cpp/trunk/components/http/server-test.scm new file mode 100644 index 0000000000..4bbff6e5c2 --- /dev/null +++ b/sca-cpp/trunk/components/http/server-test.scm @@ -0,0 +1,44 @@ +; 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. + +; JSON-RPC test case + +(define (echo x) x) + +; ATOMPub test case + +(define (get id) + (if (nul id) + '((feed (title "Sample Feed") (id "123456789") (entry + (((title "Item") (id "111") (content (item (name "Apple") (currencyCode "USD") (currencySymbol "$") (price 2.99)))) + ((title "Item") (id "222") (content (item (name "Orange") (currencyCode "USD") (currencySymbol "$") (price 3.55)))) + ((title "Item") (id "333") (content (item (name "Pear") (currencyCode "USD") (currencySymbol "$") (price 1.55)))))))) + + (list (list 'entry '(title "Item") (list 'id (car id)) '(content (item (name "Apple") (currencyCode "USD") (currencySymbol "$") (price 2.99)))))) +) + +(define (post collection item) + '("123456789") +) + +(define (put id item) + true +) + +(define (delete id) + true +) diff --git a/sca-cpp/trunk/components/http/url-test.scm b/sca-cpp/trunk/components/http/url-test.scm index 29e6629aa5..37a5b345b2 100644 --- a/sca-cpp/trunk/components/http/url-test.scm +++ b/sca-cpp/trunk/components/http/url-test.scm @@ -18,6 +18,6 @@ ; URL test case (define (get id) - "http://localhost:8090/index.html" + "http://localhost:8090/test" ) diff --git a/sca-cpp/trunk/modules/edit/apps/testhttp/app.composite b/sca-cpp/trunk/modules/edit/apps/testhttp/app.composite index a632809760..93016ae915 100644 --- a/sca-cpp/trunk/modules/edit/apps/testhttp/app.composite +++ b/sca-cpp/trunk/modules/edit/apps/testhttp/app.composite @@ -1,22 +1,4 @@ <?xml version="1.0" encoding="UTF-8"?> -<!-- - * 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. ---> <composite xmlns="http://docs.oasis-open.org/ns/opencsa/sca/200912" name="app" targetNamespace="http://app"> <service name="call" promote="call"/> <service name="get" promote="get"/> @@ -25,9 +7,9 @@ <service name="get4" promote="get4"/> <service name="get5" promote="get5"/> <service name="get6" promote="get6"/> - <service name="parse" promote="parse"/> <service name="item" promote="property"/> - <component x="36" y="287" name="call" title="call" color="green1"> + <service name="parse" promote="parse"/> + <component x="20" y="300" name="call" title="call" color="green1"> <implementation.python script="nuvem/call.py"/> <service name="call"/> <reference target="name" name="name"/> @@ -38,32 +20,38 @@ <service name="first"/> <reference target="rest" name="list"/> </component> - <component x="20" y="8" name="get" title="get" color="green1"> + <component x="750" y="320" name="format1" title="format" color="magenta1"> + <implementation.python script="nuvem/format_.py"/> + <service name="format"/> + <reference target="text12" name="pattern"/> + <reference target="list2" name="values"/> + </component> + <component x="20" y="0" name="get" title="get" color="green1"> <implementation.cpp path="lib/http" library="libhttpget"/> <service name="get"/> <reference target="text" name="url"/> </component> - <component x="18" y="61" name="get2" title="get" color="green1"> + <component x="20" y="70" name="get2" title="get" color="green1"> <implementation.cpp path="lib/http" library="libhttpget"/> <service name="get"/> <reference target="text2" name="url"/> </component> - <component x="14" y="112" name="get3" title="get" color="green1"> + <component x="20" y="150" name="get3" title="get" color="green1"> <implementation.cpp path="lib/http" library="libhttpget"/> <service name="get"/> <reference target="text3" name="url"/> </component> - <component x="19" y="170" name="get4" title="get" color="green1"> + <component x="370" y="0" name="get4" title="get" color="green1"> <implementation.cpp path="lib/http" library="libhttpget"/> <service name="get"/> <reference target="text4" name="url"/> </component> - <component x="241" y="6" name="get5" title="get" color="green1"> + <component x="230" y="0" name="get5" title="get" color="green1"> <implementation.cpp path="lib/http" library="libhttpget"/> <service name="get"/> <reference target="text5" name="url"/> </component> - <component x="16" y="227" name="get6" title="get" color="green1"> + <component x="20" y="220" name="get6" title="get" color="green1"> <implementation.cpp path="lib/http" library="libhttpget"/> <service name="get"/> <reference target="text6" name="url"/> @@ -73,12 +61,42 @@ <service name="get"/> <reference target="text7" name="url"/> </component> + <component name="item2" title="{propval} :" color="orange1"> + <implementation.python script="nuvem/item.py"/> + <service name="item"/> + <reference target="user" name="value"/> + <property>user</property> + </component> + <component name="item3" title="{propval} :" color="orange1"> + <implementation.python script="nuvem/item.py"/> + <service name="item"/> + <reference target="params" name="value"/> + <property>name</property> + </component> <component name="join" title="join" color="magenta1"> <implementation.python script="nuvem/join.py"/> <service name="join"/> <reference target="text9" name="separator"/> <reference target="first" name="list"/> </component> + <component x="570" y="350" name="keychain1" title="keychain" color="green1"> + <implementation.python script="nuvem/keychain.py"/> + <service name="keychain"/> + <reference target="name1" name="name"/> + <reference name="account" target="Accounts" visible="false"/> + </component> + <component x="710" y="290" name="keychain2" title="keychain" color="green1"> + <implementation.python script="nuvem/keychain.py"/> + <service name="keychain"/> + <reference target="name2" name="name"/> + <reference name="account" target="Accounts" visible="false"/> + </component> + <component x="720" y="310" name="keychain3" title="keychain" color="green1"> + <implementation.python script="nuvem/keychain.py"/> + <service name="keychain"/> + <reference target="name3" name="name"/> + <reference name="account" target="Accounts" visible="false"/> + </component> <component name="list" title="list" color="yellow1"> <implementation.python script="nuvem/list_.py"/> <service name="list"/> @@ -86,40 +104,64 @@ <reference target="item3" name="item" clonable="true"/> <reference name="item" clonable="true"/> </component> + <component name="list1" title="list" color="yellow1"> + <implementation.python script="nuvem/list_.py"/> + <service name="list"/> + <reference target="keychain1" name="item" clonable="true"/> + <reference target="text10" name="item" clonable="true"/> + <reference name="item" clonable="true"/> + </component> + <component name="list2" title="list" color="yellow1"> + <implementation.python script="nuvem/list_.py"/> + <service name="list"/> + <reference target="text11" name="item" clonable="true"/> + <reference target="text13" name="item" clonable="true"/> + <reference target="text14" name="item" clonable="true"/> + <reference name="item" clonable="true"/> + </component> + <component name="list4" title="list" color="yellow1"> + <implementation.python script="nuvem/list_.py"/> + <service name="list"/> + <reference target="format1" name="item" clonable="true"/> + <reference name="item" clonable="true"/> + </component> <component name="name" title="" color="orange1"> <implementation.python script="nuvem/name.py"/> <service name="name"/> <property>https://testhttp.sca-store.com:8453/components/property</property> </component> + <component x="630" y="350" name="name1" title="" color="orange1"> + <implementation.python script="nuvem/name.py"/> + <service name="name"/> + <property>twilliosid</property> + </component> + <component x="780" y="280" name="name2" title="" color="orange1"> + <implementation.python script="nuvem/name.py"/> + <service name="name"/> + <property>twilliosid</property> + </component> + <component x="780" y="320" name="name3" title="" color="orange1"> + <implementation.python script="nuvem/name.py"/> + <service name="name"/> + <property>twilliotoken</property> + </component> <component name="params" title="?params" color="green1"> <implementation.python script="nuvem/params.py"/> <service name="params"/> <property name="query" visible="false"/> </component> - <component x="597" y="167" name="parse" title="parse" color="magenta1"> + <component x="410" y="290" name="parse" title="parse" color="magenta1"> <implementation.python script="nuvem/parse.py"/> <service name="parse"/> <reference target="text8" name="regexp"/> <reference target="join" name="string"/> </component> - <component x="74" y="343" name="property" title="{propval} :" color="orange1"> + <component x="20" y="370" name="property" title="{propval} :" color="orange1"> <implementation.python script="nuvem/item.py"/> <service name="item"/> <reference target="list" name="value"/> <property>test</property> </component> - <component name="item2" title="{propval} :" color="orange1"> - <implementation.python script="nuvem/item.py"/> - <service name="item"/> - <reference target="user" name="value"/> - <property>user</property> - </component> - <component name="item3" title="{propval} :" color="orange1"> - <implementation.python script="nuvem/item.py"/> - <service name="item"/> - <reference target="params" name="value"/> - <property>name</property> - </component> <component name="rest" title="rest" color="yellow1"> <implementation.python script="nuvem/rest.py"/> <service name="rest"/> @@ -130,6 +172,41 @@ <service name="text"/> <property>http://www.google.com</property> </component> + <component x="530" y="320" name="text1" title=" '{propval}'" color="orange1"> + <implementation.python script="nuvem/text.py"/> + <service name="text"/> + <property>https://api.twilio.com/2010-04-01/Accounts/</property> + </component> + <component x="570" y="390" name="text10" title=" '{propval}'" color="orange1"> + <implementation.python script="nuvem/text.py"/> + <service name="text"/> + <property>SMS/Messages</property> + </component> + <component x="580" y="480" name="text11" title=" '{propval}'" color="orange1"> + <implementation.python script="nuvem/text.py"/> + <service name="text"/> + <property>+14155992671</property> + </component> + <component x="550" y="450" name="text12" title=" '{propval}'" color="orange1"> + <implementation.python script="nuvem/text.py"/> + <service name="text"/> + <property>From={0}&To={1}&Body={2}</property> + </component> + <component x="700" y="340" name="text13" title=" '{propval}'" color="orange1"> + <implementation.python script="nuvem/text.py"/> + <service name="text"/> + <property>+16508632924</property> + </component> + <component x="690" y="370" name="text14" title=" '{propval}'" color="orange1"> + <implementation.python script="nuvem/text.py"/> + <service name="text"/> + <property>This is a text message</property> + </component> + <component x="710" y="290" name="text15" title=" '{propval}'" color="orange1"> + <implementation.python script="nuvem/text.py"/> + <service name="text"/> + <property>application/x-www-form-urlencoded</property> + </component> <component name="text2" title=" '{propval}'" color="orange1"> <implementation.python script="nuvem/text.py"/> <service name="text"/> diff --git a/sca-cpp/trunk/modules/edit/palettes/http/palette.composite b/sca-cpp/trunk/modules/edit/palettes/http/palette.composite index 6b518f0a35..6dcfb9eb43 100644 --- a/sca-cpp/trunk/modules/edit/palettes/http/palette.composite +++ b/sca-cpp/trunk/modules/edit/palettes/http/palette.composite @@ -7,22 +7,23 @@ <service name="keychain" promote="keychain"/> <service name="param" promote="param"/> <service name="params" promote="params"/> + <service name="patch" promote="patch"/> <service name="path" promote="path"/> <service name="post" promote="post"/> <service name="put" promote="put"/> <service name="url" promote="url"/> <service name="user" promote="user"/> - <component x="180" y="230" name="delete" title="delete" color="green1"> + <component x="90" y="240" name="delete" title="delete" color="green1"> <implementation.cpp path="lib/http" library="libhttpdelete"/> <service name="delete"/> <reference name="url"/> </component> - <component x="160" y="110" name="email" title="email" color="green1"> + <component x="250" y="60" name="email" title="email" color="green1"> <implementation.python script="nuvem/email.py"/> <service name="email"/> <property name="email" visible="false"/> </component> - <component x="150" y="160" name="get" title="get" color="green1"> + <component x="90" y="170" name="get" title="get" color="green1"> <implementation.cpp path="lib/http" library="libhttpget"/> <service name="get"/> <reference name="url"/> @@ -32,47 +33,53 @@ <service name="host"/> <property name="host" visible="false"/> </component> - <component x="230" y="110" name="keychain" title="keychain" color="green1"> + <component x="90" y="110" name="keychain" title="keychain" color="green1"> <implementation.python script="nuvem/keychain.py"/> <service name="keychain"/> <reference name="name"/> <reference name="account" target="Accounts" visible="false"/> </component> - <component x="180" y="60" name="param" title="?param" color="green1"> + <component x="90" y="60" name="param" title="?param" color="green1"> <implementation.python script="nuvem/param.py"/> <service name="param"/> <property>x</property> <property name="query" visible="false"/> </component> - <component x="90" y="60" name="params" title="?params" color="green1"> + <component x="230" y="10" name="params" title="?params" color="green1"> <implementation.python script="nuvem/params.py"/> <service name="params"/> <property name="query" visible="false"/> </component> + <component x="170" y="240" name="patch" title="patch" color="green1"> + <implementation.cpp path="lib/http" library="libhttppatch"/> + <service name="patch"/> + <reference name="url"/> + <reference name="content"/> + </component> <component x="160" y="10" name="path" title="path" color="green1"> <implementation.python script="nuvem/path.py"/> <service name="path"/> <property name="path" visible="false"/> </component> - <component x="90" y="230" name="post" title="post **" color="green1"> + <component x="230" y="170" name="post" title="post" color="green1"> <implementation.cpp path="lib/http" library="libhttppost"/> <service name="post"/> <reference name="url"/> <reference name="content"/> </component> - <component x="220" y="160" name="put" title="put **" color="green1"> + <component x="160" y="170" name="put" title="put" color="green1"> <implementation.cpp path="lib/http" library="libhttpput"/> <service name="put"/> <reference name="url"/> <reference name="content"/> </component> - <component x="90" y="160" name="url" title="url" color="green1"> + <component x="190" y="110" name="url" title="url" color="green1"> <implementation.python script="nuvem/url.py"/> <service name="url"/> <reference name="address"/> <reference name="args"/> </component> - <component x="90" y="110" name="user" title="user" color="green1"> + <component x="180" y="60" name="user" title="user" color="green1"> <implementation.python script="nuvem/user.py"/> <service name="user"/> <property name="user" visible="false"/> diff --git a/sca-cpp/trunk/modules/http/http.hpp b/sca-cpp/trunk/modules/http/http.hpp index d4159add29..5cf174f4e1 100644 --- a/sca-cpp/trunk/modules/http/http.hpp +++ b/sca-cpp/trunk/modules/http/http.hpp @@ -44,6 +44,7 @@ #include "element.hpp" #include "monad.hpp" #include "parallel.hpp" +#include "../scheme/io.hpp" #include "../atom/atom.hpp" #include "../rss/rss.hpp" #include "../json/json.hpp" @@ -187,6 +188,13 @@ const string escapeArg(const string& arg) { } /** + * Return true if a URI is absolute. + */ +const bool isAbsolute(const string& uri) { + return contains(uri, "://"); +} + +/** * Parse a URI and return its host name. */ const string hostName(const string& uri, const gc_pool& p) { @@ -200,6 +208,19 @@ const string hostName(const string& uri, const gc_pool& p) { } /** + * Parse a URI and return its scheme. + */ +const string scheme(const string& uri, const gc_pool& p) { + apr_uri_t u; + const apr_status_t rc = apr_uri_parse(pool(p), c_str(uri), &u); + if (rc != APR_SUCCESS) + return ""; + if (u.scheme == NULL) + return ""; + return u.scheme; +} + +/** * Return the first subdomain name in a host name. */ const string subDomain(const string& host) { @@ -223,6 +244,9 @@ const failable<CURL*> setup(const string& url, const CURLSession& cs) { CURL* ch = handle(cs); curl_easy_reset(ch); curl_easy_setopt(ch, CURLOPT_USERAGENT, "libcurl/1.0"); +#ifdef WANT_MAINTAINER_MODE + curl_easy_setopt(ch, CURLOPT_VERBOSE, true); +#endif // Setup protocol options curl_easy_setopt(ch, CURLOPT_TCP_NODELAY, true); @@ -252,6 +276,29 @@ const failable<CURL*> setup(const string& url, const CURLSession& cs) { curl_easy_setopt(ch, CURLOPT_COOKIE, c_str(cs.cookie)); } + // Set up HTTP basic auth if requested + apr_uri_t u; + apr_pool_t* p = gc_current_pool(); + const apr_status_t prc = apr_uri_parse(p, c_str(url), &u); + if (prc == APR_SUCCESS) { + if (u.user != NULL) { + debug(u.user, "http::setup::user"); + curl_easy_setopt(ch, CURLOPT_USERNAME, u.user); + } + if (u.password != NULL) { + debug(u.password, "http::setup::pass"); + curl_easy_setopt(ch, CURLOPT_PASSWORD, u.password); + } + if (u.user != NULL || u.password != NULL) { + curl_easy_setopt(ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC); + + // Set target URL, omitting the user:password part + curl_easy_setopt(ch, CURLOPT_URL, c_str(escapeURI(apr_uri_unparse(p, &u, APR_URI_UNP_OMITUSERINFO)))); + + return ch; + } + } + // Set target URL curl_easy_setopt(ch, CURLOPT_URL, c_str(escapeURI(url))); @@ -353,6 +400,10 @@ template<typename R> const failable<list<R> > apply(const list<list<string> >& h } else if (verb == "PUT") { curl_easy_setopt(ch, CURLOPT_UPLOAD, true); curl_easy_setopt(ch, CURLOPT_INFILESIZE, sz); + } else if (verb == "PATCH") { + curl_easy_setopt(ch, CURLOPT_UPLOAD, true); + curl_easy_setopt(ch, CURLOPT_CUSTOMREQUEST, "PATCH"); + 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); @@ -424,9 +475,9 @@ const failable<string> location(const list<string>& h) { /** * Convert a location to an entry id. */ -const failable<value> entryId(const failable<string> l) { +const value entryId(const failable<string> l) { if (!hasContent(l)) - return mkfailure<value>(reason(l)); + return list<value>(); const string ls(content(l)); return value(mklist<value>(string(substr(ls, find_last(ls, '/') + 1)))); } @@ -536,26 +587,107 @@ const failable<value> get(const string& url, const CURLSession& cs) { } /** + * Form an HTTP content request. + */ +const failable<list<list<string> > > writeRequest(const failable<list<string> >& ls, const string& ct) { + if (!hasContent(ls)) + return mkfailure<list<list<string> > >(reason(ls)); + const list<list<string> > req = mklist<list<string> >(mklist<string>(string("Content-Type: ") + ct), content(ls)); + debug(req, "http::writeRequest::req"); + return req; +} + +/** + * Convert a value to an HTTP content request. + */ +const failable<list<list<string> > > contentRequest(const value& c, unused const string& url) { + + // Check if the client requested a specific format + //TODO derive that from given URL + const list<value> fmt = assoc<value>("format", list<value>()); + + // Write as a scheme value if requested by the client + if (!isNil(fmt) && cadr(fmt) == "scheme") + return writeRequest(mklist<string>(scheme::writeValue(c)), "text/plain; charset=utf-8"); + + // Write a simple value as a JSON value + if (!isList(c)) { + js::JSContext cx; + if (isSymbol(c)) { + const list<value> lc = mklist<value>(mklist<value>("name", value(string(c)))); + debug(lc, "http::contentRequest::symbol"); + return writeRequest(json::writeJSON(valuesToElements(lc), cx), "application/json; charset=utf-8"); + } + const list<value> lc = mklist<value>(mklist<value>("value", c)); + debug(lc, "http::contentRequest::value"); + return writeRequest(json::writeJSON(valuesToElements(lc), cx), "application/json; charset=utf-8"); + } + + // Write an empty list as a JSON empty value + if (isNil((list<value>)c)) { + js::JSContext cx; + debug(list<value>(), "http::contentRequest::empty"); + return writeRequest(json::writeJSON(list<value>(), cx), "application/json; charset=utf-8"); + } + + // Write content-type / content-list pair + if (isString(car<value>(c)) && !isNil(cdr<value>(c)) && isList(cadr<value>(c))) + return writeRequest(convertValues<string>(cadr<value>(c)), car<value>(c)); + + // Write an assoc value as a JSON result + if (isSymbol(car<value>(c)) && !isNil(cdr<value>(c))) { + js::JSContext cx; + const list<value> lc = mklist<value>(c); + debug(lc, "http::contentRequest::assoc"); + debug(valuesToElements(lc), "http::contentRequest::assoc::element"); + return writeRequest(json::writeJSON(valuesToElements(lc), cx), "application/json; charset=utf-8"); + } + + // Write value as JSON if requested by the client + if (!isNil(fmt) && cadr(fmt) == "json") { + js::JSContext cx; + return writeRequest(json::writeJSON(valuesToElements(c), cx), "application/json; charset=utf-8"); + } + + // Convert list of values to element values + const list<value> e = valuesToElements(c); + debug(e, "http::contentRequest::elements"); + + // Write an ATOM feed or entry + if (isList(car<value>(e)) && !isNil(car<value>(e))) { + const list<value> el = car<value>(e); + if (isSymbol(car<value>(el)) && car<value>(el) == element && !isNil(cdr<value>(el)) && isSymbol(cadr<value>(el)) && elementHasChildren(el) && !elementHasValue(el)) { + if (cadr<value>(el) == atom::feed) + return writeRequest(atom::writeATOMFeed(e), "application/atom+xml; charset=utf-8"); + if (cadr<value>(el) == atom::entry) + return writeRequest(atom::writeATOMEntry(e), "application/atom+xml; charset=utf-8"); + } + } + + // Write any other compound value as a JSON value + js::JSContext cx; + return writeRequest(json::writeJSON(e, cx), "application/json; charset=utf-8"); +} + +/** * HTTP POST. */ const failable<value> post(const value& val, const string& url, const CURLSession& cs) { - - // Convert value to an ATOM entry - const failable<list<string> > entry = atom::writeATOMEntry(valuesToElements(val)); - if (!hasContent(entry)) - return mkfailure<value>(reason(entry)); debug(url, "http::post::url"); - debug(content(entry), "http::post::input"); + + // Convert value to a content request + const failable<list<list<string> > > req = contentRequest(val, url); + if (!hasContent(req)) + return mkfailure<value>(reason(req)); + debug(content(req), "http::post::input"); // POST it to the URL - const list<string> h = mklist<string>("Content-Type: application/atom+xml"); - const list<list<string> > req = mklist<list<string> >(h, content(entry)); - const failable<list<list<string> > > res = apply<list<string>>(req, rcons<string>, list<string>(), url, "POST", cs); + const failable<list<list<string> > > res = apply<list<string>>(content(req), rcons<string>, list<string>(), url, "POST", cs); if (!hasContent(res)) return mkfailure<value>(reason(res)); - // Return the new entry id from the HTTP location header - const failable<value> eid(entryId(location(car(content(res))))); + // Return the new entry id from the HTTP location header, if any + const value eid(entryId(location(car(content(res))))); debug(eid, "http::post::result"); return eid; } @@ -564,18 +696,16 @@ const failable<value> post(const value& val, const string& url, const CURLSessio * HTTP PUT. */ const failable<value> put(const value& val, const string& url, const CURLSession& cs) { - - // Convert value to an ATOM entry - const failable<list<string> > entry = atom::writeATOMEntry(valuesToElements(val)); - if (!hasContent(entry)) - return mkfailure<value>(reason(entry)); debug(url, "http::put::url"); - debug(content(entry), "http::put::input"); + + // Convert value to a content request + const failable<list<list<string> > > req = contentRequest(val, url); + if (!hasContent(req)) + return mkfailure<value>(reason(req)); + debug(content(req), "http::put::input"); // PUT it to the URL - const list<string> h = mklist<string>("Content-Type: application/atom+xml"); - const list<list<string> > req = mklist<list<string> >(h, content(entry)); - const failable<list<list<string> > > res = apply<list<string> >(req, rcons<string>, list<string>(), url, "PUT", cs); + const failable<list<list<string> > > res = apply<list<string> >(content(req), rcons<string>, list<string>(), url, "PUT", cs); if (!hasContent(res)) return mkfailure<value>(reason(res)); @@ -584,6 +714,27 @@ const failable<value> put(const value& val, const string& url, const CURLSession } /** + * HTTP PATCH. + */ +const failable<value> patch(const value& val, const string& url, const CURLSession& cs) { + debug(url, "http::put::patch"); + + // Convert value to a content request + const failable<list<list<string> > > req = contentRequest(val, url); + if (!hasContent(req)) + return mkfailure<value>(reason(req)); + debug(content(req), "http::patch::input"); + + // PATCH it to the URL + const failable<list<list<string> > > res = apply<list<string> >(content(req), rcons<string>, list<string>(), url, "PATCH", cs); + if (!hasContent(res)) + return mkfailure<value>(reason(res)); + + debug(true, "http::patch::result"); + return value(true); +} + +/** * HTTP DELETE. */ const failable<value, string> del(const string& url, const CURLSession& cs) { @@ -778,6 +929,10 @@ struct proxy { const failable<value> val = put(caddr(args), uri + path(cadr(args)), cs); return content(val); } + if (fun == "patch") { + const failable<value> val = patch(caddr(args), uri + path(cadr(args)), cs); + return content(val); + } if (fun == "delete") { const failable<value> val = del(uri + path(cadr(args)), cs); return content(val); diff --git a/sca-cpp/trunk/modules/http/httpd.hpp b/sca-cpp/trunk/modules/http/httpd.hpp index 534fd78503..9440fe343e 100644 --- a/sca-cpp/trunk/modules/http/httpd.hpp +++ b/sca-cpp/trunk/modules/http/httpd.hpp @@ -152,13 +152,6 @@ 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") { @@ -173,6 +166,20 @@ const string scheme(request_rec* r, const string& def = "http") { } /** + * Return the port number for a server. + */ +const int port(const server_rec* s, const int def = 80) { + return s->port != 0? s->port : def; +} + +/** + * Return the port number from an HTTP request. + */ +const int port(request_rec* r, const int def = 80) { + return r->server->port != 0? r->server->port : def; +} + +/** * Return the content type of a request. */ const string contentType(const request_rec* r) { diff --git a/sca-cpp/trunk/modules/server/mod-eval.hpp b/sca-cpp/trunk/modules/server/mod-eval.hpp index 30d45baac4..b9b11e06dc 100644 --- a/sca-cpp/trunk/modules/server/mod-eval.hpp +++ b/sca-cpp/trunk/modules/server/mod-eval.hpp @@ -389,12 +389,22 @@ public: debug(uri, "modeval::implProxy::wiredByImpl::uri"); debug(aparams, "modeval::implProxy::wiredByImpl::input"); - // Use an HTTP proxy if the target is an absolute http:// target - if (httpd::isAbsolute(uri)) { + // Use an HTTP proxy if the target is an absolute :// target + if (http::isAbsolute(uri)) { gc_pool p(currentRequest->pool); + + // Interpret a uri in the form app://appname, convert it using the scheme, + // top level domain and port number from the current request + if (http::scheme(uri, p) == "app") { + 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)); + return px(aparams); + } // Pass our certificate and the cookie from the current request - // if the target is in the same domain + // 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)); @@ -474,7 +484,7 @@ const value mkrefProxy(const ServerConf& sc, const value& ref, unused const stri return mkimplProxy(sc, value()); if (isNil(target)) return mkunwiredProxy(scdl::name(ref)); - if (httpd::isAbsolute(target)) + if (http::isAbsolute(target)) return mkhttpProxy(sc, target); return mkimplProxy(sc, car(pathValues(target))); } diff --git a/sca-cpp/trunk/modules/server/mod-wiring.cpp b/sca-cpp/trunk/modules/server/mod-wiring.cpp index b1a8047525..e56cee1d8c 100644 --- a/sca-cpp/trunk/modules/server/mod-wiring.cpp +++ b/sca-cpp/trunk/modules/server/mod-wiring.cpp @@ -106,11 +106,10 @@ int translateReference(const ServerConf& sc, request_rec *r) { // Route to an absolute target URI using mod_proxy or an HTTP client redirect const list<value> pathInfo = cdddr(rpath); - if (httpd::isAbsolute(target)) { + if (http::isAbsolute(target)) { if (useModProxy) { // Build proxy URI - // current request's protocol scheme, reference target uri and request path info - string turi = httpd::scheme(r) + substr(target, find(target, "://")) + path(pathInfo) + (r->args != NULL? string("?") + r->args : string("")); + string turi = target + path(pathInfo) + (r->args != NULL? string("?") + r->args : string("")); r->filename = apr_pstrdup(r->pool, c_str(string("proxy:") + turi)); debug(r->filename, "modwiring::translateReference::filename"); r->proxyreq = PROXYREQ_REVERSE; |