# HG changeset patch # User Goffi # Date 1492454460 -7200 # Node ID 8a393ae90f8c6159fc317be4c8d0120fa6e4ddbc # Parent b5490fa65348f6c5626b269a2d5b44a167ea90ea server (pages): post requests are now handled: - if a HTTP post request is done, on_data_post is called on the page - LiberviaPage.getPostedData help to get easily needed data diff -r b5490fa65348 -r 8a393ae90f8c src/server/constants.py --- a/src/server/constants.py Sun Apr 16 18:26:31 2017 +0200 +++ b/src/server/constants.py Mon Apr 17 20:41:00 2017 +0200 @@ -58,6 +58,10 @@ PAGES_ACCESS_ADMIN = u"admin" # only profiles set in admins_list can access the page PAGES_ACCESS_ALL = (PAGES_ACCESS_NONE, PAGES_ACCESS_PUBLIC, PAGES_ACCESS_PROFILE, PAGES_ACCESS_ADMIN) + ## HTTP methods ## + HTTP_METHOD_GET = u'GET' + HTTP_METHOD_POST = u'POST' + ## HTTP codes ## HTTP_BAD_REQUEST = 400 HTTP_UNAUTHORIZED = 401 diff -r b5490fa65348 -r 8a393ae90f8c src/server/server.py --- a/src/server/server.py Sun Apr 16 18:26:31 2017 +0200 +++ b/src/server/server.py Mon Apr 17 20:41:00 2017 +0200 @@ -1426,7 +1426,7 @@ uri_callbacks = {} def __init__(self, host, root_dir, name=None, redirect=None, access=None, parse_url=None, - prepare_render=None, render=None, template=None): + prepare_render=None, render=None, template=None, on_data_post=None): """initiate LiberviaPages LiberviaPages are the main resources of Libervia, using easy to set python files @@ -1456,6 +1456,8 @@ This method is mutually exclusive with template and must return a unicode string. @param template(unicode, None): path to the template to render. This method is mutually exclusive with render + @param on_data_post(callable, None): method to call when data is posted + None if not post is handled """ web_resource.Resource.__init__(self) @@ -1487,6 +1489,7 @@ self.prepare_render = prepare_render self.template = template self.render_method = render + self.on_data_post = on_data_post if access == C.PAGES_ACCESS_NONE: # none pages just return a 404, no further check is needed return @@ -1529,7 +1532,8 @@ parse_url=page_data.get('parse_url'), prepare_render=page_data.get('prepare_render'), render=page_data.get('render'), - template=page_data.get('template')) + template=page_data.get('template'), + on_data_post=page_data.get('on_data_post')) parent.putChild(d, resource) new_path = path + [d] log.info(u"Added /{path} page".format(path=u'[...]/'.join(new_path))) @@ -1690,6 +1694,36 @@ """don't raise error on CancelError""" failure_.trap(exceptions.CancelError) + def _on_data_post(self, dummy, request): + return defer.maybeDeferred(self.on_data_post, self, request) + + def getPostedData(self, request, keys, multiple=False): + """get data from a POST request and decode it + + @param request(server.Request): request linked to the session + @param keys(unicode, iterable[unicode]): name of the value(s) to get + unicode to get one value + iterable to get more than one + @param multiple(bool): True if multiple values are possible/expected + if False, the first value is returned + @return (iterator[unicode], list[iterator[unicode], unicode, list[unicode]): values received for this(these) key(s) + """ + if isinstance(keys, basestring): + keys = [keys] + get_first = True + else: + get_first = False + + ret = [] + for key in keys: + gen = (urllib.unquote(v).decode('utf-8') for v in request.args.get(key,[])) + if multiple: + ret.append(gen) + else: + ret.append(next(gen)) + + return ret[0] if get_first else ret + def getProfile(self, request): """helper method to easily get current profile @@ -1750,6 +1784,21 @@ d.addCallback(self._subpagesHandler, request) + if request.method not in (C.HTTP_METHOD_GET, C.HTTP_METHOD_POST): + # only HTTP GET and POST are handled so far + d.addCallback(lambda dummy: self.pageError(request, C.HTTP_BAD_REQUEST)) + + + if request.method == C.HTTP_METHOD_POST: + if self.on_data_post is None: + # if we don't have on_data_post, the page was not expecting POST + # so we return an error + d.addCallback(lambda dummy: self.pageError(request, C.HTTP_BAD_REQUEST)) + else: + d.addCallback(self._on_data_post, request) + # by default, POST follow normal behaviour after on_data_post is called + # this can be changed by a redirection or other method call in on_data_post + if self.prepare_render: d.addCallback(self._prepare_render, request) @@ -1766,6 +1815,9 @@ def render_GET(self, request): return self.renderPage(request) + def render_POST(self, request): + return self.renderPage(request) + class Libervia(service.Service):