Rest protocols now make use of the http method to select the function is needed
This commit is contained in:
parent
3aa41ec7b1
commit
9d7b2895a5
@ -14,6 +14,8 @@ Changes
|
||||
|
||||
* Tests code coverage is now over 95%.
|
||||
|
||||
* RESTful protocol can now use the http method.
|
||||
|
||||
0.3 (2012-04-20)
|
||||
----------------
|
||||
|
||||
|
@ -23,11 +23,14 @@ following paths :
|
||||
- ``/ws/persons/update``
|
||||
- ``/ws/persons/destroy``
|
||||
|
||||
In a near future, an additional expose option `restverb` will allow
|
||||
to use the HTTP verb to select the function, in which case the path
|
||||
will not containt the function name.
|
||||
In addition to this trivial function mapping, a `method` option can
|
||||
be given to the `expose` decorator. In such a case, the function
|
||||
name can be omitted by the caller, and the dispatch will look at the
|
||||
http method used in the request to select the correct function.
|
||||
|
||||
The function parameters can be transmitted in two ways :
|
||||
The function parameters can be transmitted in two ways (is using
|
||||
the http method to select the function, one way or the other
|
||||
may be usable) :
|
||||
|
||||
#. As a GET query string or POST form parameters.
|
||||
|
||||
|
@ -24,6 +24,22 @@ class RestProtocol(Protocol):
|
||||
if path[-1].endswith('.' + self.dataformat):
|
||||
path[-1] = path[-1][:-len(self.dataformat) - 1]
|
||||
|
||||
# Check if the path is actually a function, and if not
|
||||
# see if the http method make a difference
|
||||
# TODO Re-think the function lookup phases. Here we are
|
||||
# doing the job that will be done in a later phase, which
|
||||
# is sub-optimal
|
||||
for p, fdef in self.root.getapi():
|
||||
if p == path:
|
||||
return path
|
||||
|
||||
# No function at this path. Now check for function that have
|
||||
# this path as a prefix, and declared an http method
|
||||
for p, fdef in self.root.getapi():
|
||||
if len(p) == len(path) + 1 and p[:len(path)] == path and \
|
||||
fdef.extra_options.get('method') == context.request.method:
|
||||
return p
|
||||
|
||||
return path
|
||||
|
||||
def read_arguments(self, context):
|
||||
@ -35,7 +51,7 @@ class RestProtocol(Protocol):
|
||||
request.headers['Content-Type']:
|
||||
# The params were read from the body, ignoring the body then
|
||||
pass
|
||||
elif len(request.params) and request.body:
|
||||
elif len(request.params) and request.content_length:
|
||||
log.warning("The request has both a body and params.")
|
||||
log.debug("Params: %s" % request.params)
|
||||
log.debug("Body: %s" % request.body)
|
||||
|
@ -14,6 +14,7 @@ import wsme.protocols.restjson
|
||||
from wsme.protocols.restjson import fromjson, tojson
|
||||
from wsme.utils import parse_isodatetime, parse_isotime, parse_isodate
|
||||
from wsme.types import isusertype, register_type
|
||||
from wsme.api import expose, validate
|
||||
|
||||
|
||||
import six
|
||||
@ -79,6 +80,52 @@ def prepare_result(value, datatype):
|
||||
return value
|
||||
|
||||
|
||||
class Obj(wsme.types.Base):
|
||||
id = int
|
||||
name = wsme.types.text
|
||||
|
||||
|
||||
class CRUDResult(object):
|
||||
data = Obj
|
||||
message = wsme.types.text
|
||||
|
||||
def __init__(self, data=wsme.types.Unset, message=wsme.types.Unset):
|
||||
self.data = data
|
||||
self.message = message
|
||||
|
||||
|
||||
class MiniCrud(object):
|
||||
@expose(CRUDResult, method='PUT')
|
||||
@validate(Obj)
|
||||
def create(self, data):
|
||||
print(repr(data))
|
||||
return CRUDResult(data, u('create'))
|
||||
|
||||
@expose(CRUDResult, method='GET')
|
||||
@validate(Obj)
|
||||
def read(self, ref):
|
||||
print(repr(ref))
|
||||
if ref.id == 1:
|
||||
ref.name = u('test')
|
||||
return CRUDResult(ref, u('read'))
|
||||
|
||||
@expose(CRUDResult, method='POST')
|
||||
@validate(Obj)
|
||||
def update(self, data):
|
||||
print(repr(data))
|
||||
return CRUDResult(data, u('update'))
|
||||
|
||||
@expose(CRUDResult, method='DELETE')
|
||||
@validate(Obj)
|
||||
def delete(self, ref):
|
||||
print(repr(ref))
|
||||
if ref.id == 1:
|
||||
ref.name = u('test')
|
||||
return CRUDResult(ref, u('delete'))
|
||||
|
||||
wsme.tests.protocol.WSTestRoot.crud = MiniCrud()
|
||||
|
||||
|
||||
class TestRestJson(wsme.tests.protocol.ProtocolTestCase):
|
||||
protocol = 'restjson'
|
||||
|
||||
@ -256,13 +303,6 @@ class TestRestJson(wsme.tests.protocol.ProtocolTestCase):
|
||||
assert r[1] == '''{
|
||||
"a": 2
|
||||
}''', r[1]
|
||||
|
||||
def test_encode_sample_result(self):
|
||||
r = self.root.protocols[0].encode_sample_result(
|
||||
int, 2, True
|
||||
)
|
||||
assert r[0] == 'javascript', r[0]
|
||||
assert r[1] == '''2'''
|
||||
|
||||
def test_encode_sample_result(self):
|
||||
r = self.root.protocols[0].encode_sample_result(
|
||||
@ -278,3 +318,63 @@ class TestRestJson(wsme.tests.protocol.ProtocolTestCase):
|
||||
assert r[1] == '''{
|
||||
"result": 2
|
||||
}'''
|
||||
|
||||
def test_PUT(self):
|
||||
data = {"id": 1, "name": u("test")}
|
||||
content = json.dumps(dict(data=data))
|
||||
headers = {
|
||||
'Content-Type': 'application/json',
|
||||
}
|
||||
res = self.app.put(
|
||||
'/crud',
|
||||
content,
|
||||
headers=headers,
|
||||
expect_errors=False)
|
||||
print("Received:", res.body)
|
||||
result = json.loads(res.text)
|
||||
print(result)
|
||||
assert result['data']['id'] == 1
|
||||
assert result['data']['name'] == u("test")
|
||||
assert result['message'] == "create"
|
||||
|
||||
def test_GET(self):
|
||||
headers = {
|
||||
'Content-Type': 'application/json',
|
||||
}
|
||||
res = self.app.get(
|
||||
'/crud?ref.id=1',
|
||||
headers=headers,
|
||||
expect_errors=False)
|
||||
print("Received:", res.body)
|
||||
result = json.loads(res.text)
|
||||
print(result)
|
||||
assert result['data']['id'] == 1
|
||||
assert result['data']['name'] == u("test")
|
||||
assert result['message'] == "read"
|
||||
|
||||
def test_POST(self):
|
||||
headers = {
|
||||
'Content-Type': 'application/json',
|
||||
}
|
||||
res = self.app.post(
|
||||
'/crud',
|
||||
json.dumps(dict(data=dict(id=1, name=u('test')))),
|
||||
headers=headers,
|
||||
expect_errors=False)
|
||||
print("Received:", res.body)
|
||||
result = json.loads(res.text)
|
||||
print(result)
|
||||
assert result['data']['id'] == 1
|
||||
assert result['data']['name'] == u("test")
|
||||
assert result['message'] == "update"
|
||||
|
||||
def test_DELETE(self):
|
||||
res = self.app.delete(
|
||||
'/crud.json?ref.id=1',
|
||||
expect_errors=False)
|
||||
print("Received:", res.body)
|
||||
result = json.loads(res.text)
|
||||
print(result)
|
||||
assert result['data']['id'] == 1
|
||||
assert result['data']['name'] == u("test")
|
||||
assert result['message'] == "delete"
|
||||
|
Loading…
x
Reference in New Issue
Block a user