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:
#actual call
if urlRouterInstance != None and pathargs != None:
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:
# 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)
# parse request arguments from form or JSON docss
self.__addRequestArguments(request, allargs)
urlRouter = urlRouterInstance.urlRouter
val = urlRouter.call(urlRouterInstance.clazz,request,**allargs)
#handle Deferreds natively
if isinstance(val,defer.Deferred):
# add callback to finish the request
......@@ -385,6 +374,27 @@ class RequestRouter:
request.yaml = yaml.safe_load(request.content.read())
except Exception as 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):
"""Filters incoming requests"""
......
......@@ -6,6 +6,8 @@ Argument extraction tests
from corepost.web import RESTResource, validate, route
from corepost.enums import Http
from formencode import Schema, validators
from twisted.python import log
import os
class TestSchema(Schema):
allow_extra_fields = True
......@@ -28,6 +30,11 @@ class ArgumentApp():
def postValidateCustom(self,request,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():
app = RESTResource((ArgumentApp(),))
app.run(8082)
\ No newline at end of file
......@@ -3,7 +3,7 @@ Using step definitions from: '../steps'
@arguments
Feature: 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
Scenario Outline: Path argument extraction
......@@ -29,4 +29,24 @@ Feature: Arguments
| url | code | content |
| /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 |
|
\ 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