comparison src/server/server.py @ 931:8a393ae90f8c

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
author Goffi <goffi@goffi.org>
date Mon, 17 Apr 2017 20:41:00 +0200
parents bb4dfc2802c0
children c3ae008f7a0f
comparison
equal deleted inserted replaced
930:b5490fa65348 931:8a393ae90f8c
1424 isLeaf = True # we handle subpages ourself 1424 isLeaf = True # we handle subpages ourself
1425 named_pages = {} 1425 named_pages = {}
1426 uri_callbacks = {} 1426 uri_callbacks = {}
1427 1427
1428 def __init__(self, host, root_dir, name=None, redirect=None, access=None, parse_url=None, 1428 def __init__(self, host, root_dir, name=None, redirect=None, access=None, parse_url=None,
1429 prepare_render=None, render=None, template=None): 1429 prepare_render=None, render=None, template=None, on_data_post=None):
1430 """initiate LiberviaPages 1430 """initiate LiberviaPages
1431 1431
1432 LiberviaPages are the main resources of Libervia, using easy to set python files 1432 LiberviaPages are the main resources of Libervia, using easy to set python files
1433 The arguments are the variables found in page_meta.py 1433 The arguments are the variables found in page_meta.py
1434 @param host(Libervia): the running instance of Libervia 1434 @param host(Libervia): the running instance of Libervia
1454 @param render(callable, None): if not template is set, this method will be called and 1454 @param render(callable, None): if not template is set, this method will be called and
1455 what it returns will be rendered. 1455 what it returns will be rendered.
1456 This method is mutually exclusive with template and must return a unicode string. 1456 This method is mutually exclusive with template and must return a unicode string.
1457 @param template(unicode, None): path to the template to render. 1457 @param template(unicode, None): path to the template to render.
1458 This method is mutually exclusive with render 1458 This method is mutually exclusive with render
1459 @param on_data_post(callable, None): method to call when data is posted
1460 None if not post is handled
1459 """ 1461 """
1460 1462
1461 web_resource.Resource.__init__(self) 1463 web_resource.Resource.__init__(self)
1462 self.host = host 1464 self.host = host
1463 self.root_dir = root_dir 1465 self.root_dir = root_dir
1485 self.redirect = None 1487 self.redirect = None
1486 self.parse_url = parse_url 1488 self.parse_url = parse_url
1487 self.prepare_render = prepare_render 1489 self.prepare_render = prepare_render
1488 self.template = template 1490 self.template = template
1489 self.render_method = render 1491 self.render_method = render
1492 self.on_data_post = on_data_post
1490 if access == C.PAGES_ACCESS_NONE: 1493 if access == C.PAGES_ACCESS_NONE:
1491 # none pages just return a 404, no further check is needed 1494 # none pages just return a 404, no further check is needed
1492 return 1495 return
1493 if template is None: 1496 if template is None:
1494 if not callable(render): 1497 if not callable(render):
1527 redirect=page_data.get('redirect'), 1530 redirect=page_data.get('redirect'),
1528 access=page_data.get('access'), 1531 access=page_data.get('access'),
1529 parse_url=page_data.get('parse_url'), 1532 parse_url=page_data.get('parse_url'),
1530 prepare_render=page_data.get('prepare_render'), 1533 prepare_render=page_data.get('prepare_render'),
1531 render=page_data.get('render'), 1534 render=page_data.get('render'),
1532 template=page_data.get('template')) 1535 template=page_data.get('template'),
1536 on_data_post=page_data.get('on_data_post'))
1533 parent.putChild(d, resource) 1537 parent.putChild(d, resource)
1534 new_path = path + [d] 1538 new_path = path + [d]
1535 log.info(u"Added /{path} page".format(path=u'[...]/'.join(new_path))) 1539 log.info(u"Added /{path} page".format(path=u'[...]/'.join(new_path)))
1536 if 'uri_handlers' in page_data: 1540 if 'uri_handlers' in page_data:
1537 if not isinstance(page_data, dict): 1541 if not isinstance(page_data, dict):
1688 1692
1689 def _renderEb(self, failure_, request): 1693 def _renderEb(self, failure_, request):
1690 """don't raise error on CancelError""" 1694 """don't raise error on CancelError"""
1691 failure_.trap(exceptions.CancelError) 1695 failure_.trap(exceptions.CancelError)
1692 1696
1697 def _on_data_post(self, dummy, request):
1698 return defer.maybeDeferred(self.on_data_post, self, request)
1699
1700 def getPostedData(self, request, keys, multiple=False):
1701 """get data from a POST request and decode it
1702
1703 @param request(server.Request): request linked to the session
1704 @param keys(unicode, iterable[unicode]): name of the value(s) to get
1705 unicode to get one value
1706 iterable to get more than one
1707 @param multiple(bool): True if multiple values are possible/expected
1708 if False, the first value is returned
1709 @return (iterator[unicode], list[iterator[unicode], unicode, list[unicode]): values received for this(these) key(s)
1710 """
1711 if isinstance(keys, basestring):
1712 keys = [keys]
1713 get_first = True
1714 else:
1715 get_first = False
1716
1717 ret = []
1718 for key in keys:
1719 gen = (urllib.unquote(v).decode('utf-8') for v in request.args.get(key,[]))
1720 if multiple:
1721 ret.append(gen)
1722 else:
1723 ret.append(next(gen))
1724
1725 return ret[0] if get_first else ret
1726
1693 def getProfile(self, request): 1727 def getProfile(self, request):
1694 """helper method to easily get current profile 1728 """helper method to easily get current profile
1695 1729
1696 @return (unicode, None): current profile 1730 @return (unicode, None): current profile
1697 None if no profile session is started 1731 None if no profile session is started
1748 if self.parse_url is not None and not skip_parse_url: 1782 if self.parse_url is not None and not skip_parse_url:
1749 d.addCallback(self.parse_url, request) 1783 d.addCallback(self.parse_url, request)
1750 1784
1751 d.addCallback(self._subpagesHandler, request) 1785 d.addCallback(self._subpagesHandler, request)
1752 1786
1787 if request.method not in (C.HTTP_METHOD_GET, C.HTTP_METHOD_POST):
1788 # only HTTP GET and POST are handled so far
1789 d.addCallback(lambda dummy: self.pageError(request, C.HTTP_BAD_REQUEST))
1790
1791
1792 if request.method == C.HTTP_METHOD_POST:
1793 if self.on_data_post is None:
1794 # if we don't have on_data_post, the page was not expecting POST
1795 # so we return an error
1796 d.addCallback(lambda dummy: self.pageError(request, C.HTTP_BAD_REQUEST))
1797 else:
1798 d.addCallback(self._on_data_post, request)
1799 # by default, POST follow normal behaviour after on_data_post is called
1800 # this can be changed by a redirection or other method call in on_data_post
1801
1753 if self.prepare_render: 1802 if self.prepare_render:
1754 d.addCallback(self._prepare_render, request) 1803 d.addCallback(self._prepare_render, request)
1755 1804
1756 if self.template: 1805 if self.template:
1757 d.addCallback(self._render_template, request.template_data) 1806 d.addCallback(self._render_template, request.template_data)
1762 d.addErrback(self._renderEb, request) 1811 d.addErrback(self._renderEb, request)
1763 d.callback(self) 1812 d.callback(self)
1764 return server.NOT_DONE_YET 1813 return server.NOT_DONE_YET
1765 1814
1766 def render_GET(self, request): 1815 def render_GET(self, request):
1816 return self.renderPage(request)
1817
1818 def render_POST(self, request):
1767 return self.renderPage(request) 1819 return self.renderPage(request)
1768 1820
1769 1821
1770 class Libervia(service.Service): 1822 class Libervia(service.Service):
1771 1823