Commit 1261244b authored by Jacek Furmankiewicz's avatar Jacek Furmankiewicz

ability to parse JSON documents for method arguments

parent 3691da3a
...@@ -248,26 +248,15 @@ class RequestRouter: ...@@ -248,26 +248,15 @@ class RequestRouter:
#actual call #actual call
if urlRouterInstance != None and pathargs != None: if urlRouterInstance != None and pathargs != None:
allargs = copy.deepcopy(pathargs) allargs = copy.deepcopy(pathargs)
# handler for weird Twisted logic where PUT does not get form params
# see: http://twistedmatrix.com/pipermail/twisted-web/2007-March/003338.html
requestargs = request.args
if request.method == Http.PUT and HttpHeader.CONTENT_TYPE in request.received_headers.keys() \
and request.received_headers[HttpHeader.CONTENT_TYPE] == MediaType.APPLICATION_FORM_URLENCODED:
requestargs = parse_qs(request.content.read(), 1)
#merge form args
for arg in requestargs.keys():
# maintain first instance of an argument always
if arg not in allargs:
allargs[arg] = requestargs[arg][0]
try: try:
# if POST/PUT, check if we need to automatically parse JSON # if POST/PUT, check if we need to automatically parse JSON, YAML, XML
self.__parseRequestData(request) self.__parseRequestData(request)
# parse request arguments from form or JSON docss
self.__addRequestArguments(request, allargs)
urlRouter = urlRouterInstance.urlRouter urlRouter = urlRouterInstance.urlRouter
val = urlRouter.call(urlRouterInstance.clazz,request,**allargs) val = urlRouter.call(urlRouterInstance.clazz,request,**allargs)
#handle Deferreds natively #handle Deferreds natively
if isinstance(val,defer.Deferred): if isinstance(val,defer.Deferred):
# add callback to finish the request # add callback to finish the request
...@@ -385,6 +374,27 @@ class RequestRouter: ...@@ -385,6 +374,27 @@ class RequestRouter:
request.yaml = yaml.safe_load(request.content.read()) request.yaml = yaml.safe_load(request.content.read())
except Exception as ex: except Exception as ex:
raise TypeError("Unable to parse YAML body: %s" % ex) raise TypeError("Unable to parse YAML body: %s" % ex)
def __addRequestArguments(self,request,allargs):
"""Parses the request form arguments OR JSON document root elements to build the list of arguments to a method"""
# handler for weird Twisted logic where PUT does not get form params
# see: http://twistedmatrix.com/pipermail/twisted-web/2007-March/003338.html
requestargs = request.args
if request.method == Http.PUT and HttpHeader.CONTENT_TYPE in request.received_headers.keys() \
and request.received_headers[HttpHeader.CONTENT_TYPE] == MediaType.APPLICATION_FORM_URLENCODED:
requestargs = parse_qs(request.content.read(), 1)
#merge form args
for arg in requestargs.keys():
# maintain first instance of an argument always
if arg not in allargs:
allargs[arg] = requestargs[arg][0]
# if JSON parse root elements instead of form elements
if hasattr(request,'json'):
for key in request.json.keys():
if key not in allargs:
allargs[key] = request.json[key]
def __filterRequests(self,request): def __filterRequests(self,request):
"""Filters incoming requests""" """Filters incoming requests"""
......
...@@ -6,6 +6,8 @@ Argument extraction tests ...@@ -6,6 +6,8 @@ Argument extraction tests
from corepost.web import RESTResource, validate, route from corepost.web import RESTResource, validate, route
from corepost.enums import Http from corepost.enums import Http
from formencode import Schema, validators from formencode import Schema, validators
from twisted.python import log
import os
class TestSchema(Schema): class TestSchema(Schema):
allow_extra_fields = True allow_extra_fields = True
...@@ -28,6 +30,11 @@ class ArgumentApp(): ...@@ -28,6 +30,11 @@ class ArgumentApp():
def postValidateCustom(self,request,rootId,childId,**kwargs): def postValidateCustom(self,request,rootId,childId,**kwargs):
return "%s - %s - %s" % (rootId,childId,kwargs) return "%s - %s - %s" % (rootId,childId,kwargs)
@route("/formOrJson",(Http.POST,Http.PUT))
def postArgumentsByContentType(self,request,first,last,**kwargs):
return "%s %s" % (str(first),str(last))
def run_app_arguments(): def run_app_arguments():
app = RESTResource((ArgumentApp(),)) app = RESTResource((ArgumentApp(),))
app.run(8082) app.run(8082)
\ No newline at end of file
...@@ -3,7 +3,7 @@ Using step definitions from: '../steps' ...@@ -3,7 +3,7 @@ Using step definitions from: '../steps'
@arguments @arguments
Feature: Arguments Feature: Arguments
CorePost should be able to correctly extract arguments CorePost should be able to correctly extract arguments
from paths, query arguments and form arguments from paths, query arguments, form arguments and JSON documents
@arguments_ok @arguments_ok
Scenario Outline: Path argument extraction Scenario Outline: Path argument extraction
...@@ -29,4 +29,24 @@ Feature: Arguments ...@@ -29,4 +29,24 @@ Feature: Arguments
| url | code | content | | url | code | content |
| /int/WRONG/float/1.1/string/TEST | 404 | URL '/int/WRONG/float/1.1/string/TEST' not found | | /int/WRONG/float/1.1/string/TEST | 404 | URL '/int/WRONG/float/1.1/string/TEST' not found |
| /int/1/float/WRONG/string/TEST | 404 | URL '/int/1/float/WRONG/string/TEST' not found | | /int/1/float/WRONG/string/TEST | 404 | URL '/int/1/float/WRONG/string/TEST' not found |
|
\ No newline at end of file @arguments_by_type
Scenario Outline: Parse form arguments OR from JSON documents for POST / PUT
Given 'arguments' is running
# pass in as form arguments
When as user 'None:None' I <method> 'http://127.0.0.1:8082/formOrJson' with 'first=John&last=Doe'
Then I expect HTTP code <code>
And I expect content contains 'John Doe'
# pass in as JSON document
When as user 'None:None' I <method> 'http://127.0.0.1:8082/formOrJson' with JSON
"""
{"first":"Jane","last":"Doeovskaya"}
"""
Then I expect HTTP code <code>
And I expect content contains 'Jane Doeovskaya'
Examples:
| method | code |
| POST | 201 |
| PUT | 200 |
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment