From 7c018c6fb691b65ac1cb181a95f5766e2933eb3c Mon Sep 17 00:00:00 2001 From: jsdelfino Date: Sat, 26 Feb 2011 20:59:35 +0000 Subject: Correctly pass query strings through component wiring redirects and improve format of XML and JSON response documents. git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@1074924 13f79535-47bb-0310-9956-ffa450edef68 --- sca-cpp/trunk/components/webservice/axiom-test.cpp | 6 +- sca-cpp/trunk/kernel/value.hpp | 2 +- sca-cpp/trunk/kernel/xml.hpp | 1 + sca-cpp/trunk/modules/atom/atom-test.cpp | 142 +++++++++++---------- sca-cpp/trunk/modules/http/http.hpp | 41 +++++- sca-cpp/trunk/modules/http/httpd.hpp | 18 --- sca-cpp/trunk/modules/http/openauth.hpp | 2 +- sca-cpp/trunk/modules/js/htdocs/xmlutil.js | 5 +- sca-cpp/trunk/modules/json/json-test.cpp | 138 +++++++++++++++++--- sca-cpp/trunk/modules/json/json.hpp | 2 +- sca-cpp/trunk/modules/oauth/mod-oauth1.cpp | 8 +- sca-cpp/trunk/modules/oauth/mod-oauth2.cpp | 10 +- sca-cpp/trunk/modules/rss/rss-test.cpp | 138 ++++++++++---------- sca-cpp/trunk/modules/scdl/scdl-test.cpp | 2 +- sca-cpp/trunk/modules/server/htdocs/test/entry.xml | 14 +- sca-cpp/trunk/modules/server/htdocs/test/feed.xml | 44 ++++++- .../modules/server/htdocs/test/json-properties.txt | 14 +- .../modules/server/htdocs/test/json-result.txt | 5 +- sca-cpp/trunk/modules/server/mod-eval.hpp | 79 ++++++++---- sca-cpp/trunk/modules/server/mod-wiring.cpp | 4 +- .../samples/store-cpp/htdocs/test/items-result.txt | 23 +++- .../store-python/htdocs/test/items-result.txt | 23 +++- 22 files changed, 500 insertions(+), 221 deletions(-) (limited to 'sca-cpp') diff --git a/sca-cpp/trunk/components/webservice/axiom-test.cpp b/sca-cpp/trunk/components/webservice/axiom-test.cpp index a3ab8e7e8f..75ce2452fd 100644 --- a/sca-cpp/trunk/components/webservice/axiom-test.cpp +++ b/sca-cpp/trunk/components/webservice/axiom-test.cpp @@ -45,6 +45,10 @@ const string customerElement = "45673000" ""; +const string echo("\n" + " Hello World!\n" + ""); + bool testAxiom() { const Axis2Context ax; { @@ -63,7 +67,7 @@ bool testAxiom() { assert(hasContent(n)); const failable x = axiomNodeToString(content(n), ax); assert(hasContent(x)); - assert(content(x) == "Hello World!"); + assert(content(x) == echo); const failable > l = axiomNodeToValues(content(n), ax); assert(hasContent(l)); assert(l == arg); diff --git a/sca-cpp/trunk/kernel/value.hpp b/sca-cpp/trunk/kernel/value.hpp index 211873ef0c..07be7f5c82 100644 --- a/sca-cpp/trunk/kernel/value.hpp +++ b/sca-cpp/trunk/kernel/value.hpp @@ -240,7 +240,7 @@ public: return true; switch(type) { case value::Undefined: - return true; + return v.type == value::Undefined; case value::List: return v.type == value::List && lst()() == v.lst()(); case value::Lambda: diff --git a/sca-cpp/trunk/kernel/xml.hpp b/sca-cpp/trunk/kernel/xml.hpp index 3459592c97..97c9effcc2 100644 --- a/sca-cpp/trunk/kernel/xml.hpp +++ b/sca-cpp/trunk/kernel/xml.hpp @@ -347,6 +347,7 @@ template const failable writeXML(const lambda("xmlNewTextWriter failed"); + xmlTextWriterSetIndent(xml, 1); const failable w = write(l, xml, xmlTag); xmlFreeTextWriter(xml); diff --git a/sca-cpp/trunk/modules/atom/atom-test.cpp b/sca-cpp/trunk/modules/atom/atom-test.cpp index 762331d528..5503c0f9b4 100644 --- a/sca-cpp/trunk/modules/atom/atom-test.cpp +++ b/sca-cpp/trunk/modules/atom/atom-test.cpp @@ -36,52 +36,56 @@ ostream* writer(const string& s, ostream* os) { return os; } -string itemEntry("\n" - "" - "item" - "cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b" - "" - "" - "Apple$2.99" - "" - "" - "" +const string itemEntry( + "\n" + "\n" + " item\n" + " cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b\n" + " \n" + " \n" + " Apple\n" + " $2.99\n" + " \n" + " \n" + " \n" "\n"); -string itemTextEntry("\n" - "" - "item" - "cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b" - "Apple" - "" +const string itemTextEntry("\n" + "\n" + " item\n" + " cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b\n" + " Apple\n" + " \n" "\n"); -string itemNoContentEntry("\n" - "" - "item" - "cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b" - "" +const string itemNoContentEntry("\n" + "\n" + " item\n" + " cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b\n" + " \n" "\n"); -string incompleteEntry("" - "item" - "" - "Orange" - "3.55" - "" - "" - ""); - -string completedEntry("\n" - "" - "item" - "" - "" - "" - "Orange" - "3.55" - "" - "" +const string incompleteEntry("\n" + " item\n" + " \n" + " \n" + " Orange\n" + " 3.55\n" + " \n" + " \n" + "\n"); + +const string completedEntry("\n" + "\n" + " item\n" + " \n" + " \n" + " \n" + " Orange\n" + " 3.55\n" + " \n" + " \n" + " \n" "\n"); bool testEntry() { @@ -133,36 +137,38 @@ bool testEntry() { return true; } -string emptyFeed("\n" - "" - "Feed" - "1234" +const string emptyFeed("\n" + "\n" + " Feed\n" + " 1234\n" "\n"); -string itemFeed("\n" - "" - "Feed" - "1234" - "" - "item" - "cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b" - "" - "" - "Apple$2.99" - "" - "" - "" - "" - "" - "item" - "cart-53d67a61-aa5e-4e5e-8401-39edeba8b83c" - "" - "" - "Orange$3.55" - "" - "" - "" - "" +const string itemFeed("\n" + "\n" + " Feed\n" + " 1234\n" + " \n" + " item\n" + " cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b\n" + " \n" + " \n" + " Apple\n" + " $2.99\n" + " \n" + " \n" + " \n" + " \n" + " \n" + " item\n" + " cart-53d67a61-aa5e-4e5e-8401-39edeba8b83c\n" + " \n" + " \n" + " Orange\n" + " $3.55\n" + " \n" + " \n" + " \n" + " \n" "\n"); bool testFeed() { diff --git a/sca-cpp/trunk/modules/http/http.hpp b/sca-cpp/trunk/modules/http/http.hpp index 26a2e0cf0c..e2327be40a 100644 --- a/sca-cpp/trunk/modules/http/http.hpp +++ b/sca-cpp/trunk/modules/http/http.hpp @@ -620,6 +620,39 @@ const failable recv(char* c, const size_t l, const CURLSession& cs) { return recv(c, l, cs); } + +/** + * Filter path segment in a list of arguments. + */ +const bool filterPath(const value& arg) { + return isString(arg); +} + +/** + * Filter query string arguments in a list of arguments. + */ +const bool filterQuery(const value& arg) { + return isList(arg); +} + +/** + * Converts a list of key value pairs to a query string. + */ +ostringstream& queryString(const list > args, ostringstream& os) { + if (isNil(args)) + return os; + debug(car(args), "http::queryString::arg"); + os << car(car(args)) << "=" << c_str(cadr(car(args))); + if (!isNil(cdr(args))) + os << "&"; + return queryString(cdr(args), os); +} + +const string queryString(const list > args) { + ostringstream os; + return str(queryString(args, os)); +} + /** * HTTP client proxy function. */ @@ -630,7 +663,13 @@ struct proxy { const value operator()(const list& args) const { const value fun = car(args); if (fun == "get") { - const failable val = get(uri + path(cadr(args)), cs); + const list lp = filter(filterPath, cadr(args)); + debug(lp, "http::queryString::arg"); + const list lq = filter(filterQuery, cadr(args)); + debug(lq, "http::get::query"); + const value p = path(lp); + const value q = queryString(lq); + const failable val = get(uri + p + (q != ""? string("?") + q : string("")), cs); return content(val); } if (fun == "post") { diff --git a/sca-cpp/trunk/modules/http/httpd.hpp b/sca-cpp/trunk/modules/http/httpd.hpp index b6756c51e3..768537aa03 100644 --- a/sca-cpp/trunk/modules/http/httpd.hpp +++ b/sca-cpp/trunk/modules/http/httpd.hpp @@ -282,24 +282,6 @@ const list > queryArgs(const request_rec* r) { return queryArgs(r->args); } -/** - * Converts a list of key value pairs to a query string. - */ -ostringstream& queryString(const list > args, ostringstream& os) { - if (isNil(args)) - return os; - debug(car(args), "httpd::queryString::arg"); - os << car(car(args)) << "=" << c_str(cadr(car(args))); - if (!isNil(cdr(args))) - os << "&"; - return queryString(cdr(args), os); -} - -const string queryString(const list > args) { - ostringstream os; - return str(queryString(args, os)); -} - /** * Converts the args received in a POST to a list of key value pairs. */ diff --git a/sca-cpp/trunk/modules/http/openauth.hpp b/sca-cpp/trunk/modules/http/openauth.hpp index ff69a9732f..9023848305 100644 --- a/sca-cpp/trunk/modules/http/openauth.hpp +++ b/sca-cpp/trunk/modules/http/openauth.hpp @@ -87,7 +87,7 @@ const string cookie(const string& sid) { */ const failable login(const string& page, request_rec* r) { const list > largs = mklist >(mklist("openauth_referrer", httpd::escape(httpd::url(r->uri, r)))); - const string loc = httpd::url(page, r) + string("?") + httpd::queryString(largs); + const string loc = httpd::url(page, r) + string("?") + http::queryString(largs); debug(loc, "openauth::login::uri"); return httpd::externalRedirect(loc, r); } diff --git a/sca-cpp/trunk/modules/js/htdocs/xmlutil.js b/sca-cpp/trunk/modules/js/htdocs/xmlutil.js index b3fb34435a..3965596599 100644 --- a/sca-cpp/trunk/modules/js/htdocs/xmlutil.js +++ b/sca-cpp/trunk/modules/js/htdocs/xmlutil.js @@ -61,7 +61,10 @@ function childElements(e) { * Return the child text nodes of an element. */ function childText(e) { - return filter(function(n) { return n.nodeType == 3; }, nodeList(e.childNodes)); + function trim(s) { + return s.replace(/^\s*/, '').replace(/\s*$/, ''); + } + return filter(function(n) { return n.nodeType == 3 && trim(n.nodeValue) != ''; }, nodeList(e.childNodes)); } /** diff --git a/sca-cpp/trunk/modules/json/json-test.cpp b/sca-cpp/trunk/modules/json/json-test.cpp index 6666b3f479..eed41c4e59 100644 --- a/sca-cpp/trunk/modules/json/json-test.cpp +++ b/sca-cpp/trunk/modules/json/json-test.cpp @@ -36,6 +36,35 @@ ostream* jsonWriter(const string& s, ostream* os) { return os; } +const string jscustomer("{\n" + " \"customer\":{\n" + " \"@name\":\"jdoe\",\n" + " \"address\":{\n" + " \"@city\":\"san francisco\",\n" + " \"@state\":\"ca\"\n" + " },\n" + " \"account\":{\n" + " \"id\":\"1234\",\n" + " \"@balance\":1000\n" + " }\n" + " }\n" + "}"); + +const string jsphones("{\n" + " \"phones\":[\"408-1234\",\n" + " \"650-1234\"\n" + " ],\n" + " \"lastName\":\"test\\u0009tab\",\n" + " \"@firstName\":\"test1\"\n" + "}"); + +const string jsecho("{\n" + " \"ns1:echoString\":{\n" + " \"@xmlns:ns1\":\"http://ws.apache.org/axis2/services/echo\",\n" + " \"text\":\"Hello World!\"\n" + " }\n" + "}"); + bool testJSON() { const js::JSContext cx; @@ -47,7 +76,7 @@ bool testJSON() { ostringstream os; writeJSON(jsonWriter, &os, c, cx); - assert(str(os) == "{\"customer\":{\"@name\":\"jdoe\",\"address\":{\"@city\":\"san francisco\",\"@state\":\"ca\"},\"account\":{\"id\":\"1234\",\"@balance\":1000}}}"); + assert(str(os) == jscustomer); } { const list phones = mklist (string("408-1234"), string("650-1234")); @@ -55,7 +84,7 @@ bool testJSON() { ostringstream os; writeJSON(jsonWriter, &os, l, cx); - assert(str(os) == "{\"phones\":[\"408-1234\",\"650-1234\"],\"lastName\":\"test\\u0009tab\",\"@firstName\":\"test1\"}"); + assert(str(os) == jsphones); istringstream is(str(os)); const list il = streamList(is); @@ -70,7 +99,7 @@ bool testJSON() { const list l = mklist(list() + "ns1:echoString" + (list() + "@xmlns:ns1" + string("http://ws.apache.org/axis2/services/echo")) + (list() + "text" + string("Hello World!"))); ostringstream wos; write(content(writeJSON(valuesToElements(l), cx)), wos); - assert(str(wos) == "{\"ns1:echoString\":{\"@xmlns:ns1\":\"http://ws.apache.org/axis2/services/echo\",\"text\":\"Hello World!\"}}"); + assert(str(wos) == jsecho); istringstream is(str(wos)); const list il = streamList(is); @@ -80,6 +109,86 @@ bool testJSON() { return true; } +const string jsitem("{\n" + " \"id\":3,\n" + " \"result\":[{\n" + " \"price\":\"$2.99\",\n" + " \"name\":\"Apple\"\n" + " },\n" + " {\n" + " \"price\":\"$3.55\",\n" + " \"name\":\"Orange\"\n" + " },\n" + " {\n" + " \"price\":\"$1.55\",\n" + " \"name\":\"Pear\"\n" + " }\n" + " ]\n" + "}"); + +const string jsresult("{\n" + " \"id\":1,\n" + " \"result\":[\"Service.get\",\n" + " \"Service.getTotal\"\n" + " ]\n" + "}"); + +const string jsfeed("{\n" + " \"id\":1,\n" + " \"result\":[\"Sample Feed\",\n" + " \"123456789\",\n" + " [\"Item\",\n" + " \"111\",\n" + " {\n" + " \"name\":\"Apple\",\n" + " \"currencyCode\":\"USD\",\n" + " \"currencySymbol\":\"$\",\n" + " \"price\":2.99\n" + " }\n" + " ],\n" + " [\"Item\",\n" + " \"222\",\n" + " {\n" + " \"name\":\"Orange\",\n" + " \"currencyCode\":\"USD\",\n" + " \"currencySymbol\":\"$\",\n" + " \"price\":3.55\n" + " }\n" + " ],\n" + " [\"Item\",\n" + " \"333\",\n" + " {\n" + " \"name\":\"Pear\",\n" + " \"currencyCode\":\"USD\",\n" + " \"currencySymbol\":\"$\",\n" + " \"price\":1.55\n" + " }\n" + " ]\n" + " ]\n" + "}"); + +const string jsechoreq("{\n" + " \"id\":1,\n" + " \"method\":\"echo\",\n" + " \"params\":[{\n" + " \"ns1:echoString\":{\n" + " \"@xmlns:ns1\":\"http://ws.apache.org/axis2/services/echo\",\n" + " \"text\":\"Hello World!\"\n" + " }\n" + " }\n" + " ]\n" + "}"); + +const string jsechores("{\n" + " \"id\":1,\n" + " \"result\":{\n" + " \"ns1:echoString\":{\n" + " \"@xmlns:ns1\":\"http://ws.apache.org/axis2/c/samples\",\n" + " \"text\":\"Hello World!\"\n" + " }\n" + " }\n" + "}"); + bool testJSONRPC() { js::JSContext cx; { @@ -91,18 +200,16 @@ bool testJSONRPC() { assert(assoc("params", v) == mklist("params", list())); } { - const string i("{\"id\":3,\"result\":[{\"price\":\"$2.99\",\"name\":\"Apple\"},{\"price\":\"$3.55\",\"name\":\"Orange\"},{\"price\":\"$1.55\",\"name\":\"Pear\"}]}"); - const list e = content(readJSON(mklist(i), cx)); - const string i2("{\"id\":3,\"result\":{\"0\":{\"price\":\"$2.99\",\"name\":\"Apple\"},\"1\":{\"price\":\"$3.55\",\"name\":\"Orange\"},\"2\":{\"price\":\"$1.55\",\"name\":\"Pear\"}}}"); - const list e2 = content(readJSON(mklist(i), cx)); + const string i2 = "{\"id\":3,\"result\":{\"0\":{\"price\":\"$2.99\",\"name\":\"Apple\"},\"1\":{\"price\":\"$3.55\",\"name\":\"Orange\"},\"2\":{\"price\":\"$1.55\",\"name\":\"Pear\"}}}"; + const list e = content(readJSON(mklist(jsitem), cx)); + const list e2 = content(readJSON(mklist(i2), cx)); assert(e == e2); } { - const string i("{\"id\":3,\"result\":[{\"price\":\"$2.99\",\"name\":\"Apple\"},{\"price\":\"$3.55\",\"name\":\"Orange\"},{\"price\":\"$1.55\",\"name\":\"Pear\"}]}"); - const list e = content(readJSON(mklist(i), cx)); + const list e = content(readJSON(mklist(jsitem), cx)); ostringstream os; write(content(writeJSON(e, cx)), os); - assert(str(os) == i); + assert(str(os) == jsitem); const list v = elementsToValues(e); const list r = valuesToElements(v); assert(r == e); @@ -112,23 +219,22 @@ bool testJSONRPC() { const list e = valuesToElements(r); ostringstream os; write(content(writeJSON(e, cx)), os); - assert(str(os) == "{\"id\":1,\"result\":[\"Service.get\",\"Service.getTotal\"]}"); + assert(str(os) == jsresult); } { - const string f("{\"id\":1,\"result\":[\"Sample Feed\",\"123456789\",[\"Item\",\"111\",{\"name\":\"Apple\",\"currencyCode\":\"USD\",\"currencySymbol\":\"$\",\"price\":2.99}],[\"Item\",\"222\",{\"name\":\"Orange\",\"currencyCode\":\"USD\",\"currencySymbol\":\"$\",\"price\":3.55}],[\"Item\",\"333\",{\"name\":\"Pear\",\"currencyCode\":\"USD\",\"currencySymbol\":\"$\",\"price\":1.55}]]}"); - const list r = content(readJSON(mklist(f), cx)); + const list r = content(readJSON(mklist(jsfeed), cx)); const list v = elementsToValues(r); const list e = valuesToElements(v); ostringstream os; write(content(writeJSON(e, cx)), os); - assert(str(os) == f); + assert(str(os) == jsfeed); } { const list arg = mklist(list() + "ns1:echoString" + (list() + "@xmlns:ns1" + string("http://ws.apache.org/axis2/services/echo")) + (list() + "text" + string("Hello World!"))); const failable > r = jsonRequest(1, "echo", mklist(arg), cx); ostringstream os; write(content(r), os); - assert(str(os) == "{\"id\":1,\"method\":\"echo\",\"params\":[{\"ns1:echoString\":{\"@xmlns:ns1\":\"http://ws.apache.org/axis2/services/echo\",\"text\":\"Hello World!\"}}]}"); + assert(str(os) == jsechoreq); istringstream is(str(os)); const list il = streamList(is); @@ -140,7 +246,7 @@ bool testJSONRPC() { const failable > r = jsonResult(1, res, cx); ostringstream os; write(content(r), os); - assert(str(os) == "{\"id\":1,\"result\":{\"ns1:echoString\":{\"@xmlns:ns1\":\"http://ws.apache.org/axis2/c/samples\",\"text\":\"Hello World!\"}}}"); + assert(str(os) == jsechores); istringstream is(str(os)); const list il = streamList(is); diff --git a/sca-cpp/trunk/modules/json/json.hpp b/sca-cpp/trunk/modules/json/json.hpp index df82fddbb5..f35c04208e 100644 --- a/sca-cpp/trunk/modules/json/json.hpp +++ b/sca-cpp/trunk/modules/json/json.hpp @@ -110,7 +110,7 @@ template const failable writeJSON(const lambda wcx(reduce, initial, cx); - if (!JS_Stringify(cx, &val, NULL, JSVAL_NULL, writeCallback, &wcx)) + if (!JS_Stringify(cx, &val, NULL, INT_TO_JSVAL(1), writeCallback, &wcx)) return mkfailure("JS_Stringify failed"); return wcx.accum; } diff --git a/sca-cpp/trunk/modules/oauth/mod-oauth1.cpp b/sca-cpp/trunk/modules/oauth/mod-oauth1.cpp index 84de8f2d05..acf39601b3 100644 --- a/sca-cpp/trunk/modules/oauth/mod-oauth1.cpp +++ b/sca-cpp/trunk/modules/oauth/mod-oauth1.cpp @@ -193,7 +193,7 @@ const failable authorize(const list >& args, request_rec* r, co // Build the redirect URI const list > redirargs = mklist >(mklist("mod_oauth1_step", "access_token"), tok, cid, info); - const string redir = httpd::url(r->uri, r) + string("?") + httpd::queryString(redirargs); + const string redir = httpd::url(r->uri, r) + string("?") + http::queryString(redirargs); debug(redir, "modoauth1::authorize::redir"); // Lookup client app configuration @@ -203,7 +203,7 @@ const failable authorize(const list >& args, request_rec* r, co list appkey = cadr(app); // Build and sign the request token URI - const string requri = httpd::unescape(cadr(req)) + string("&") + httpd::queryString(mklist >(mklist("oauth_callback", httpd::escape(redir)))); + const string requri = httpd::unescape(cadr(req)) + string("&") + http::queryString(mklist >(mklist("oauth_callback", httpd::escape(redir)))); const list srequri = sign("POST", requri, appkey, "", ""); debug(srequri, "modoauth1::authorize::srequri"); @@ -236,7 +236,7 @@ const failable authorize(const list >& args, request_rec* r, co return mkfailure(reason(prc)); // Redirect to the authorize URI - const string authuri = httpd::unescape(cadr(auth)) + string("?") + httpd::queryString(mklist >(tv)); + const string authuri = httpd::unescape(cadr(auth)) + string("?") + http::queryString(mklist >(tv)); debug(authuri, "modoauth1::authorize::authuri"); return httpd::externalRedirect(authuri, r); } @@ -325,7 +325,7 @@ const failable access_token(const list >& args, request_rec* r, return mkfailure(reason(sv)); // Build and sign access token request URI - const string tokuri = httpd::unescape(cadr(tok)) + string("?") + httpd::queryString(mklist >(vv)); + const string tokuri = httpd::unescape(cadr(tok)) + string("?") + http::queryString(mklist >(vv)); const list stokuri = sign("POST", tokuri, appkey, cadr(tv), content(sv)); debug(stokuri, "modoauth1::access_token::stokuri"); diff --git a/sca-cpp/trunk/modules/oauth/mod-oauth2.cpp b/sca-cpp/trunk/modules/oauth/mod-oauth2.cpp index 51bd240177..a662333c9e 100644 --- a/sca-cpp/trunk/modules/oauth/mod-oauth2.cpp +++ b/sca-cpp/trunk/modules/oauth/mod-oauth2.cpp @@ -141,7 +141,7 @@ const failable authorize(const list >& args, request_rec* r, co // Build the redirect URI const list > rargs = mklist >(mklist("mod_oauth2_step", "access_token"), tok, cid, info); - const string redir = httpd::url(r->uri, r) + string("?") + httpd::queryString(rargs); + const string redir = httpd::url(r->uri, r) + string("?") + http::queryString(rargs); debug(redir, "modoauth2::authorize::redir"); // Lookup client app configuration @@ -152,7 +152,7 @@ const failable authorize(const list >& args, request_rec* r, co // Redirect to the authorize URI const list > aargs = mklist >(mklist("client_id", car(appkey)), mklist("scope", "email"), mklist("redirect_uri", httpd::escape(redir))); - const string uri = httpd::unescape(cadr(auth)) + string("?") + httpd::queryString(aargs); + const string uri = httpd::unescape(cadr(auth)) + string("?") + http::queryString(aargs); debug(uri, "modoauth2::authorize::uri"); return httpd::externalRedirect(uri, r); } @@ -192,12 +192,12 @@ const failable access_token(const list >& args, request_rec* r, // Build the redirect URI const list > rargs = mklist >(mklist("mod_oauth2_step", "access_token"), tok, cid, info); - const string redir = httpd::url(r->uri, r) + string("?") + httpd::queryString(rargs); + const string redir = httpd::url(r->uri, r) + string("?") + http::queryString(rargs); debug(redir, "modoauth2::access_token::redir"); // Request access token const list > targs = mklist >(mklist("client_id", car(appkey)), mklist("redirect_uri", httpd::escape(redir)), mklist("client_secret", cadr(appkey)), code); - const string turi = httpd::unescape(cadr(tok)) + string("?") + httpd::queryString(targs); + const string turi = httpd::unescape(cadr(tok)) + string("?") + http::queryString(targs); debug(turi, "modoauth2::access_token::tokenuri"); const failable tr = http::get(turi, sc.cs); if (!hasContent(tr)) @@ -211,7 +211,7 @@ const failable access_token(const list >& args, request_rec* r, // Request user info // TODO Make this step configurable const list > iargs = mklist >(tv); - const string iuri = httpd::unescape(cadr(info)) + string("?") + httpd::queryString(iargs); + const string iuri = httpd::unescape(cadr(info)) + string("?") + http::queryString(iargs); debug(iuri, "modoauth2::access_token::infouri"); const failable profres = http::get(iuri, sc.cs); if (!hasContent(profres)) diff --git a/sca-cpp/trunk/modules/rss/rss-test.cpp b/sca-cpp/trunk/modules/rss/rss-test.cpp index 0b773ba31e..c2c3eb9e8f 100644 --- a/sca-cpp/trunk/modules/rss/rss-test.cpp +++ b/sca-cpp/trunk/modules/rss/rss-test.cpp @@ -36,49 +36,51 @@ ostream* writer(const string& s, ostream* os) { return os; } -string itemEntry("\n" - "" - "fruit" - "cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b" - "" - "" - "Apple$2.99" - "" - "" +const string itemEntry("\n" + "\n" + " fruit\n" + " cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b\n" + " \n" + " \n" + " Apple\n" + " $2.99\n" + " \n" + " \n" "\n"); -string itemTextEntry("\n" - "" - "fruit" - "cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b" - "Apple" +const string itemTextEntry("\n" + "\n" + " fruit\n" + " cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b\n" + " Apple\n" "\n"); -string itemNoDescriptionEntry("\n" - "" - "fruit" - "cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b" +const string itemNoDescriptionEntry("\n" + "\n" + " fruit\n" + " cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b\n" "\n"); -string incompleteEntry("" - "fruit" - "" - "Orange" - "3.55" - "" - "" +const string incompleteEntry("\n" + " fruit\n" + " \n" + " \n" + " Orange\n" + " 3.55\n" + " \n" + " \n" ""); -string completedEntry("\n" - "" - "fruit" - "" - "" - "" - "Orange" - "3.55" - "" - "" +const string completedEntry("\n" + "\n" + " fruit\n" + " \n" + " \n" + " \n" + " Orange\n" + " 3.55\n" + " \n" + " \n" "\n"); bool testEntry() { @@ -130,40 +132,42 @@ bool testEntry() { return true; } -string emptyFeed("\n" - "" - "" - "Feed" - "1234" - "Feed" - "" +const string emptyFeed("\n" + "\n" + " \n" + " Feed\n" + " 1234\n" + " Feed\n" + " \n" "\n"); -string itemFeed("\n" - "" - "" - "Feed" - "1234" - "Feed" - "" - "fruit" - "cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b" - "" - "" - "Apple$2.99" - "" - "" - "" - "" - "fruit" - "cart-53d67a61-aa5e-4e5e-8401-39edeba8b83c" - "" - "" - "Orange$3.55" - "" - "" - "" - "" +const string itemFeed("\n" + "\n" + " \n" + " Feed\n" + " 1234\n" + " Feed\n" + " \n" + " fruit\n" + " cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b\n" + " \n" + " \n" + " Apple\n" + " $2.99\n" + " \n" + " \n" + " \n" + " \n" + " fruit\n" + " cart-53d67a61-aa5e-4e5e-8401-39edeba8b83c\n" + " \n" + " \n" + " Orange\n" + " $3.55\n" + " \n" + " \n" + " \n" + " \n" "\n"); bool testFeed() { diff --git a/sca-cpp/trunk/modules/scdl/scdl-test.cpp b/sca-cpp/trunk/modules/scdl/scdl-test.cpp index e8ee77eb4e..09a3dcd5dd 100644 --- a/sca-cpp/trunk/modules/scdl/scdl-test.cpp +++ b/sca-cpp/trunk/modules/scdl/scdl-test.cpp @@ -47,8 +47,8 @@ bool testComponents() { const value store = car(c); assert(name(store) == string("Store")); const value impl = implementation(store); - assert(uri(impl) == string("store.html")); assert(implementationType(impl) == "t:implementation.scheme"); + assert(attributeValue("script", impl) == string("store.scm")); const value catalog = named(string("Catalog"), c); assert(name(catalog) == string("Catalog")); diff --git a/sca-cpp/trunk/modules/server/htdocs/test/entry.xml b/sca-cpp/trunk/modules/server/htdocs/test/entry.xml index 6528c793e3..46053c3138 100644 --- a/sca-cpp/trunk/modules/server/htdocs/test/entry.xml +++ b/sca-cpp/trunk/modules/server/htdocs/test/entry.xml @@ -1,2 +1,14 @@ -Item111AppleUSD$2.99 + + Item + 111 + + + Apple + USD + $ + 2.99 + + + + diff --git a/sca-cpp/trunk/modules/server/htdocs/test/feed.xml b/sca-cpp/trunk/modules/server/htdocs/test/feed.xml index bcb304f9c2..337320e4c5 100644 --- a/sca-cpp/trunk/modules/server/htdocs/test/feed.xml +++ b/sca-cpp/trunk/modules/server/htdocs/test/feed.xml @@ -1,2 +1,44 @@ -Sample Feed123456789Item111AppleUSD$2.99Item222OrangeUSD$3.55Item333PearUSD$1.55 + + Sample Feed + 123456789 + + Item + 111 + + + Apple + USD + $ + 2.99 + + + + + + Item + 222 + + + Orange + USD + $ + 3.55 + + + + + + Item + 333 + + + Pear + USD + $ + 1.55 + + + + + diff --git a/sca-cpp/trunk/modules/server/htdocs/test/json-properties.txt b/sca-cpp/trunk/modules/server/htdocs/test/json-properties.txt index 70f0139ea0..75843bc286 100644 --- a/sca-cpp/trunk/modules/server/htdocs/test/json-properties.txt +++ b/sca-cpp/trunk/modules/server/htdocs/test/json-properties.txt @@ -1 +1,13 @@ -{"id":"1","result":{"host":"localhost","path":["components","property-test"],"query":{"id":"1","method":"print"}}} \ No newline at end of file +{ + "id":"1", + "result":{ + "host":"localhost", + "path":["components", + "property-test" + ], + "query":{ + "id":"1", + "method":"print" + } + } +} \ No newline at end of file diff --git a/sca-cpp/trunk/modules/server/htdocs/test/json-result.txt b/sca-cpp/trunk/modules/server/htdocs/test/json-result.txt index 121bf74902..38aa8a2a5e 100644 --- a/sca-cpp/trunk/modules/server/htdocs/test/json-result.txt +++ b/sca-cpp/trunk/modules/server/htdocs/test/json-result.txt @@ -1 +1,4 @@ -{"id":1,"result":"Hello"} \ No newline at end of file +{ + "id":1, + "result":"Hello" +} \ No newline at end of file diff --git a/sca-cpp/trunk/modules/server/mod-eval.hpp b/sca-cpp/trunk/modules/server/mod-eval.hpp index 64ab6df4bb..8047015cbc 100644 --- a/sca-cpp/trunk/modules/server/mod-eval.hpp +++ b/sca-cpp/trunk/modules/server/mod-eval.hpp @@ -125,24 +125,43 @@ const failable get(request_rec* r, const lambda&)>& // Evaluate the GET expression const list path(pathValues(r->uri)); - const failable val = failableResult(impl(cons("get", mklist(cddr(path))))); + const list params(append(cddr(path), mkvalues(args))); + const failable val = failableResult(impl(cons("get", mklist(params)))); if (!hasContent(val)) return mkfailure(reason(val)); const value c = content(val); + // Write a simple value as a JSON value + if (!isList(c)) { + js::JSContext cx; + return httpd::writeResult(json::writeJSON(valuesToElements(mklist(mklist("value", c))), cx), "application/json", r); + } + + // Write an empty list as a JSON empty value + if (isNil(c)) { + js::JSContext cx; + return httpd::writeResult(json::writeJSON(list(), cx), "application/json", r); + } + + // Write an assoc value as a JSON result + if (isSymbol(car(c)) && !isNil(cdr(c))) { + js::JSContext cx; + return httpd::writeResult(json::writeJSON(valuesToElements(mklist(c)), cx), "application/json", r); + } + // Write content-type / content-list pair - if (isString(car(c)) && isList(cadr(c))) + if (isString(car(c)) && !isNil(cdr(c)) && isList(cadr(c))) return httpd::writeResult(convertValues(cadr(c)), car(c), r); - // Write ATOM feed or entry - if (isString(car(c)) && isString(cadr(c))) { + // Write an ATOM feed or entry + if (isString(car(c)) && !isNil(cdr(c)) && isString(cadr(c))) { if (isNil(cddr(path))) return httpd::writeResult(atom::writeATOMFeed(atom::feedValuesToElements(c)), "application/atom+xml", r); else return httpd::writeResult(atom::writeATOMEntry(atom::entryValuesToElements(c)), "application/atom+xml", r); } - // Write JSON value + // Write any other compound value as a JSON value js::JSContext cx; return httpd::writeResult(json::writeJSON(valuesToElements(c), cx), "application/json", r); } @@ -419,27 +438,29 @@ struct userPropProxy { }; const value mkpropProxy(const value& prop) { - if (scdl::name(prop) == "host") - return lambda&)>(hostPropProxy(elementValue(prop))); - if (scdl::name(prop) == "path") - return lambda&)>(pathPropProxy(elementValue(prop))); - if (scdl::name(prop) == "query") - return lambda&)>(queryPropProxy(elementValue(prop))); - if (scdl::name(prop) == "user") - return lambda&)>(userPropProxy(elementValue(prop))); - if (scdl::name(prop) == "realm") - return lambda&)>(envPropProxy("REALM", elementValue(prop))); - if (scdl::name(prop) == "email") - return lambda&)>(envPropProxy("EMAIL", elementValue(prop))); - if (scdl::name(prop) == "nickname") - return lambda&)>(envPropProxy("NICKNAME", elementValue(prop))); - if (scdl::name(prop) == "fullname") - return lambda&)>(envPropProxy("FULLNAME", elementValue(prop))); - if (scdl::name(prop) == "firstname") - return lambda&)>(envPropProxy("FIRSTNAME", elementValue(prop))); - if (scdl::name(prop) == "lastname") - return lambda&)>(envPropProxy("LASTNAME", elementValue(prop))); - return lambda&)>(propProxy(elementValue(prop))); + const value n = scdl::name(prop); + const value v = elementHasValue(prop)? elementValue(prop):value(string("")); + if (n == "host") + return lambda&)>(hostPropProxy(v)); + if (n == "path") + return lambda&)>(pathPropProxy(v)); + if (n == "query") + return lambda&)>(queryPropProxy(v)); + if (n == "user") + return lambda&)>(userPropProxy(v)); + if (n == "realm") + return lambda&)>(envPropProxy("REALM", v)); + if (n == "email") + return lambda&)>(envPropProxy("EMAIL", v)); + if (n == "nickname") + return lambda&)>(envPropProxy("NICKNAME", v)); + if (n == "fullname") + return lambda&)>(envPropProxy("FULLNAME", v)); + if (n == "firstname") + return lambda&)>(envPropProxy("FIRSTNAME", v)); + if (n == "lastname") + return lambda&)>(envPropProxy("LASTNAME", v)); + return lambda&)>(propProxy(v)); } const list propProxies(const list& props) { @@ -675,8 +696,10 @@ int handler(request_rec *r) { // Get the component implementation lambda const list path(pathValues(r->uri)); const list impl(assoctree(cadr(path), usevh? vhc.vsc.implTree : sc.implTree)); - if (isNil(impl)) - return httpd::reportStatus(mkfailure(string("Couldn't find component implementation: ") + cadr(path))); + if (isNil(impl)) { + mkfailure(string("Couldn't find component implementation: ") + cadr(path)); + return HTTP_NOT_FOUND; + } // Handle HTTP method const lambda&)> l(cadr(impl)); diff --git a/sca-cpp/trunk/modules/server/mod-wiring.cpp b/sca-cpp/trunk/modules/server/mod-wiring.cpp index b63cd3fb37..ac9e621177 100644 --- a/sca-cpp/trunk/modules/server/mod-wiring.cpp +++ b/sca-cpp/trunk/modules/server/mod-wiring.cpp @@ -107,7 +107,7 @@ int translateReference(const ServerConf& sc, request_rec *r) { 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); + string turi = httpd::scheme(r) + substr(target, find(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; @@ -124,7 +124,7 @@ int translateReference(const ServerConf& sc, request_rec *r) { // Route to a relative target URI using a local internal redirect // /components/, target component name and request path info const value tname = substr(target, 0, find(target, '/')); - const string tpath = path(cons(tname, pathInfo)); + const string tpath = path(cons(tname, pathInfo)) + (r->args != NULL? string("?") + r->args : string("")); r->filename = apr_pstrdup(r->pool, c_str(string("/redirect:/components") + tpath)); debug(r->filename, "modwiring::translateReference::filename"); r->handler = "mod_tuscany_wiring"; diff --git a/sca-cpp/trunk/samples/store-cpp/htdocs/test/items-result.txt b/sca-cpp/trunk/samples/store-cpp/htdocs/test/items-result.txt index 56f87d2778..676ded6242 100644 --- a/sca-cpp/trunk/samples/store-cpp/htdocs/test/items-result.txt +++ b/sca-cpp/trunk/samples/store-cpp/htdocs/test/items-result.txt @@ -1 +1,22 @@ -{"id":1,"result":[{"name":"Apple","currencyCode":"USD","currencySymbol":"$","price":2.99},{"name":"Orange","currencyCode":"USD","currencySymbol":"$","price":3.55},{"name":"Pear","currencyCode":"USD","currencySymbol":"$","price":1.55}]} \ No newline at end of file +{ + "id":1, + "result":[{ + "name":"Apple", + "currencyCode":"USD", + "currencySymbol":"$", + "price":2.99 + }, + { + "name":"Orange", + "currencyCode":"USD", + "currencySymbol":"$", + "price":3.55 + }, + { + "name":"Pear", + "currencyCode":"USD", + "currencySymbol":"$", + "price":1.55 + } + ] +} \ No newline at end of file diff --git a/sca-cpp/trunk/samples/store-python/htdocs/test/items-result.txt b/sca-cpp/trunk/samples/store-python/htdocs/test/items-result.txt index 788b7cdf89..5e498c948a 100644 --- a/sca-cpp/trunk/samples/store-python/htdocs/test/items-result.txt +++ b/sca-cpp/trunk/samples/store-python/htdocs/test/items-result.txt @@ -1 +1,22 @@ -{"id":1,"result":[{"name":"Mango","currencyCode":"USD","currencySymbol":"$","price":2.99},{"name":"Passion","currencyCode":"USD","currencySymbol":"$","price":3.55},{"name":"Kiwi","currencyCode":"USD","currencySymbol":"$","price":1.55}]} \ No newline at end of file +{ + "id":1, + "result":[{ + "name":"Mango", + "currencyCode":"USD", + "currencySymbol":"$", + "price":2.99 + }, + { + "name":"Passion", + "currencyCode":"USD", + "currencySymbol":"$", + "price":3.55 + }, + { + "name":"Kiwi", + "currencyCode":"USD", + "currencySymbol":"$", + "price":1.55 + } + ] +} \ No newline at end of file -- cgit v1.2.3