summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjsdelfino <jsdelfino@13f79535-47bb-0310-9956-ffa450edef68>2011-02-26 20:59:35 +0000
committerjsdelfino <jsdelfino@13f79535-47bb-0310-9956-ffa450edef68>2011-02-26 20:59:35 +0000
commit7c018c6fb691b65ac1cb181a95f5766e2933eb3c (patch)
treeb12eb4fd6fc05faebd9d481f1d57599cd0b2829e
parent0ee21c5d9657a1259a731722f53666ad135279bb (diff)
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
-rw-r--r--sca-cpp/trunk/components/webservice/axiom-test.cpp6
-rw-r--r--sca-cpp/trunk/kernel/value.hpp2
-rw-r--r--sca-cpp/trunk/kernel/xml.hpp1
-rw-r--r--sca-cpp/trunk/modules/atom/atom-test.cpp142
-rw-r--r--sca-cpp/trunk/modules/http/http.hpp41
-rw-r--r--sca-cpp/trunk/modules/http/httpd.hpp18
-rw-r--r--sca-cpp/trunk/modules/http/openauth.hpp2
-rw-r--r--sca-cpp/trunk/modules/js/htdocs/xmlutil.js5
-rw-r--r--sca-cpp/trunk/modules/json/json-test.cpp138
-rw-r--r--sca-cpp/trunk/modules/json/json.hpp2
-rw-r--r--sca-cpp/trunk/modules/oauth/mod-oauth1.cpp8
-rw-r--r--sca-cpp/trunk/modules/oauth/mod-oauth2.cpp10
-rw-r--r--sca-cpp/trunk/modules/rss/rss-test.cpp138
-rw-r--r--sca-cpp/trunk/modules/scdl/scdl-test.cpp2
-rw-r--r--sca-cpp/trunk/modules/server/htdocs/test/entry.xml14
-rw-r--r--sca-cpp/trunk/modules/server/htdocs/test/feed.xml44
-rw-r--r--sca-cpp/trunk/modules/server/htdocs/test/json-properties.txt14
-rw-r--r--sca-cpp/trunk/modules/server/htdocs/test/json-result.txt5
-rw-r--r--sca-cpp/trunk/modules/server/mod-eval.hpp79
-rw-r--r--sca-cpp/trunk/modules/server/mod-wiring.cpp4
-rw-r--r--sca-cpp/trunk/samples/store-cpp/htdocs/test/items-result.txt23
-rw-r--r--sca-cpp/trunk/samples/store-python/htdocs/test/items-result.txt23
22 files changed, 500 insertions, 221 deletions
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 =
"<account><id>4567</id><balance>3000</balance></account>"
"</customer>";
+const string echo("<ns1:echoString xmlns:ns1=\"http://ws.apache.org/axis2/services/echo\">\n"
+ " <text>Hello World!</text>\n"
+ "</ns1:echoString>");
+
bool testAxiom() {
const Axis2Context ax;
{
@@ -63,7 +67,7 @@ bool testAxiom() {
assert(hasContent(n));
const failable<const string> x = axiomNodeToString(content(n), ax);
assert(hasContent(x));
- assert(content(x) == "<ns1:echoString xmlns:ns1=\"http://ws.apache.org/axis2/services/echo\"><text>Hello World!</text></ns1:echoString>");
+ assert(content(x) == echo);
const failable<const list<value> > 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<typename R> const failable<R> writeXML(const lambda<R(const string&, co
xmlTextWriterPtr xml = xmlNewTextWriter(out);
if (xml == NULL)
return mkfailure<R>("xmlNewTextWriter failed");
+ xmlTextWriterSetIndent(xml, 1);
const failable<bool> 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("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
- "<entry xmlns=\"http://www.w3.org/2005/Atom\">"
- "<title type=\"text\">item</title>"
- "<id>cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b</id>"
- "<content type=\"application/xml\">"
- "<item>"
- "<name>Apple</name><price>$2.99</price>"
- "</item>"
- "</content>"
- "<link href=\"cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b\"/>"
+const string itemEntry(
+ "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+ "<entry xmlns=\"http://www.w3.org/2005/Atom\">\n"
+ " <title type=\"text\">item</title>\n"
+ " <id>cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b</id>\n"
+ " <content type=\"application/xml\">\n"
+ " <item>\n"
+ " <name>Apple</name>\n"
+ " <price>$2.99</price>\n"
+ " </item>\n"
+ " </content>\n"
+ " <link href=\"cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b\"/>\n"
"</entry>\n");
-string itemTextEntry("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
- "<entry xmlns=\"http://www.w3.org/2005/Atom\">"
- "<title type=\"text\">item</title>"
- "<id>cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b</id>"
- "<content type=\"text\">Apple</content>"
- "<link href=\"cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b\"/>"
+const string itemTextEntry("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+ "<entry xmlns=\"http://www.w3.org/2005/Atom\">\n"
+ " <title type=\"text\">item</title>\n"
+ " <id>cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b</id>\n"
+ " <content type=\"text\">Apple</content>\n"
+ " <link href=\"cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b\"/>\n"
"</entry>\n");
-string itemNoContentEntry("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
- "<entry xmlns=\"http://www.w3.org/2005/Atom\">"
- "<title type=\"text\">item</title>"
- "<id>cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b</id>"
- "<link href=\"cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b\"/>"
+const string itemNoContentEntry("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+ "<entry xmlns=\"http://www.w3.org/2005/Atom\">\n"
+ " <title type=\"text\">item</title>\n"
+ " <id>cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b</id>\n"
+ " <link href=\"cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b\"/>\n"
"</entry>\n");
-string incompleteEntry("<entry xmlns=\"http://www.w3.org/2005/Atom\">"
- "<title>item</title><content type=\"text/xml\">"
- "<Item xmlns=\"http://services/\">"
- "<name xmlns=\"\">Orange</name>"
- "<price xmlns=\"\">3.55</price>"
- "</Item>"
- "</content>"
- "</entry>");
-
-string completedEntry("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
- "<entry xmlns=\"http://www.w3.org/2005/Atom\">"
- "<title type=\"text\">item</title>"
- "<id></id>"
- "<content type=\"application/xml\">"
- "<Item xmlns=\"http://services/\">"
- "<name xmlns=\"\">Orange</name>"
- "<price xmlns=\"\">3.55</price>"
- "</Item>"
- "</content><link href=\"\"/>"
+const string incompleteEntry("<entry xmlns=\"http://www.w3.org/2005/Atom\">\n"
+ " <title>item</title>\n"
+ " <content type=\"text/xml\">\n"
+ " <Item xmlns=\"http://services/\">\n"
+ " <name xmlns=\"\">Orange</name>\n"
+ " <price xmlns=\"\">3.55</price>\n"
+ " </Item>\n"
+ " </content>\n"
+ "</entry>\n");
+
+const string completedEntry("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+ "<entry xmlns=\"http://www.w3.org/2005/Atom\">\n"
+ " <title type=\"text\">item</title>\n"
+ " <id></id>\n"
+ " <content type=\"application/xml\">\n"
+ " <Item xmlns=\"http://services/\">\n"
+ " <name xmlns=\"\">Orange</name>\n"
+ " <price xmlns=\"\">3.55</price>\n"
+ " </Item>\n"
+ " </content>\n"
+ " <link href=\"\"/>\n"
"</entry>\n");
bool testEntry() {
@@ -133,36 +137,38 @@ bool testEntry() {
return true;
}
-string emptyFeed("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
- "<feed xmlns=\"http://www.w3.org/2005/Atom\">"
- "<title type=\"text\">Feed</title>"
- "<id>1234</id>"
+const string emptyFeed("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+ "<feed xmlns=\"http://www.w3.org/2005/Atom\">\n"
+ " <title type=\"text\">Feed</title>\n"
+ " <id>1234</id>\n"
"</feed>\n");
-string itemFeed("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
- "<feed xmlns=\"http://www.w3.org/2005/Atom\">"
- "<title type=\"text\">Feed</title>"
- "<id>1234</id>"
- "<entry xmlns=\"http://www.w3.org/2005/Atom\">"
- "<title type=\"text\">item</title>"
- "<id>cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b</id>"
- "<content type=\"application/xml\">"
- "<item>"
- "<name>Apple</name><price>$2.99</price>"
- "</item>"
- "</content>"
- "<link href=\"cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b\"/>"
- "</entry>"
- "<entry xmlns=\"http://www.w3.org/2005/Atom\">"
- "<title type=\"text\">item</title>"
- "<id>cart-53d67a61-aa5e-4e5e-8401-39edeba8b83c</id>"
- "<content type=\"application/xml\">"
- "<item>"
- "<name>Orange</name><price>$3.55</price>"
- "</item>"
- "</content>"
- "<link href=\"cart-53d67a61-aa5e-4e5e-8401-39edeba8b83c\"/>"
- "</entry>"
+const string itemFeed("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+ "<feed xmlns=\"http://www.w3.org/2005/Atom\">\n"
+ " <title type=\"text\">Feed</title>\n"
+ " <id>1234</id>\n"
+ " <entry xmlns=\"http://www.w3.org/2005/Atom\">\n"
+ " <title type=\"text\">item</title>\n"
+ " <id>cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b</id>\n"
+ " <content type=\"application/xml\">\n"
+ " <item>\n"
+ " <name>Apple</name>\n"
+ " <price>$2.99</price>\n"
+ " </item>\n"
+ " </content>\n"
+ " <link href=\"cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b\"/>\n"
+ " </entry>\n"
+ " <entry xmlns=\"http://www.w3.org/2005/Atom\">\n"
+ " <title type=\"text\">item</title>\n"
+ " <id>cart-53d67a61-aa5e-4e5e-8401-39edeba8b83c</id>\n"
+ " <content type=\"application/xml\">\n"
+ " <item>\n"
+ " <name>Orange</name>\n"
+ " <price>$3.55</price>\n"
+ " </item>\n"
+ " </content>\n"
+ " <link href=\"cart-53d67a61-aa5e-4e5e-8401-39edeba8b83c\"/>\n"
+ " </entry>\n"
"</feed>\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<size_t> 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<list<value> > 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<list<value> > args) {
+ ostringstream os;
+ return str(queryString(args, os));
+}
+
/**
* HTTP client proxy function.
*/
@@ -630,7 +663,13 @@ struct proxy {
const value operator()(const list<value>& args) const {
const value fun = car(args);
if (fun == "get") {
- const failable<value> val = get(uri + path(cadr(args)), cs);
+ const list<value> lp = filter<value>(filterPath, cadr(args));
+ debug(lp, "http::queryString::arg");
+ const list<value> lq = filter<value>(filterQuery, cadr(args));
+ debug(lq, "http::get::query");
+ const value p = path(lp);
+ const value q = queryString(lq);
+ const failable<value> 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
@@ -283,24 +283,6 @@ const list<list<value> > queryArgs(const request_rec* r) {
}
/**
- * Converts a list of key value pairs to a query string.
- */
-ostringstream& queryString(const list<list<value> > 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<list<value> > args) {
- ostringstream os;
- return str(queryString(args, os));
-}
-
-/**
* Converts the args received in a POST to a list of key value pairs.
*/
const list<list<value> > postArgs(const list<value>& a) {
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<int> login(const string& page, request_rec* r) {
const list<list<value> > largs = mklist<list<value> >(mklist<value>("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<ostream*>(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<value> phones = mklist<value> (string("408-1234"), string("650-1234"));
@@ -55,7 +84,7 @@ bool testJSON() {
ostringstream os;
writeJSON<ostream*>(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<string> il = streamList(is);
@@ -70,7 +99,7 @@ bool testJSON() {
const list<value> l = mklist<value>(list<value>() + "ns1:echoString" + (list<value>() + "@xmlns:ns1" + string("http://ws.apache.org/axis2/services/echo")) + (list<value>() + "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<string> 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<value>("params", v) == mklist<value>("params", list<value>()));
}
{
- const string i("{\"id\":3,\"result\":[{\"price\":\"$2.99\",\"name\":\"Apple\"},{\"price\":\"$3.55\",\"name\":\"Orange\"},{\"price\":\"$1.55\",\"name\":\"Pear\"}]}");
- const list<value> 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<value> 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<value> e = content(readJSON(mklist(jsitem), cx));
+ const list<value> 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<value> e = content(readJSON(mklist(i), cx));
+ const list<value> e = content(readJSON(mklist(jsitem), cx));
ostringstream os;
write(content(writeJSON(e, cx)), os);
- assert(str(os) == i);
+ assert(str(os) == jsitem);
const list<value> v = elementsToValues(e);
const list<value> r = valuesToElements(v);
assert(r == e);
@@ -112,23 +219,22 @@ bool testJSONRPC() {
const list<value> 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<value> r = content(readJSON(mklist(f), cx));
+ const list<value> r = content(readJSON(mklist(jsfeed), cx));
const list<value> v = elementsToValues(r);
const list<value> e = valuesToElements(v);
ostringstream os;
write(content(writeJSON(e, cx)), os);
- assert(str(os) == f);
+ assert(str(os) == jsfeed);
}
{
const list<value> arg = mklist<value>(list<value>() + "ns1:echoString" + (list<value>() + "@xmlns:ns1" + string("http://ws.apache.org/axis2/services/echo")) + (list<value>() + "text" + string("Hello World!")));
const failable<list<string> > r = jsonRequest(1, "echo", mklist<value>(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<string> il = streamList(is);
@@ -140,7 +246,7 @@ bool testJSONRPC() {
const failable<list<string> > 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<string> 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<typename R> const failable<R> writeJSON(const lambda<R(const string&, c
val = OBJECT_TO_JSVAL(valuesToJSProperties(JS_NewObject(cx, NULL, NULL, NULL), l, cx));
WriteContext<R> wcx(reduce, initial, cx);
- if (!JS_Stringify(cx, &val, NULL, JSVAL_NULL, writeCallback<R>, &wcx))
+ if (!JS_Stringify(cx, &val, NULL, INT_TO_JSVAL(1), writeCallback<R>, &wcx))
return mkfailure<R>("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<int> authorize(const list<list<value> >& args, request_rec* r, co
// Build the redirect URI
const list<list<value> > redirargs = mklist<list<value> >(mklist<value>("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<int> authorize(const list<list<value> >& args, request_rec* r, co
list<value> appkey = cadr(app);
// Build and sign the request token URI
- const string requri = httpd::unescape(cadr(req)) + string("&") + httpd::queryString(mklist<list<value> >(mklist<value>("oauth_callback", httpd::escape(redir))));
+ const string requri = httpd::unescape(cadr(req)) + string("&") + http::queryString(mklist<list<value> >(mklist<value>("oauth_callback", httpd::escape(redir))));
const list<string> srequri = sign("POST", requri, appkey, "", "");
debug(srequri, "modoauth1::authorize::srequri");
@@ -236,7 +236,7 @@ const failable<int> authorize(const list<list<value> >& args, request_rec* r, co
return mkfailure<int>(reason(prc));
// Redirect to the authorize URI
- const string authuri = httpd::unescape(cadr(auth)) + string("?") + httpd::queryString(mklist<list<value> >(tv));
+ const string authuri = httpd::unescape(cadr(auth)) + string("?") + http::queryString(mklist<list<value> >(tv));
debug(authuri, "modoauth1::authorize::authuri");
return httpd::externalRedirect(authuri, r);
}
@@ -325,7 +325,7 @@ const failable<int> access_token(const list<list<value> >& args, request_rec* r,
return mkfailure<int>(reason(sv));
// Build and sign access token request URI
- const string tokuri = httpd::unescape(cadr(tok)) + string("?") + httpd::queryString(mklist<list<value> >(vv));
+ const string tokuri = httpd::unescape(cadr(tok)) + string("?") + http::queryString(mklist<list<value> >(vv));
const list<string> 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<int> authorize(const list<list<value> >& args, request_rec* r, co
// Build the redirect URI
const list<list<value> > rargs = mklist<list<value> >(mklist<value>("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<int> authorize(const list<list<value> >& args, request_rec* r, co
// Redirect to the authorize URI
const list<list<value> > aargs = mklist<list<value> >(mklist<value>("client_id", car(appkey)), mklist<value>("scope", "email"), mklist<value>("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<int> access_token(const list<list<value> >& args, request_rec* r,
// Build the redirect URI
const list<list<value> > rargs = mklist<list<value> >(mklist<value>("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<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("?") + httpd::queryString(targs);
+ 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);
if (!hasContent(tr))
@@ -211,7 +211,7 @@ const failable<int> access_token(const list<list<value> >& args, request_rec* r,
// Request user info
// TODO Make this step configurable
const list<list<value> > iargs = mklist<list<value> >(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<value> 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("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
- "<item>"
- "<title>fruit</title>"
- "<link>cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b</link>"
- "<description>"
- "<item>"
- "<name>Apple</name><price>$2.99</price>"
- "</item>"
- "</description>"
+const string itemEntry("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+ "<item>\n"
+ " <title>fruit</title>\n"
+ " <link>cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b</link>\n"
+ " <description>\n"
+ " <item>\n"
+ " <name>Apple</name>\n"
+ " <price>$2.99</price>\n"
+ " </item>\n"
+ " </description>\n"
"</item>\n");
-string itemTextEntry("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
- "<item>"
- "<title>fruit</title>"
- "<link>cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b</link>"
- "<description>Apple</description>"
+const string itemTextEntry("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+ "<item>\n"
+ " <title>fruit</title>\n"
+ " <link>cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b</link>\n"
+ " <description>Apple</description>\n"
"</item>\n");
-string itemNoDescriptionEntry("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
- "<item>"
- "<title>fruit</title>"
- "<link>cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b</link>"
+const string itemNoDescriptionEntry("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+ "<item>\n"
+ " <title>fruit</title>\n"
+ " <link>cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b</link>\n"
"</item>\n");
-string incompleteEntry("<item>"
- "<title>fruit</title><description>"
- "<Item xmlns=\"http://services/\">"
- "<name xmlns=\"\">Orange</name>"
- "<price xmlns=\"\">3.55</price>"
- "</Item>"
- "</description>"
+const string incompleteEntry("<item>\n"
+ " <title>fruit</title>\n"
+ " <description>\n"
+ " <Item xmlns=\"http://services/\">\n"
+ " <name xmlns=\"\">Orange</name>\n"
+ " <price xmlns=\"\">3.55</price>\n"
+ " </Item>\n"
+ " </description>\n"
"</item>");
-string completedEntry("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
- "<item>"
- "<title>fruit</title>"
- "<link></link>"
- "<description>"
- "<Item xmlns=\"http://services/\">"
- "<name xmlns=\"\">Orange</name>"
- "<price xmlns=\"\">3.55</price>"
- "</Item>"
- "</description>"
+const string completedEntry("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+ "<item>\n"
+ " <title>fruit</title>\n"
+ " <link></link>\n"
+ " <description>\n"
+ " <Item xmlns=\"http://services/\">\n"
+ " <name xmlns=\"\">Orange</name>\n"
+ " <price xmlns=\"\">3.55</price>\n"
+ " </Item>\n"
+ " </description>\n"
"</item>\n");
bool testEntry() {
@@ -130,40 +132,42 @@ bool testEntry() {
return true;
}
-string emptyFeed("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
- "<rss version=\"2.0\">"
- "<channel>"
- "<title>Feed</title>"
- "<link>1234</link>"
- "<description>Feed</description>"
- "</channel>"
+const string emptyFeed("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+ "<rss version=\"2.0\">\n"
+ " <channel>\n"
+ " <title>Feed</title>\n"
+ " <link>1234</link>\n"
+ " <description>Feed</description>\n"
+ " </channel>\n"
"</rss>\n");
-string itemFeed("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
- "<rss version=\"2.0\">"
- "<channel>"
- "<title>Feed</title>"
- "<link>1234</link>"
- "<description>Feed</description>"
- "<item>"
- "<title>fruit</title>"
- "<link>cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b</link>"
- "<description>"
- "<item>"
- "<name>Apple</name><price>$2.99</price>"
- "</item>"
- "</description>"
- "</item>"
- "<item>"
- "<title>fruit</title>"
- "<link>cart-53d67a61-aa5e-4e5e-8401-39edeba8b83c</link>"
- "<description>"
- "<item>"
- "<name>Orange</name><price>$3.55</price>"
- "</item>"
- "</description>"
- "</item>"
- "</channel>"
+const string itemFeed("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+ "<rss version=\"2.0\">\n"
+ " <channel>\n"
+ " <title>Feed</title>\n"
+ " <link>1234</link>\n"
+ " <description>Feed</description>\n"
+ " <item>\n"
+ " <title>fruit</title>\n"
+ " <link>cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b</link>\n"
+ " <description>\n"
+ " <item>\n"
+ " <name>Apple</name>\n"
+ " <price>$2.99</price>\n"
+ " </item>\n"
+ " </description>\n"
+ " </item>\n"
+ " <item>\n"
+ " <title>fruit</title>\n"
+ " <link>cart-53d67a61-aa5e-4e5e-8401-39edeba8b83c</link>\n"
+ " <description>\n"
+ " <item>\n"
+ " <name>Orange</name>\n"
+ " <price>$3.55</price>\n"
+ " </item>\n"
+ " </description>\n"
+ " </item>\n"
+ " </channel>\n"
"</rss>\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 @@
<?xml version="1.0" encoding="UTF-8"?>
-<entry xmlns="http://www.w3.org/2005/Atom"><title type="text">Item</title><id>111</id><content type="application/xml"><item><name>Apple</name><currencyCode>USD</currencyCode><currencySymbol>$</currencySymbol><price>2.99</price></item></content><link href="111"/></entry>
+<entry xmlns="http://www.w3.org/2005/Atom">
+ <title type="text">Item</title>
+ <id>111</id>
+ <content type="application/xml">
+ <item>
+ <name>Apple</name>
+ <currencyCode>USD</currencyCode>
+ <currencySymbol>$</currencySymbol>
+ <price>2.99</price>
+ </item>
+ </content>
+ <link href="111"/>
+</entry>
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 @@
<?xml version="1.0" encoding="UTF-8"?>
-<feed xmlns="http://www.w3.org/2005/Atom"><title type="text">Sample Feed</title><id>123456789</id><entry xmlns="http://www.w3.org/2005/Atom"><title type="text">Item</title><id>111</id><content type="application/xml"><item><name>Apple</name><currencyCode>USD</currencyCode><currencySymbol>$</currencySymbol><price>2.99</price></item></content><link href="111"/></entry><entry xmlns="http://www.w3.org/2005/Atom"><title type="text">Item</title><id>222</id><content type="application/xml"><item><name>Orange</name><currencyCode>USD</currencyCode><currencySymbol>$</currencySymbol><price>3.55</price></item></content><link href="222"/></entry><entry xmlns="http://www.w3.org/2005/Atom"><title type="text">Item</title><id>333</id><content type="application/xml"><item><name>Pear</name><currencyCode>USD</currencyCode><currencySymbol>$</currencySymbol><price>1.55</price></item></content><link href="333"/></entry></feed>
+<feed xmlns="http://www.w3.org/2005/Atom">
+ <title type="text">Sample Feed</title>
+ <id>123456789</id>
+ <entry xmlns="http://www.w3.org/2005/Atom">
+ <title type="text">Item</title>
+ <id>111</id>
+ <content type="application/xml">
+ <item>
+ <name>Apple</name>
+ <currencyCode>USD</currencyCode>
+ <currencySymbol>$</currencySymbol>
+ <price>2.99</price>
+ </item>
+ </content>
+ <link href="111"/>
+ </entry>
+ <entry xmlns="http://www.w3.org/2005/Atom">
+ <title type="text">Item</title>
+ <id>222</id>
+ <content type="application/xml">
+ <item>
+ <name>Orange</name>
+ <currencyCode>USD</currencyCode>
+ <currencySymbol>$</currencySymbol>
+ <price>3.55</price>
+ </item>
+ </content>
+ <link href="222"/>
+ </entry>
+ <entry xmlns="http://www.w3.org/2005/Atom">
+ <title type="text">Item</title>
+ <id>333</id>
+ <content type="application/xml">
+ <item>
+ <name>Pear</name>
+ <currencyCode>USD</currencyCode>
+ <currencySymbol>$</currencySymbol>
+ <price>1.55</price>
+ </item>
+ </content>
+ <link href="333"/>
+ </entry>
+</feed>
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<int> get(request_rec* r, const lambda<value(const list<value>&)>&
// Evaluate the GET expression
const list<value> path(pathValues(r->uri));
- const failable<value> val = failableResult(impl(cons<value>("get", mklist<value>(cddr(path)))));
+ const list<value> params(append<value>(cddr(path), mkvalues(args)));
+ const failable<value> val = failableResult(impl(cons<value>("get", mklist<value>(params))));
if (!hasContent(val))
return mkfailure<int>(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<value>(mklist<value>("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<value>(), cx), "application/json", r);
+ }
+
+ // Write an assoc value as a JSON result
+ if (isSymbol(car<value>(c)) && !isNil(cdr<value>(c))) {
+ js::JSContext cx;
+ return httpd::writeResult(json::writeJSON(valuesToElements(mklist<value>(c)), cx), "application/json", r);
+ }
+
// Write content-type / content-list pair
- if (isString(car<value>(c)) && isList(cadr<value>(c)))
+ if (isString(car<value>(c)) && !isNil(cdr<value>(c)) && isList(cadr<value>(c)))
return httpd::writeResult(convertValues<string>(cadr<value>(c)), car<value>(c), r);
- // Write ATOM feed or entry
- if (isString(car<value>(c)) && isString(cadr<value>(c))) {
+ // Write an ATOM feed or entry
+ if (isString(car<value>(c)) && !isNil(cdr<value>(c)) && isString(cadr<value>(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<value(const list<value>&)>(hostPropProxy(elementValue(prop)));
- if (scdl::name(prop) == "path")
- return lambda<value(const list<value>&)>(pathPropProxy(elementValue(prop)));
- if (scdl::name(prop) == "query")
- return lambda<value(const list<value>&)>(queryPropProxy(elementValue(prop)));
- if (scdl::name(prop) == "user")
- return lambda<value(const list<value>&)>(userPropProxy(elementValue(prop)));
- if (scdl::name(prop) == "realm")
- return lambda<value(const list<value>&)>(envPropProxy("REALM", elementValue(prop)));
- if (scdl::name(prop) == "email")
- return lambda<value(const list<value>&)>(envPropProxy("EMAIL", elementValue(prop)));
- if (scdl::name(prop) == "nickname")
- return lambda<value(const list<value>&)>(envPropProxy("NICKNAME", elementValue(prop)));
- if (scdl::name(prop) == "fullname")
- return lambda<value(const list<value>&)>(envPropProxy("FULLNAME", elementValue(prop)));
- if (scdl::name(prop) == "firstname")
- return lambda<value(const list<value>&)>(envPropProxy("FIRSTNAME", elementValue(prop)));
- if (scdl::name(prop) == "lastname")
- return lambda<value(const list<value>&)>(envPropProxy("LASTNAME", elementValue(prop)));
- return lambda<value(const list<value>&)>(propProxy(elementValue(prop)));
+ const value n = scdl::name(prop);
+ const value v = elementHasValue(prop)? elementValue(prop):value(string(""));
+ if (n == "host")
+ return lambda<value(const list<value>&)>(hostPropProxy(v));
+ if (n == "path")
+ return lambda<value(const list<value>&)>(pathPropProxy(v));
+ if (n == "query")
+ return lambda<value(const list<value>&)>(queryPropProxy(v));
+ if (n == "user")
+ return lambda<value(const list<value>&)>(userPropProxy(v));
+ if (n == "realm")
+ return lambda<value(const list<value>&)>(envPropProxy("REALM", v));
+ if (n == "email")
+ return lambda<value(const list<value>&)>(envPropProxy("EMAIL", v));
+ if (n == "nickname")
+ return lambda<value(const list<value>&)>(envPropProxy("NICKNAME", v));
+ if (n == "fullname")
+ return lambda<value(const list<value>&)>(envPropProxy("FULLNAME", v));
+ if (n == "firstname")
+ return lambda<value(const list<value>&)>(envPropProxy("FIRSTNAME", v));
+ if (n == "lastname")
+ return lambda<value(const list<value>&)>(envPropProxy("LASTNAME", v));
+ return lambda<value(const list<value>&)>(propProxy(v));
}
const list<value> propProxies(const list<value>& props) {
@@ -675,8 +696,10 @@ int handler(request_rec *r) {
// Get the component implementation lambda
const list<value> path(pathValues(r->uri));
const list<value> impl(assoctree<value>(cadr(path), usevh? vhc.vsc.implTree : sc.implTree));
- if (isNil(impl))
- return httpd::reportStatus(mkfailure<int>(string("Couldn't find component implementation: ") + cadr(path)));
+ if (isNil(impl)) {
+ mkfailure<int>(string("Couldn't find component implementation: ") + cadr(path));
+ return HTTP_NOT_FOUND;
+ }
// Handle HTTP method
const lambda<value(const list<value>&)> l(cadr<value>(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