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
This commit is contained in:
parent
eb7ad1a024
commit
ba223e693c
18 changed files with 895 additions and 116 deletions
|
@ -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
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
23
sca-cpp/trunk/components/http/content-test.scm
Normal file
23
sca-cpp/trunk/components/http/content-test.scm
Normal file
|
@ -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)))))
|
||||
)
|
||||
|
|
@ -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>
|
||||
|
|
29
sca-cpp/trunk/components/http/httppatch.componentType
Normal file
29
sca-cpp/trunk/components/http/httppatch.componentType
Normal file
|
@ -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>
|
93
sca-cpp/trunk/components/http/httppatch.cpp
Normal file
93
sca-cpp/trunk/components/http/httppatch.cpp
Normal file
|
@ -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>();
|
||||
}
|
||||
|
||||
}
|
29
sca-cpp/trunk/components/http/httppost.componentType
Normal file
29
sca-cpp/trunk/components/http/httppost.componentType
Normal file
|
@ -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>
|
93
sca-cpp/trunk/components/http/httppost.cpp
Normal file
93
sca-cpp/trunk/components/http/httppost.cpp
Normal file
|
@ -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>();
|
||||
}
|
||||
|
||||
}
|
29
sca-cpp/trunk/components/http/httpput.componentType
Normal file
29
sca-cpp/trunk/components/http/httpput.componentType
Normal file
|
@ -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>
|
93
sca-cpp/trunk/components/http/httpput.cpp
Normal file
93
sca-cpp/trunk/components/http/httpput.cpp
Normal file
|
@ -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>();
|
||||
}
|
||||
|
||||
}
|
44
sca-cpp/trunk/components/http/server-test.scm
Normal file
44
sca-cpp/trunk/components/http/server-test.scm
Normal file
|
@ -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
|
||||
)
|
|
@ -18,6 +18,6 @@
|
|||
; URL test case
|
||||
|
||||
(define (get id)
|
||||
"http://localhost:8090/index.html"
|
||||
"http://localhost:8090/test"
|
||||
)
|
||||
|
||||
|
|
|
@ -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,41 +61,6 @@
|
|||
<service name="get"/>
|
||||
<reference target="text7" name="url"/>
|
||||
</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 name="list" title="list" color="yellow1">
|
||||
<implementation.python script="nuvem/list_.py"/>
|
||||
<service name="list"/>
|
||||
<reference target="item2" name="item" clonable="true"/>
|
||||
<reference target="item3" 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 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">
|
||||
<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">
|
||||
<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"/>
|
||||
|
@ -120,6 +73,95 @@
|
|||
<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"/>
|
||||
<reference target="item2" name="item" clonable="true"/>
|
||||
<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="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="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="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"/>
|
||||
|
|
|
@ -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"/>
|
||||
|
|
|
@ -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"
|
||||
|
@ -186,6 +187,13 @@ const string escapeArg(const string& arg) {
|
|||
return e;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if a URI is absolute.
|
||||
*/
|
||||
const bool isAbsolute(const string& uri) {
|
||||
return contains(uri, "://");
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a URI and return its host name.
|
||||
*/
|
||||
|
@ -199,6 +207,19 @@ const string hostName(const string& uri, const gc_pool& p) {
|
|||
return u.hostname;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
@ -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))));
|
||||
}
|
||||
|
@ -535,27 +586,108 @@ const failable<value> get(const string& url, const CURLSession& cs) {
|
|||
return val;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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));
|
||||
|
||||
|
@ -583,6 +713,27 @@ const failable<value> put(const value& val, const string& url, const CURLSession
|
|||
return value(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
@ -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);
|
||||
|
|
|
@ -151,13 +151,6 @@ const bool isVirtualHostRequest(const server_rec* s, request_rec* r) {
|
|||
return hostName(r) != hostName(s);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if a URI is absolute.
|
||||
*/
|
||||
const bool isAbsolute(const string& uri) {
|
||||
return contains(uri, "://");
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the protocol scheme for a server.
|
||||
*/
|
||||
|
@ -172,6 +165,20 @@ const string scheme(request_rec* r, const string& def = "http") {
|
|||
return r->server->server_scheme != NULL? r->server->server_scheme : def;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
|
|
@ -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)));
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Add table
Reference in a new issue