Port REST support improvements to AppEngine Python integration scripts and add a sample.
git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@1053004 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
fe9add6a09
commit
c5e532242f
15 changed files with 404 additions and 28 deletions
sca-cpp/trunk
|
@ -920,6 +920,7 @@ AC_CONFIG_FILES([Makefile
|
|||
samples/store-vhost/Makefile
|
||||
samples/store-cluster/Makefile
|
||||
samples/relay-python/Makefile
|
||||
samples/relay-gae/Makefile
|
||||
doc/Makefile
|
||||
doc/Doxyfile
|
||||
ubuntu/Makefile
|
||||
|
|
|
@ -43,7 +43,7 @@ def readATOMEntry(l):
|
|||
return ()
|
||||
return entryElementsToValues(car(e))
|
||||
|
||||
# Convert a list of values representy an ATOM entry to a value
|
||||
# Convert a list of values representing an ATOM entry to a value
|
||||
def entryValue(e):
|
||||
v = elementsToValues((caddr(e),))
|
||||
return cons(car(e), (cadr(e), cdr(car(v))))
|
||||
|
|
|
@ -177,20 +177,25 @@ def application(e, r):
|
|||
if m == "GET":
|
||||
v = comp("get", id)
|
||||
|
||||
# Write returned content-type / content pair
|
||||
if not isinstance(cadr(v), basestring):
|
||||
# Write content-type / content-list pair
|
||||
if isString(car(v)) and isList(cadr(v)):
|
||||
return result(e, r, 200, (("Content-type", car(v)),), cadr(v))
|
||||
|
||||
# Write an ATOM feed or entry
|
||||
if isNil(id):
|
||||
return result(e, r, 200, (("Content-type", "application/atom+xml;type=feed"),), writeATOMFeed(feedValuesToElements(v)))
|
||||
return result(e, r, 200, (("Content-type", "application/atom+xml;type=entry"),), writeATOMEntry(entryValuesToElements(v)))
|
||||
if isString(car(v)) and isString(cadr(v)):
|
||||
if isNil(id):
|
||||
return result(e, r, 200, (("Content-type", "application/atom+xml;type=feed"),), writeATOMFeed(feedValuesToElements(v)))
|
||||
return result(e, r, 200, (("Content-type", "application/atom+xml;type=entry"),), writeATOMEntry(entryValuesToElements(v)))
|
||||
|
||||
# Write a JSON value
|
||||
return result(e, r, 200, (("Content-type", "application/json"),), writeJSON(valuesToElements(v)))
|
||||
|
||||
if m == "POST":
|
||||
ct = requestContentType(e)
|
||||
|
||||
# Handle a JSON-RPC function call
|
||||
if ct.find("application/json-rpc") != -1 or ct.find("text/plain") != -1 or ct.find("application/x-www-form-urlencoded") != -1:
|
||||
if contains(ct, "application/json-rpc") or contains(ct, "text/plain") or contains(ct, "application/x-www-form-urlencoded"):
|
||||
print >> stderr, "Handling JSON-RPC request"
|
||||
json = elementsToValues(readJSON(requestBody(e)))
|
||||
args = postArgs(json)
|
||||
jid = cadr(assoc("'id", args))
|
||||
|
@ -200,7 +205,7 @@ def application(e, r):
|
|||
return result(e, r, 200, (("Content-type", "application/json-rpc"),), jsonResult(jid, v))
|
||||
|
||||
# Handle an ATOM entry POST
|
||||
if ct.find("application/atom+xml") != -1:
|
||||
if contains(ct, "application/atom+xml"):
|
||||
ae = entryValue(readATOMEntry(requestBody(e)))
|
||||
v = comp("post", id, ae)
|
||||
if isNil(v):
|
||||
|
@ -237,7 +242,7 @@ def main():
|
|||
|
||||
# Handle the WSGI request with the WSGI runtime
|
||||
st = serverType(environ)
|
||||
if st.find("App Engine") != -1 or st.find("Development") != -1:
|
||||
if contains(st, "App Engine") or contains(st, "Development"):
|
||||
from google.appengine.ext.webapp.util import run_wsgi_app
|
||||
run_wsgi_app(application)
|
||||
elif st != "":
|
||||
|
|
|
@ -17,11 +17,6 @@
|
|||
# specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
uri=$1
|
||||
if [ "$uri" = "" ]; then
|
||||
uri="http://localhost:8090"
|
||||
fi
|
||||
|
||||
# Setup
|
||||
mkdir -p tmp
|
||||
./wsgi-start target 8090 2>/dev/null
|
||||
|
|
|
@ -26,8 +26,11 @@ from string import strip
|
|||
from base64 import b64encode
|
||||
from sys import stderr
|
||||
from util import *
|
||||
from atomutil import *
|
||||
from jsonutil import *
|
||||
from elemutil import *
|
||||
import atomutil
|
||||
import jsonutil
|
||||
import rssutil
|
||||
import xmlutil
|
||||
|
||||
# JSON request id
|
||||
id = 1
|
||||
|
@ -38,23 +41,116 @@ class client:
|
|||
self.url = urlparse(url)
|
||||
|
||||
def __call__(self, func, *args):
|
||||
print >> stderr, "Client proxy call", func, args
|
||||
|
||||
# Connect to the configured URL
|
||||
print >> stderr, "Client POST", self.url.geturl()
|
||||
c, headers = connect(self.url)
|
||||
|
||||
# POST a JSON-RPC request
|
||||
# handle a GET request
|
||||
if func == "get":
|
||||
u = requesturi(self.url, car(args))
|
||||
print >> stderr, "Client GET request", u
|
||||
c.request("GET", u, None, headers)
|
||||
res = c.getresponse()
|
||||
print >> stderr, "Client status", res.status
|
||||
if res.status != 200:
|
||||
return None
|
||||
ct = res.getheader("Content-type", "text/plain")
|
||||
ls = (res.read(),)
|
||||
|
||||
if contains(ct, "application/atom+xml;type=entry"):
|
||||
# Read an ATOM entry
|
||||
v = atomutil.entryValue(atomutil.readATOMEntry(ls))
|
||||
print >> stderr, "Client result", v
|
||||
return v
|
||||
|
||||
if contains(ct, "application/atom+xml;type=feed"):
|
||||
# Read an ATOM feed
|
||||
v = atomutil.feedValues(atomutil.readATOMFeed(ls))
|
||||
print >> stderr, "Client result", v
|
||||
return v
|
||||
|
||||
if contains(ct, "application/rss+xml") or rssutil.isRSSFeed(ls):
|
||||
# Read an RSS feed
|
||||
v = rssutil.feedValues(rssutil.readRSSFeed(ls))
|
||||
print >> stderr, "Client result", v
|
||||
return v
|
||||
|
||||
if contains(ct, "text/javascript") or contains(ct, "application/json") or jsonutil.isJSON(ls):
|
||||
# Read a JSON document
|
||||
v = elementsToValues(jsonutil.readJSON(ls))
|
||||
print >> stderr, "Client result", v
|
||||
return v
|
||||
|
||||
if contains(ct, "text/xml") or contains(ct, "application/xml") or xmlutil.isXML(ls):
|
||||
# Read an XML document
|
||||
v = elementsToValues(xmlutil.readXML(ls))
|
||||
print >> stderr, "Client result", v
|
||||
return v
|
||||
|
||||
# Return the content type and a content list
|
||||
v = (ct, ls)
|
||||
print >> stderr, "Client result", v
|
||||
return v
|
||||
|
||||
# handle a POST request
|
||||
if func == "post":
|
||||
u = requesturi(self.url, car(args))
|
||||
print >> stderr, "Client POST request", u
|
||||
req = StringIO()
|
||||
writeStrings(atomutil.writeATOMEntry(atomutil.entryValuesToElements(cadr(args))), req)
|
||||
headers["Content-type"] = "application/atom+xml"
|
||||
c.request("POST", u, req.getvalue(), headers)
|
||||
res = c.getresponse()
|
||||
print >> stderr, "Client status", res.status
|
||||
if res.status != 200 and res.status != 201:
|
||||
return None
|
||||
loc = res.getheader("Location")
|
||||
if loc == None:
|
||||
return None
|
||||
return loc[(loc.rfind('/') + 1):]
|
||||
|
||||
# handle a PUT request
|
||||
if func == "put":
|
||||
u = requesturi(self.url, car(args))
|
||||
print >> stderr, "Client PUT request", u
|
||||
req = StringIO()
|
||||
writeStrings(atomutil.writeATOMEntry(atomutil.entryValuesToElements(cadr(args))), req)
|
||||
headers["Content-type"] = "application/atom+xml"
|
||||
c.request("PUT", u, req.getvalue(), headers)
|
||||
res = c.getresponse()
|
||||
print >> stderr, "Client status", res.status
|
||||
if res.status != 200:
|
||||
return None
|
||||
return True
|
||||
|
||||
# handle a DELETE request
|
||||
if func == "delete":
|
||||
u = requesturi(self.url, car(args))
|
||||
print >> stderr, "Client DELETE request", u
|
||||
c.request("DELETE", u, None, headers)
|
||||
res = c.getresponse()
|
||||
print >> stderr, "Client status", res.status
|
||||
if res.status != 200:
|
||||
return None
|
||||
return True
|
||||
|
||||
# handle a JSON-RPC request
|
||||
u = requesturi(self.url, ())
|
||||
print >> stderr, "Client JSON-RPC request", u
|
||||
global id
|
||||
req = StringIO()
|
||||
writeStrings(jsonRequest(id, func, args), req)
|
||||
writeStrings(jsonutil.jsonRequest(id, func, args), req)
|
||||
id = id + 1
|
||||
headers["Content-type"] = "application/json-rpc"
|
||||
c.request("POST", self.url.path, req.getvalue(), headers)
|
||||
c.request("POST", u, req.getvalue(), headers)
|
||||
res = c.getresponse()
|
||||
print >> stderr, "Client status", res.status
|
||||
if res.status != 200:
|
||||
return None
|
||||
return jsonResultValue((res.read(),))
|
||||
v = jsonutil.jsonResultValue((res.read(),))
|
||||
print >> stderr, "Client result", v
|
||||
return v
|
||||
|
||||
def __getattr__(self, name):
|
||||
if name[0] == '_':
|
||||
|
@ -82,12 +178,19 @@ def connect(url):
|
|||
else:
|
||||
c = HTTPSConnection(url.hostname, 443 if url.port == None else url.port)
|
||||
|
||||
# For HTTP basic authentication the user and password are
|
||||
# For HTTP basic authentication the user and password may be
|
||||
# provided by htpasswd.py
|
||||
import htpasswd
|
||||
auth = 'Basic ' + b64encode(htpasswd.user + ':' + htpasswd.passwd)
|
||||
return c, {"Authorization": auth}
|
||||
try:
|
||||
import htpasswd
|
||||
auth = 'Basic ' + b64encode(htpasswd.user + ':' + htpasswd.passwd)
|
||||
return c, {"Authorization": auth}
|
||||
except:
|
||||
return c, {}
|
||||
else:
|
||||
c = HTTPConnection(url.hostname, 80 if url.port == None else url.port)
|
||||
return c, {}
|
||||
|
||||
# Convert a URL and arg to a request URI
|
||||
def requesturi(url, arg):
|
||||
return url.path + path(arg) + ("" if url.query == "" else "?" + url.query)
|
||||
|
||||
|
|
|
@ -59,6 +59,9 @@ def isNil(l):
|
|||
def isSymbol(v):
|
||||
return isinstance(v, basestring) and v[0:1] == "'"
|
||||
|
||||
def isString(v):
|
||||
return isinstance(v, basestring) and v[0:1] != "'"
|
||||
|
||||
def isList(v):
|
||||
if getattr(v, '__iter__', False) == False:
|
||||
return False
|
||||
|
@ -132,10 +135,20 @@ def assoc(k, l):
|
|||
def curry(f, *args):
|
||||
return lambda *a: f(*(args + a))
|
||||
|
||||
# Convert a path represented as a list of values to a string
|
||||
def path(p):
|
||||
if isNil(p):
|
||||
return ""
|
||||
return "/" + car(p) + path(cdr(p))
|
||||
|
||||
# Split a path into a list of segments
|
||||
def tokens(path):
|
||||
return tuple(filter(lambda s: len(s) != 0, path.split("/")))
|
||||
|
||||
# Return true if s1 contains s2
|
||||
def contains(s1, s2):
|
||||
return s1.find(s2) != -1
|
||||
|
||||
# Write a list of strings to a stream
|
||||
def writeStrings(l, os):
|
||||
if l == ():
|
||||
|
|
|
@ -31,8 +31,10 @@ def readAttributes(a):
|
|||
|
||||
# Read an XML element
|
||||
def readElement(e):
|
||||
l = (element, "'" + e.tag) + readAttributes(tuple(e.items())) + readElements(tuple(e.getchildren()))
|
||||
if e.text == None:
|
||||
a = tuple(e.items())
|
||||
c = tuple(e.getchildren())
|
||||
l = (element, "'" + e.tag) + readAttributes(a) + readElements(c)
|
||||
if e.text == None or c != ():
|
||||
return l
|
||||
return l + (e.text,)
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
# specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
SUBDIRS = store-scheme store-cpp store-python store-java store-gae store-sql store-nosql store-vhost store-cluster relay-python
|
||||
SUBDIRS = store-scheme store-cpp store-python store-java store-gae store-sql store-nosql store-vhost store-cluster relay-python relay-gae
|
||||
|
||||
sample_DATA = README
|
||||
sampledir=$(prefix)/samples
|
||||
|
|
40
sca-cpp/trunk/samples/relay-gae/Makefile.am
Normal file
40
sca-cpp/trunk/samples/relay-gae/Makefile.am
Normal file
|
@ -0,0 +1,40 @@
|
|||
# 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.
|
||||
|
||||
if WANT_PYTHON
|
||||
if WANT_GAE
|
||||
|
||||
dist_sample_SCRIPTS = start stop
|
||||
sampledir = $(prefix)/samples/relay-gae
|
||||
|
||||
BUILT_SOURCES = target.stamp
|
||||
target.stamp: app.yaml *.py *.composite $(top_builddir)/modules/wsgi/*.py htdocs/*.html
|
||||
mkdir -p target
|
||||
cp app.yaml *.py *.composite `ls $(top_builddir)/modules/wsgi/*.py | grep -v "\-test"` target
|
||||
mkdir -p target/htdocs
|
||||
cp -R htdocs/* target/htdocs
|
||||
touch target.stamp
|
||||
|
||||
clean-local:
|
||||
rm -rf target.stamp target
|
||||
|
||||
nobase_sample_DATA = target/app.yaml target/*.py target/*.composite target/htdocs/*.html
|
||||
|
||||
EXTRA_DIST = app.yaml *.composite *.py htdocs/*.html
|
||||
|
||||
endif
|
||||
endif
|
50
sca-cpp/trunk/samples/relay-gae/app.yaml
Normal file
50
sca-cpp/trunk/samples/relay-gae/app.yaml
Normal file
|
@ -0,0 +1,50 @@
|
|||
# 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.
|
||||
|
||||
application: sca-relay
|
||||
version: 1
|
||||
runtime: python
|
||||
api_version: 1
|
||||
skip_files:
|
||||
- ^(.*/)?app\.yaml
|
||||
- ^(.*/)?app\.yml
|
||||
- ^(.*/)?index\.yaml
|
||||
- ^(.*/)?index\.yml
|
||||
- ^(.*/)?#.*#
|
||||
- ^(.*/)?.*~
|
||||
- ^(.*/)?.*\.py[co]
|
||||
- ^(.*/)?.*/RCS/.*
|
||||
- ^(.*/)?\..*
|
||||
- ^(.*/)?.*-test$
|
||||
- ^(.*/)?.*\.cpp$
|
||||
- ^(.*/)?.*\.o$
|
||||
- ^(.*/)?core$
|
||||
- ^(.*/)?.*\.out$
|
||||
- ^(.*/)?.*\.log$
|
||||
- ^(.*/)?Makefile.*
|
||||
- ^(.*/)?tmp/.*
|
||||
- ^(.*/)?wsgi-start
|
||||
- ^(.*/)?wsgi-stop
|
||||
|
||||
handlers:
|
||||
- url: /(.*\.(html|png))
|
||||
static_files: htdocs/\1
|
||||
upload: htdocs/(.*\.(html|png))
|
||||
|
||||
- url: /.*
|
||||
script: composite.py
|
||||
|
75
sca-cpp/trunk/samples/relay-gae/domain.composite
Normal file
75
sca-cpp/trunk/samples/relay-gae/domain.composite
Normal file
|
@ -0,0 +1,75 @@
|
|||
<?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"
|
||||
xmlns:t="http://tuscany.apache.org/xmlns/sca/1.1"
|
||||
targetNamespace="http://relay"
|
||||
name="relay">
|
||||
|
||||
<component name="JSONTwit">
|
||||
<t:implementation.python script="relay.py"/>
|
||||
<service name="Relay">
|
||||
<t:binding.http uri="jsontwit"/>
|
||||
</service>
|
||||
<reference name="target">
|
||||
<t:binding.http uri="http://api.twitter.com/1/statuses/user_timeline.json?screen_name=jsdelfino"/>
|
||||
</reference>
|
||||
</component>
|
||||
|
||||
<component name="XMLTwit">
|
||||
<t:implementation.python script="relay.py"/>
|
||||
<service name="Relay">
|
||||
<t:binding.http uri="xmltwit"/>
|
||||
</service>
|
||||
<reference name="target">
|
||||
<t:binding.http uri="http://api.twitter.com/1/statuses/user_timeline.xml?screen_name=jsdelfino"/>
|
||||
</reference>
|
||||
</component>
|
||||
|
||||
<component name="RSSTwit">
|
||||
<t:implementation.python script="relay.py"/>
|
||||
<service name="Relay">
|
||||
<t:binding.http uri="rsstwit"/>
|
||||
</service>
|
||||
<reference name="target">
|
||||
<t:binding.http uri="http://api.twitter.com/1/statuses/user_timeline.rss?screen_name=jsdelfino"/>
|
||||
</reference>
|
||||
</component>
|
||||
|
||||
<component name="HTML">
|
||||
<t:implementation.python script="relay.py"/>
|
||||
<service name="Relay">
|
||||
<t:binding.http uri="html"/>
|
||||
</service>
|
||||
<reference name="target">
|
||||
<t:binding.http uri="http://people.apache.org/~jsdelfino/"/>
|
||||
</reference>
|
||||
</component>
|
||||
|
||||
<component name="JSONFB">
|
||||
<t:implementation.python script="relay.py"/>
|
||||
<service name="Relay">
|
||||
<t:binding.http uri="jsonfb"/>
|
||||
</service>
|
||||
<reference name="target">
|
||||
<t:binding.http uri="https://graph.facebook.com/100001053301307"/>
|
||||
</reference>
|
||||
</component>
|
||||
|
||||
</composite>
|
31
sca-cpp/trunk/samples/relay-gae/htdocs/index.html
Normal file
31
sca-cpp/trunk/samples/relay-gae/htdocs/index.html
Normal file
|
@ -0,0 +1,31 @@
|
|||
<!--
|
||||
* 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.
|
||||
-->
|
||||
<html>
|
||||
<head>
|
||||
<title>Relay</title>
|
||||
<body>
|
||||
|
||||
<p><a href="/html">Sample HTML request</a></p>
|
||||
<p><a href="/jsontwit">Sample Twitter JSON request</a></p>
|
||||
<p><a href="/xmltwit">Sample Twitter XML request</a></p>
|
||||
<p><a href="/rsstwit">Sample Twitter RSS request</a></p>
|
||||
<p><a href="/jsonfb">Sample Facebook JSON request</a></p>
|
||||
|
||||
</body>
|
||||
</html>
|
21
sca-cpp/trunk/samples/relay-gae/relay.py
Normal file
21
sca-cpp/trunk/samples/relay-gae/relay.py
Normal file
|
@ -0,0 +1,21 @@
|
|||
# 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.
|
||||
|
||||
# Relay implementation
|
||||
def get(id, target):
|
||||
return target.get(id)
|
||||
|
20
sca-cpp/trunk/samples/relay-gae/start
Executable file
20
sca-cpp/trunk/samples/relay-gae/start
Executable file
|
@ -0,0 +1,20 @@
|
|||
#!/bin/sh
|
||||
|
||||
# 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.
|
||||
|
||||
../../modules/wsgi/gae-start target 8090
|
20
sca-cpp/trunk/samples/relay-gae/stop
Executable file
20
sca-cpp/trunk/samples/relay-gae/stop
Executable file
|
@ -0,0 +1,20 @@
|
|||
#!/bin/sh
|
||||
|
||||
# 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.
|
||||
|
||||
../../modules/wsgi/gae-stop target 8090
|
Loading…
Add table
Reference in a new issue